Addressed the requests in issue #1285

`getfieldInfo` can now also take a source index as argument. Plus it was modified to also handle "telem1+" etc.
New functions `getSourceIndex(sourceName)` and `getSourceName(sourceIndex)` were added, which use the names shown on the
screen instead of the special names table used by `getFieldInfo` and `getValue`.
Indices are the same for all of the functions, so `getValue(sourceIndex)` also works with indices from `getSourceIndex`.
New iterator functions `sources([first[, last]])` and `switches([first[, last]])` for getting ranges of sources and switches.
`getPhysicalSwitches` was removed, as I consider the iterator function to be a better solution.
This commit is contained in:
jfrickmann
2022-01-04 09:51:47 +10:00
committed by Peter Feerick
parent 351643b652
commit f2a360c9d3
2 changed files with 255 additions and 37 deletions
+253 -37
View File
@@ -327,6 +327,8 @@ void luaGetValueAndPush(lua_State* L, int src)
*/
bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags)
{
strncpy(field.name, name, sizeof(field.name) - 1);
field.name[sizeof(field.name) - 1] = '\0';
// TODO better search method (binary lookup)
for (unsigned int n=0; n<DIM(luaSingleFields); ++n) {
if (!strcmp(name, luaSingleFields[n].name)) {
@@ -349,20 +351,25 @@ bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags)
unsigned int fieldLen = strlen(fieldName);
if (!strncmp(name, fieldName, fieldLen)) {
unsigned int index;
if (len == fieldLen+1 && isdigit(name[fieldLen])) {
index = name[fieldLen] - '1';
}
else if (len == fieldLen+2 && isdigit(name[fieldLen]) && isdigit(name[fieldLen+1])) {
index = 10 * (name[fieldLen] - '0') + (name[fieldLen+1] - '1');
if (len >= fieldLen + 1 && isdigit(name[fieldLen])) {
index = name[fieldLen] - '0';
if (len >= fieldLen + 2 && isdigit(name[fieldLen + 1])) {
index = 10 * index + (name[fieldLen + 1] - '0');
}
index -= 1;
}
else {
continue;
}
if (index < luaMultipleFields[n].count) {
if(luaMultipleFields[n].id == MIXSRC_FIRST_TELEM)
field.id = luaMultipleFields[n].id + index*3;
else
field.id = luaMultipleFields[n].id + index;
if(luaMultipleFields[n].id == MIXSRC_FIRST_TELEM) {
index *= 3;
if (name[len - 1] == '-')
index += 1;
else if (name[len - 1] == '+')
index += 2;
}
field.id = luaMultipleFields[n].id + index;
if (flags & FIND_FIELD_DESC) {
snprintf(field.desc, sizeof(field.desc)-1, luaMultipleFields[n].desc, index+1);
field.desc[sizeof(field.desc)-1] = '\0';
@@ -402,6 +409,73 @@ bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags)
return false; // not found
}
// Return field data for a given field id
bool luaFindFieldById(int id, LuaField & field, unsigned int flags)
{
field.id = id;
field.name[sizeof(field.name) - 1] = '\0';
field.desc[0] = '\0';
// TODO better search method (binary lookup)
for (unsigned int n = 0; n < DIM(luaSingleFields); ++n) {
if (id == luaSingleFields[n].id) {
strncpy(field.name, luaSingleFields[n].name, sizeof(field.name) - 1);
if (flags & FIND_FIELD_DESC) {
strncpy(field.desc, luaSingleFields[n].desc, sizeof(field.desc) - 1);
field.desc[sizeof(field.desc) - 1] = '\0';
}
return true;
}
}
// search in multiples
for (unsigned int n = 0; n < DIM(luaMultipleFields); ++n) {
int index = id - luaMultipleFields[n].id;
if (0 <= index && index < luaMultipleFields[n].count) {
int index2 = 0;
if(luaMultipleFields[n].id == MIXSRC_FIRST_TELEM) {
index2 = index % 3;
index /= 3;
}
switch (index2) {
case 0:
snprintf(field.name, sizeof(field.name), "%s%i", luaMultipleFields[n].name, index + 1);
break;
case 1:
snprintf(field.name, sizeof(field.name), "%s%i-", luaMultipleFields[n].name, index + 1);
break;
case 2:
snprintf(field.name, sizeof(field.name), "%s%i+", luaMultipleFields[n].name, index + 1);
}
if (flags & FIND_FIELD_DESC)
snprintf(field.desc, sizeof(field.desc), luaMultipleFields[n].desc, index + 1);
return true;
}
}
// search in telemetry
for (int i = 0; i < MAX_TELEMETRY_SENSORS; i++) {
if (isTelemetryFieldAvailable(i)) {
int index = id - (MIXSRC_FIRST_TELEM + 3 * i);
if (0 <= index && index < 3) {
const char* sensorName = g_model.telemetrySensors[i].label;
switch (index) {
case 0:
snprintf(field.name, sizeof(field.name), "%s", sensorName);
break;
case 1:
snprintf(field.name, sizeof(field.name), "%s-", sensorName);
break;
case 2:
snprintf(field.name, sizeof(field.name), "%s+", sensorName);
}
}
}
}
return false; // not found
}
/*luadoc
@function getRotEncSpeed()
@@ -739,7 +813,7 @@ static int luaCrossfireTelemetryPush(lua_State * L)
#endif
/*luadoc
@function getFieldInfo(name)
@function getFieldInfo(source)
Return detailed information about field (source)
@@ -752,7 +826,7 @@ The list of valid sources is available:
| 2.2 | [X9D and X9D+](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x9d.txt), [X9E](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x9e.txt), [Horus](http://downloads.open-tx.org/2.2/release/firmware/lua_fields_x12s.txt) |
| 2.3 | [X9D and X9D+](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x9d.txt), [X9E](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x9e.txt), [X7](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x7.txt), [Horus](http://downloads.open-tx.org/2.3/release/firmware/lua_fields_x12s.txt) |
@param name (string) name of the field
@param source can be an index (number) (which was obtained by `getFieldInfo` or `getSourceIndex`) or a name (string) of the source.
@retval table information about requested field, table elements:
* `id` (number) field identifier
@@ -766,13 +840,18 @@ The list of valid sources is available:
*/
static int luaGetFieldInfo(lua_State * L)
{
const char * what = luaL_checkstring(L, 1);
bool found;
LuaField field;
bool found = luaFindFieldByName(what, field, FIND_FIELD_DESC);
if (lua_isnumber(L, 1))
found = luaFindFieldById(luaL_checkinteger(L, 1), field, FIND_FIELD_DESC);
else
found = luaFindFieldByName(luaL_checkstring(L, 1), field, FIND_FIELD_DESC);
if (found) {
lua_newtable(L);
lua_pushtableinteger(L, "id", field.id);
lua_pushtablestring(L, "name", what);
lua_pushtablestring(L, "name", field.name);
lua_pushtablestring(L, "desc", field.desc);
if (field.id >= MIXSRC_FIRST_TELEM && field.id <= MIXSRC_LAST_TELEM) {
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[(int)((field.id-MIXSRC_FIRST_TELEM)/3)];
@@ -806,8 +885,7 @@ To get a telemetry value simply use it's sensor name. For example:
* to get the current altitude use the source "Alt"
* to get the minimum altitude use the source "Alt-", to get the maximum use "Alt+"
@param source can be an identifier (number) (which was obtained by the getFieldInfo())
or a name (string) of the source.
@param source can be an index (number) (which was obtained by `getFieldInfo` or `getSourceIndex`) or a name (string) of the source.
@retval value current source value (number). Zero is returned for:
* non-existing sources
@@ -1998,39 +2076,174 @@ static int luaGetSwitchValue(lua_State * L)
}
/*luadoc
@function getPhysicalSwitches()
@function switches([first[, last]])
@retval switches: table in the format `{{switchName, switchIndex}, ...}`
@param first: the first switch index. If `nil` or omitted, the first available switch is used.
Returns a list of physical switch positions.
@param last: the last switch index. If `nil` or omitted, the last available switch is used.
@status current Introduced in 2.6
This is an iterator function over switch positions. `for switchIndex, switchName in switches() do ...` will iterate over all available switch positions.
@status current Introduced in 2.7
*/
static int luaGetPhysicalSwitches(lua_State * L)
static int luaNextSwitch(lua_State * L)
{
int i = 1;
lua_newtable(L);
for (swsrc_t idx = 1 - SWSRC_FIRST_TRIM; idx < SWSRC_FIRST_TRIM; idx++) {
if (idx != SWSRC_NONE && isSwitchAvailableInLogicalSwitches(idx)) {
swsrc_t last = luaL_checkinteger(L, 1);
swsrc_t idx = luaL_checkinteger(L, 2);
while (++idx <= last) {
if (isSwitchAvailableInLogicalSwitches(idx)) {
char* name = getSwitchPositionName(idx);
lua_pushinteger(L, i++);
lua_createtable (L, 2, 0);
lua_pushinteger(L, 1);
lua_pushstring(L, name);
lua_settable(L, -3);
lua_pushinteger(L, 2);
lua_pushinteger(L, idx);
lua_settable(L, -3);
lua_settable(L, -3);
lua_pushstring(L, name);
return 2;
}
}
lua_pushnil(L);
return 1;
}
static int luaSwitches(lua_State * L)
{
swsrc_t first;
swsrc_t last;
if (lua_isnumber(L, 1)) {
first = luaL_checkinteger(L, 1) - 1;
if (first < SWSRC_FIRST - 1)
first = SWSRC_FIRST - 1;
} else
first = SWSRC_FIRST - 1;
if (lua_isnumber(L, 2)) {
last = luaL_checkinteger(L, 2);
if (last > SWSRC_LAST)
last = SWSRC_LAST;
} else
last = SWSRC_LAST;
lua_pushcfunction(L, luaNextSwitch);
lua_pushinteger(L, last);
lua_pushinteger(L, first);
return 3;
}
/*luadoc
@function getSourceIndex(sourceName)
@param sourceName: string naming a value source as it is shown on radio menus where you can select it. Notice that many names have special characters in them.
@retval sourceIndex: integer. The source index, which can be used as input for `getSourceName(sourceIndex)`, `getValue(sourceIndex)`, and `getFieldInfo(sourceIndex)`.
@notice the source names shown on the screen are not the same as the names used by `getFieldInfo` and `getValue`. But the indices are the same, so `getValue(index)` will work with the indices obtained here.
This function is rather time consuming, and should not be used repeatedly in a script, if it can be avoided.
@status current Introduced in 2.7
*/
static int luaGetSourceIndex(lua_State * L)
{
const char * name = luaL_checkstring(L, 1);
bool found = false;
mixsrc_t idx;
for (idx = MIXSRC_NONE; idx <= MIXSRC_LAST_TELEM; idx++) {
if (isSourceAvailable(idx)) {
char* s = getSourceString(idx);
if (!strncasecmp(s, name, 31)) {
found = true;
break;
}
}
}
if (found)
lua_pushinteger(L, idx);
else
lua_pushnil(L);
return 1;
}
/*luadoc
@function getSourceName(sourceIndex)
@param sourceIndex: integer identifying a value source as returned by `getSourceIndex(sourceName)` or the `id` field in the table returned by `getFieldInfo`.
@retval sourceName: string naming the value source as it is shown on radio menus where a source can be chosen.
@notice the source names shown on the screen are not the same as the names used by `getFieldInfo` and `getValue`. But the indices are the same, so `getValue(index)` will work with the indices used here.
@status current Introduced in 2.7
*/
static int luaGetSourceName(lua_State * L)
{
mixsrc_t idx = luaL_checkinteger(L, 1);
if (idx <= MIXSRC_LAST_TELEM && isSourceAvailable(idx)) {
char* name = getSourceString(idx);
lua_pushstring(L, name);
}
else
lua_pushnil(L);
return 1;
}
/*luadoc
@function sources([first[, last]])
@param first: the first source index. If `nil` or omitted, the first available source is used.
@param last: the last soure index. If `nil` or omitted, the last available source is used.
This is an iterator function over value sources. `for sourceIndex, sourceName in sources() do ...` will iterate over all available value sources.
@status current Introduced in 2.7
*/
static int luaNextSource(lua_State * L)
{
mixsrc_t last = luaL_checkinteger(L, 1);
mixsrc_t idx = luaL_checkinteger(L, 2);
while (++idx <= last) {
if (isSourceAvailable(idx)) {
char* name = getSourceString(idx);
lua_pushinteger(L, idx);
lua_pushstring(L, name);
return 2;
}
}
lua_pushnil(L);
return 1;
}
static int luaSources(lua_State * L)
{
mixsrc_t first;
mixsrc_t last;
if (lua_isnumber(L, 1))
first = luaL_checkinteger(L, 1) - 1;
else
first = MIXSRC_NONE - 1;
if (lua_isnumber(L, 2)) {
last = luaL_checkinteger(L, 2);
if (last > INPUTSRC_LAST)
last = INPUTSRC_LAST;
} else
last = INPUTSRC_LAST;
lua_pushcfunction(L, luaNextSource);
lua_pushinteger(L, last);
lua_pushinteger(L, first);
return 3;
}
const luaL_Reg opentxLib[] = {
{ "getTime", luaGetTime },
{ "getDateTime", luaGetDateTime },
@@ -2095,7 +2308,10 @@ const luaL_Reg opentxLib[] = {
{ "getSwitchIndex", luaGetSwitchIndex },
{ "getSwitchName", luaGetSwitchName },
{ "getSwitchValue", luaGetSwitchValue },
{ "getPhysicalSwitches", luaGetPhysicalSwitches },
{ "switches", luaSwitches },
{ "getSourceIndex", luaGetSourceIndex },
{ "getSourceName", luaGetSourceName },
{ "sources", luaSources },
{ nullptr, nullptr } /* sentinel */
};
+2
View File
@@ -208,10 +208,12 @@ extern uint8_t instructionsPercent;
struct LuaField {
uint16_t id;
char name[20];
char desc[50];
};
bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags=0);
bool luaFindFieldById(int id, LuaField & field, unsigned int flags=0);
void luaLoadThemes();
void luaRegisterLibraries(lua_State * L);
void registerBitmapClass(lua_State * L);