Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 172 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

2.6

Loading...

Loading...

Loading...

Loading...

Part I - Script Type Overview

This section introduces the types of Lua scripts supported by EdgeTX and how they may be used.

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

io Library

Loading...

Loading...

io.read()

io.write()

io.seek()

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Model Functions

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

EdgeTX 2.6 Lua Reference Guide

This guide covers the development of user-written scripts for R/C transmitters running the EdgeTX 2.6 operating system with Lua support. Readers should be familiar with EdgeTX, the EdgeTX Companion, and know how to transfer files the SD card in the transmitter.

Part I of the guide shows how to enable Lua support for Taranis and includes basic examples of each types of script.

Part II is a programming guide that introduces the types of EdgeTX Lua scripts and how to use them.

Part III is the EdgeTX Lua API Reference

Part IV covers advanced topics with examples

The latest version of this guide will always be available . At the top of the left sidebar there is a version option if you are running an older version of EdgeTX and need the docs for that specific version.

Please feel free to make suggestions or corrections to the documentation on GitHub, but the preferred method of editing is to use , so all changes will need to be made by someone who is authorized as a writer there.

Join the chat on Discord
here
GitBook

Custom (Mixer) Scripts

WARNING - Do not use Lua Custom scripts for controlling any aspect of your model that could cause a crash if the script stops executing!

Overview

Each model can have several custom scripts associated with it, and these scripts are run periodically. They behave similarly to standard OpenTX mixers, but at the same time they provide a much more flexible and powerful tool. Custom scripts take one or more values as inputs, do some processing in Lua code, and output one or more values.

Please note: the firmware must be compiled with the option LUA_MIXER=Y for Custom scripts to be available.

Please note: the scripts should be as short as possible, to avoid delays. It is also important to keep in mind that other loaded Telemetry and Function scripts can add to the response time, or worse: hang the system!

Typical uses

  • replacement for complex mixes that are not critical to model function

  • complex processing of inputs and reaction to their current state and/or their history

  • filtering of telemetry values

Limitations

  • cannot update LCD screen or perform user input.

  • should not exceed allowed run-time/ number of instructions.

  • custom scripts are run with less priority than built-in mixes. Their execution period is around 30ms and is not guaranteed!

  • can be disabled/killed anytime due to logic errors in script, not enough free memory, etc...)

Lifetime

  • Custom scripts are loaded from SD card when model is selected

  • init __function is called first

  • run function is called periodically (about 30 times per second)

  • the script is killed (stopped and disabled) if it misbehaves (e.g. run-time error or low memory)

  • all Custom scripts are stopped while a One-Time script is running (see Lua One-time scripts)

Disabled script

If the script output is used as a mixer source , and the script is killed for whatever reason, then the whole mixer line is disabled ! This can be used for example to provide a fallback in case Lua Custom script is killed.

Example where Lua mix script is used to drive ailerons in some clever way, but control falls back to the standard aileron mix if script is killed. Second mixer line replaces the first one when the script is alive:

CH1  [I4]Ail Weight(+100%)
  := LUA4b Weight(+100%)

File Location

Place them on SD card in folder /SCRIPTS/MIXES/. File name length (without extension) must be 6 characters or less (this limit was 8 characters in OpenTX 2.1).

Interface

Every script must include a return statement at the end, defining its interface to EdgeTX. This statement returns a table with the following fields:

  • input table (optional)

  • output table (optional)

  • init function (optional)

  • run function

Example

local input =
  {
    { "Strength", SOURCE},           -- user selects source (typically slider or knob)
    { "Interval", VALUE, 0, 100, 0 } -- interval value, default = 0.
  }

local output = { "Val1", "Val2" }

local function init()
  -- Called once when the script is loaded
end

local function run(Strength, Interval) -- Must match input table
  local v1, v2
  -- Called periodically
  return v1, v2                        -- Must match output table
end

return { input=input, output=output, run=run, init=init }

Input table

The input table defines what values are available as input(s) to custom scripts. There are two forms of input table entries.

{ "<name>", SOURCE }

SOURCE inputs provide the current value of a selected OpenTX variable. The source must be selected by the user when the script is configured. Source can be any value that EdgeTX knows about (inputs, channels, telemetry values, switches, custom functions etc.). Note: the typical input range is -1024 thru +1024. Simply divide the input value by 10.24 to convert to a percentage from -100% to +100%.

{ "<name>", VALUE, <min>, <max>, <default> }

VALUE inputs provide a constant value that is set by the user when the script is configured.

  • name - maximum length of 8 characters

  • min - minimum value of -128

  • max - maximum value of 127

  • default - must be within the valid range specified

  • Maximum of 6 inputs per script (was 8 in 2.1)

Output table

The output table defines only name(s), as the actual values are returned by the script's run function.

{ "<name1>", "<name2>" }

Note: the above names are only visible as source values on the radio screen when the script is running. If the model is edited in Companion, then the values show as LUA1a and LUA1b etc.

Function Scripts

Overview

Function scripts are invoked via the 'Lua Script' option of Special Functions configuration page.

Typical uses of Function scripts are:

  • specialized handling in response to switch position changes

  • customized announcements

Please be aware that:

  • all function scripts are stopped if a One-Time Lua script is running

  • Function scripts DO NOT HAVE ACCESS TO LCD DISPLAY

Lifetime

  • init function is called once when the model is selected

  • depending on the switch associated with the Special Function, either the run function (switch = on) or the background function (switch = off) is called periodically

  • the script is stopped and disabled if it misbehaves (e.g. run-time error or low memory)

File Location

Scripts are located on the SD card in the folder /SCRIPTS/FUNCTIONS/<name>.lua. File name length (without extension) must be 6 characters or less (this limit was 8 characters in OpenTX 2.1).

Interface

Every script must include a return statement at the end, defining its interface to EdgeTX. This statement returns a table with the following fields:

  • init function (optional)

  • run function

  • background function (optional)

Example

local function init()
  -- Called once when the script is loaded
end

local function run()
  -- Called periodically while the Special Function switch is on
end

local function background()
  -- Called periodically while the Special Function switch is off
end

return { run=run, background=background, init=init }

One-Time Scripts

WARNING - Running a One-Time script will suspend execution of all other currently loaded Lua scripts (Custom, Telemetry, and Functions)

Overview

One-Time scripts start when called upon by a specific radio function or when the user selects them from a contextual menu. They do their task and are then terminated and unloaded. Please note that all persistent scripts are halted during the execution of One-Time scripts. They are automatically restarted once the One-Time script is finished. This is done to provide enough system resources to execute the one time script.

Lifetime

Script is executed when user selects Execute on a script file from SD card browser screen.

Script executes until:

  • it returns value different from 0

  • is forcefully closed by user by long press of EXIT key

  • is forcefully closed by system if if it misbehaves (e.g. run-time error or low

    memory)

File Location

Place them anywhere on SD card, the folder /SCRIPTS/ is recommended. The only exception is official model wizard script, that should be put into /SCRIPTS/WIZARD/ folder that way it will start automatically when new model is created.

Interface

Every script must include a return statement at the end, defining its interface to EdgeTX. This statement returns a table with the following fields:

  • init function (optional)

  • run function

Example

local function init()
  -- init is called once when model is loaded
end

local function run(event)
  -- run is called periodically only when screen is visible
  -- A non-zero return value will halt the script
  return x
end

return { run=run, init=init }

Notes:

  • A non-zero return value from run will halt the script.

Getting Started

Downloading EdgeTX Companion

Updating firmware with Lua option selected

If you intend to use mixer scripts, when updating the firmware on your transmitter you need to make sure the lua option is checked in the settings for your radio profile (Main menu -> Settings ->Settings...) as shown below. This is not required if you only intend to run telemetry, one-time and function scripts, support for those is included by default.

Also note that the SD Structure path should contain a valid path to a copy of your transmitter's SD card contents, although that's not specific to Lua.

Widget Scripts

Overview

Most of the time, widget scripts show some info in a zone either in the top bar or in one of the user defined main views, and they cannot receive direct input from the user via key events like e.g. Telemetry scripts.

But widgets on the main views can also be shown in full screen mode, where they take over the entire screen area. And here they receive user input via key events, and for radios with touch screen, also touch events. Full screen mode can be entered by selecting the widget, pressing ENTER and selecting Full screen on the widget menu, or by double tapping the widget on radios with a touch screen. Full screen mode can be exited by long pressing the RETURN button, or by calling the Lua function lcd.exitFullScreen().

Each model can have up to five main views, with up to 8 widgets per screen, depending on their size and layout. Each instance of a widget has his own options table.

Please note: Widget scripts are only available on radios with color screens, e.g. FrSky Horus models, Radiomaster TX16 and Jumper T16.

Lifetime

All widget scripts on the SD card are loaded into memory when the model is selected; even widgets that are not used. This has the side effect that any global functions defined in a widget script will always be available to other widget scripts. It also means that any script on the SD card will consume part of the radio's memory - even if it is not being used. Therefore, it is important to either keep widget scripts small, or to use Lua's loadScript() function to load code dynamically.

They can be added to the top bar or a main view through the telemetry setup menu. When a widget has been added to a screen, then the widget functions are called as follows:

  • create is called once when the widget instance is registered (started).

  • update is called when widget settings are changed by the user.

  • background is called periodically when the widget instance is not visible. Note: this is different from the way that telemetry scripts are handled.

  • refresh is called periodically when the widget instance is visible. Note: if you want background to run when the widget is visible, then call it from refresh.

  • A widget script is stopped and disabled if it misbehaves (e.g. too long runtime, run-time error, or low memory)

File Location

Widgets are located on the SD card, each in their specific folder /WIDGETS/<name>/main.lua (<name> must be in 8 characters or less).

Interface

Every script must include a return statement at the end, defining its interface to EdgeTX. This statement returns a table with the following fields:

  • name string

  • options table

  • create function

  • update function

  • background function (optional)

  • refresh function

Example

local name = "WidgetName"

-- Create a table with default options
-- Options can be changed by the user from the Widget Settings menu
-- Notice that each line is a table inside { }
local options = {
  { "Source", SOURCE, 1 },
  -- BOOL is actually not a boolean, but toggles between 0 and 1
  { "Boolean", BOOL, 1 },
  { "Value", VALUE, 1, 0, 10},
  { "Color", COLOR, ORANGE },
  { "Text", STRING, "Max8chrs" }
}

local function create(zone, options)
  -- Runs one time when the widget instance is registered
  -- Store zone and options in the widget table for later use
  local widget = {
    zone = zone,
    options = options
  }
  -- Add local variables to the widget table,
  -- unless you want to share with other instances!
  widget.someVariable = 3
  -- Return widget table to EdgeTX
  return widget
end

local function update(widget, options)
  -- Runs if options are changed from the Widget Settings menu
  widget.options = options
end

local function background(widget)
  -- Runs periodically only when widget instance is not visible
end

local function refresh(widget, event, touchState)
  -- Runs periodically only when widget instance is visible
  -- If full screen, then event is 0 or event value, otherwise nil
end

return {
  name = name,
  options = options,
  create = create,
  update = update,
  refresh = refresh,
  background = background
}

Notes

  • The name must be max. 10 characters long.

  • options is passed to create and then stored in Lua. Changing it has no effect on EdgeTX.

  • If options is changed by the user in the Widget Settings menu, then update will be called with a new options table, unaffected by any changes made by Lua code to the old options table.

  • Maximum five options are allowed, with names of max. 10 characters, and no spaces.

  • If local variables are declared outside functions in the widget script, then they are shared between all instances of the widget.

  • Therefore, local variables that are private for each instance should be added to the widget table in the create function before returning the widget table to EdgeTX.

  • When the widget is not in full screen mode, then both event and touchState are nil.

  • The size of the widget's screen area is as follows:

    • Full screen mode: LCD_W by LCD_H

    • Not full screen mode: zone.w by zone.h

Loading Code Modules Dynamically

Lua makes it easy to load and unload code modules on the fly, to save memory or to provide program extensions.

You can load and use the above file with the following code:

So here we put together what we learned in the previous section. The body of the script is an anonymous function returned by loadScript and stored in the variable chunk. It returns the function f when it is called. The local variable c in the script is assigned to the first vararg passed to the call. Since a new closure is created every time we call chunk, f1 and f2 have different closures with different values of c.

The event parameter indicates which transmitter key has been pressed (see ).

EdgeTX Companion 2.6 is (pick the version for your operating system from Assets heading at the bottom of the page - filename will have cpn as part of the name).

Edit Settings dialog from EdgeTX Companion

All widgets are stopped while a One-Time script is running (see ).

When the widget is in full screen mode, then event is either 0, a , or a .

If event is a , then touchState is a table. Otherwise, it is nil.

The function will load a script from a the file and return a function that is the body of the script, as described in the previous section. So you could have the following Lua script file saved on the SD card:

Key Events
available for download here
One-Time scripts
key event value
touch event value
touch event value
-- /SCRIPTS/TestScript.lua
local c = ...

local function f(x)
  return x + c
end

return f
local chunk = loadScript("/SCRIPTS/TestScript.lua")

local f1 = chunk(1)
local y = f1(5)
-- y = 5 + 1

local f2 = chunk(3)
local z = f2(5)
-- z = 5 + 3
loadScript(<file>)

Using Key and Touch Events

This section will discuss how interactive scripts receiving user inputs via key and touch events can be created.

The two Lua widgets EventDemo and LibGUI are provided on the SD card content for color screen radios. EventDemo is just a small widget showing off how key, and especially touch events, can be used. LibGUI contains a globally available library, and a widget showing how the library can be used by other widgets. This section will discuss these two widgets for color screen radios, but generally, what is stated about key events here also applies to the run function in Telemetry and One-Time scripts.

EventDemo Widget

LibGUI

This is a widget that comes with a global library. Since all widgets are loaded whether or not they are being used, global functions declared in the body of a widget script will always be available. It is not necessary to setup the widget to use the library, and the only purpose of the widget is to show how LibGUI can be used to create apps.

The global function loadGUI() returns a new libGUI object. This object can be used to create new GUIobjects, which are used to create screens with elements like buttons, menus, labels, numbers that can be edited, and timers.

libGUI Properties

libGUI has the following properties controlling general settings for the library.

libGUI.flags

These are default drawing flags to be applied if no flags are given at creation of screen elements.

Note: these flags should not contain color values, as colors are added by the following.

libGUI.colors

This is a table of the colors used for drawing the GUI elements. These are all theme colors by default, but they can be changed for the libGUI instance without changing the theme colors anywhere else.

libGUI.widgetRefresh

A function f() to draw the zone of the screen in widget mode. It takes no arguments.

libGUI Functions

libGUI.match(x, ...)

This is a small utility function that returns true if the first argument x matches any of the following arguments. It is useful for comparing values of event, e.g. if we want to test if the user pressed either of the following buttons, we can use:libGUI.match(event, EVT_VIRTUAL_ENTER, EVT_VIRTUAL_EXIT, EVT_VIRTUAL_MENU)

libGUI.newGUI()

This is the main function that creates a new GUI object. If an application has different screens, then a GUI object is created for each screen.

GUI Object Properties

GUI.fullScreenRefresh

A function f(event, touchState) to draw the screen background in full screen mode. The GUI elements are drawn afterwards on top.

GUI.prompt

A GUI (or another table with a function run(event, touchState). When this is set, the GUI will first be drawn, and then it will call prompt.run(event, touchState) instead of running itself. That way, the prompt can implement a modal prompt window.

GUI Object Functions

GUI.run(event, touchState)

Redraws the screen and processes key and touch events. It can directly replace a widget's refresh function, or it can be called by refresh.

GUI.SetEventHandler(event, f)

Sets a function f(event, touchState) to handle an event. If no GUI element is being edited, then this can trap events before they are passed to the GUI, e.g. to press EXIT to go back to the previous screen. If f is nil, then the event handler is removed.

GUI Screen Elements

The screen elements are drawn in the order that they are added to the GUI, and touch events are sent to the first element that covers the touched point of the screen. GUI elements therefore should never overlap.

There are some common properties that can be set for all or most of the GUI elements.

  • element.disabled = true prevents the element from taking focus and receiving events, and disabled buttons are greyed out.

  • element.hidden = true in addition to the above, the element is not drawn.

  • element.title can be changed for elements with a title.

  • element.value can be changed for elements with a value.

  • element.flags drawing flags for the element's text. If no flags were given at element creation, it defaults to GUI.flags.

  • elements.blink will make non-button elements blink

  • elements.invers will make non-button elements draw in inversed colors.

The various screen elements are added to the GUI with the functions described below. The functions all add the element to the GUI and returns a reference so the element subsequently can be accessed by the client.

GUI.button (x, y, w, h, title[, callBack] [, flags])

Add a button to the GUI.

When tapped, it calls callBack(self) so a call back function can tell which button activated it.

GUI.toggleButton(x, y, w, h, title, value[, callBack] [, flags])

Add a toggle button to the GUI.

The value is either true or false.

When tapped, it calls callBack(self) so a call back function can tell which toggle button activated it, and what self.value is.

GUI.number(x, y, w, h, value[, callBack] [, flags])

Add an editable number to the GUI.

The value can be either a number or text. By setting the value to a text, it can be shown that the number is not present e.g. by "- -" or similar.

When tapped, the number will go to edit mode. In edit mode, events are passed to callBack(self, event, touchState). Thereby, the call back function can use events to edit the number, e.g. sliding a finger up and down can increase and decrease the value. You can look in the LibGUI widget's loadable file for an example of this.

GUI.timer(x, y, w, h, tmr[, callBack] [, flags])

Add a timer to the GUI.

If no value is present, then the model timer tmr will be shown. If value is a number, then it indicates the time in seconds, and it will be shown as MM:SS. The value can also be text, e.g. "- - : - -" to show that the timer is disabled.

When tapped, the timer will go to edit mode, as described above for number.

GUI.label(x, y, w, h, title[, flags])

Add a text label to the GUI.

The label does not respond to any events, but its title and flags can be changed.

GUI.menu(x, y, visibleCount, items[, callBack] [, flags])

Add a scrollable menu to the GUI. This function returns a table with each of the menu's line elements.

visibleCount is the number of visible menu items.

items is a table with the menu item texts.

When a menu item is tapped, it calls callBack(self). Each menu element has a field self.idx giving the index in the menu, and this can be used by callBack to see which menu item was selected.

Notice that the menu's width is decided by the item texts and the font flags, and the height is decided by visibleCount and the font flags.

GUI.dropDown(x, y, w, h, items, selected, callBack, flags)

Add a field with values that can be selected on a drop down menu.

items is a table with the items that can be selected from.

selected is the index of the initially selected item.

When an item has been selected, it calls callBack(self). The index of the selected item is given by self.selected.

GUI.gui.horizontalSlider(x, y, w, value, min, max, delta, callBack)

Adds a horizontal slider that starts at (x, y) and has the width w.

value is the initial value, and min - max is the interval of values that can be selected with step size delta.

When the value is changed, callBack(self) is called, and the value is given by self.value.

GUI.gui.verticalSlider(x, y, w, value, min, max, delta, callBack)

The same as the above, just vertical.

This widget uses the design pattern for saving memory by loadable files discussed in the so all of the action takes place in the file loadable.lua. The following code listing is an outline of the refresh function with comments explaining what is going on.

The library is implemented in the /WIDGETS/LibGUI/libgui.lua. The widget that demonstrates how to use the library is implemented in the /WIDGETS/LibGUI/loadable.lua. The file /WIDGETS/LibGUI/main.lua contains a global function that loads the library and the standard functions needed for a widget.

Color
Default value
Used for
-- This code chunk is loaded on demand by the widget's main script 
-- when the create(...) function is run. Hence, the body of this 
-- file is executed by the widget's create(...) function.

-- zone and options were passed as arguments to chunk(...)
local zone, options = ...
-- The widget table will be returned to the main script
local widget = { }

function widget.refresh(event, touchState)
  if event == nil then -- Widget mode
    -- Draw in widget mode. The size equals zone.w by zone.h
  else -- Full screen mode
    -- Draw in full screen mode. The size equals LCD_W by LCD_H
    if event ~= 0 then -- Do we have an event?
      if touchState then -- Only touch events come with a touchState
        if event == EVT_TOUCH_FIRST then
          -- When the finger first hits the screen
        elseif event == EVT_TOUCH_BREAK then
          -- When the finger leaves the screen and did not slide on it
        elseif event == EVT_TOUCH_TAP then
          -- A short tap gives TAP instead of BREAK
          -- touchState.tapCount shows number of taps
        elseif event == EVT_TOUCH_SLIDE then
          -- Sliding the finger gives a SLIDE instead of BREAK or TAP
          if touchState.swipeRight then
            -- Is true if user swiped right
          elseif touchState.swipeLeft then
          elseif touchState.swipeUp then
          elseif touchState.swipeDown then
            -- etc.
          else
            -- Sliding but not swiping
          end
        end
      else -- event ~= 0 and touchState == nil: key event
        if event == EVT_VIRTUAL_ENTER then
          -- User hit ENTER
        elseif event == EVT_VIRTUAL_EXIT then
          -- etc.
        end
      end
    end    
  end
end

primary1

COLOR_THEME_PRIMARY1

Text on dropDown menu

primary2

COLOR_THEME_PRIMARY2

Text on buttons and numbers/timers being edited

primary3

COLOR_THEME_PRIMARY3

Text on labels, menus, and numbers/timers

focus

COLOR_THEME_FOCUS

Background on buttons and numbers/timers being edited.

edit

COLOR_THEME_EDIT

Background when a value is being edited.

active

COLOR_THEME_ACTIVE

Background on active toggle buttons and the border around selected elements.

Acknowledgments

The EdgeTX team has no intention of making a profit from their work. EdgeTX is free and open source and will remain free and open source. But EdgeTX is more expensive to maintain than most open source projects. The reason is that there is a never ending flood of hardware to integrate and maintain code for. Hardware that costs.

previous section,
loadable file
loadable file

Part III - EdgeTX Lua API Reference

This section describes the Lua libraries, functions and constants that are provided by EdgeTX.

Saving Memory

This chapter will show you some ways that large script projects can be fitted into the limited memory of our radios.

Regarding memory, the situation is a bit different for the radios with black/white or grey scale screens and telemetry scripts, and the radios with color screens and widget scripts. The telemetry script radios only have 128-192 KB RAM memory - that is very small! The widget script radios have 8 MB RAM memory. But the way that widgets are designed means that all widget scripts present on the SD card will be loaded into memory, whether or not they are actually used. Therefore, different strategies should be applied to save memory for the two different types of radios and scripts.

Telemetry Script Radios

Radios with black/white or grey scale screens and telemetry scripts such as e.g. FrSky Taranis, Xlite, Jumper T12 and Radiomaster TX16 have extremely small RAM memories, and therefore it may be necessary to divide up your script into smaller loadable modules.

The following simple example demonstrates how different screens can be loaded on demand, and how shared data can be stored in a table.

-- Main telemetry script

local shared = { }
shared.screens = {
  "/SCRIPTS/Test/menu1.lua",
  "/SCRIPTS/Test/menu2.lua",
  "/SCRIPTS/Test/menu3.lua"
}

function shared.changeScreen(delta)
  shared.current = shared.current + delta
  if shared.current > #shared.screens then
    shared.current = 1
  elseif shared.current < 1 then
    shared.current = #shared.screens
  end
  local chunk = loadScript(shared.screens[shared.current])
  chunk(shared)
end

local function init()
  shared.current = 1
  shared.changeScreen(0)
end

local function run(event)
  shared.run(event)
end

return { run = run, init = init }
-- /SCRIPTS/Test/menu1.lua

local shared = ...

function shared.run(event)
  lcd.clear()
  lcd.drawText(20, 10, "Screen 1", MIDSIZE)
  
  if event == EVT_VIRTUAL_NEXT then
    shared.changeScreen(1)
  elseif event == EVT_VIRTUAL_PREV then
    shared.changeScreen(-1)
  end
end
-- /SCRIPTS/Test/menu2.lua

local shared = ...

function shared.run(event)
  lcd.clear()
  lcd.drawText(20, 10, "Screen 2", MIDSIZE)
  
  if event == EVT_VIRTUAL_NEXT then
    shared.changeScreen(1)
  elseif event == EVT_VIRTUAL_PREV then
    shared.changeScreen(-1)
  end
end
-- /SCRIPTS/Test/menu3.lua

local shared = ...

function shared.run(event)
  lcd.clear()
  lcd.drawText(20, 10, "Screen 3", MIDSIZE)
  
  if event == EVT_VIRTUAL_NEXT then
    shared.changeScreen(1)
  elseif event == EVT_VIRTUAL_PREV then
    shared.changeScreen(-1)
  end
end

The table shared contains data that is shared between the main telemetry script and the loadable screens. Notice that the functions shared.changeScreen and shared.run are also shared this way.

Code is loaded by shared.changeScreen with the loadScript function, which returns the loadable script as a chunk of code. The code is executed with shared as the argument, and the loadable script adds a new run function to the shared table. shared.run is called by run in the main script.

Widget Script Radios

Radios with color screens and widget scripts such as e.g. FrSky Horus, Jumper T16 and Radiomaster TX16 have fairly large RAM memories, but since all widget scripts present on the SD card are always loaded into memory, they could run out of memory if many big widget scripts are present on the card - even if they are not being used by the selected model. Therefore, large widget scripts should be divided into a small main script and a large loadable part. One way to accomplish this is the following.

-- main.lua
local name = "<widget name>"

local function create(zone, options)
  -- Loadable code is called immediately and returns a widget table
  return loadScript("/WIDGETS/" .. name .. "/loadable.lua")(zone, options)
end

local function refresh(widget, event, touchState)
  widget.refresh(event, touchState)
end

local options = {
  -- default options here
}

local function update(widget, options)
  widget.update(options)
end

local function background(widget)
  widget.background()
end

return {
  name = name, 
  create = create, 
  refresh = refresh, 
  options = options, 
  update = update, 
  background = background
}
-- loadable.lua
local zone, options = ...

-- The widget table will be returned to the main script.
local widget = { }

function widget.refresh(event, touchState)
  -- refresh code here
end

function widget.update(opt)
  options = opt
  -- update code here
end

function widget.background()
  -- background code here
end

-- Return to the create(...) function in the main script
return widget

Obviously, the bulk of the widget's code goes in loadable.lua, and is only loaded if the widgets is in fact being used. Therefore, if the widget is not used, only the small amount of code in main.lua is loaded into the radio's memory.

For an example of a widget that uses the above design pattern, please have a look at the EventDemo widget that is included on the SD card with EdgeTX for color screen radios.

The create function loads the file loadable.lua in the folder /WIDGETS/<widget name>/, and calls it immediately as described in . It passes zone and options as arguments to loadable.lua. This scripts adds the functions refresh, update and (optionally) background to the widget table:

zone and options are stored in the of loadable.lua, therefore they do not need to be added to the widget table, as is commonly done.

the previous section

io.open(filename [, mode])

This function opens a file, in the mode specified in the string mode. It returns a new file handle, or, in case of errors, nil plus an error message.

The mode string can be any of the following:

  • "r": read mode (the default)

  • "w": write mode

  • "a": append mode

Part II - EdgeTX Lua API Programming Guide

This section provides more specifics on the EdgeTX Lua implementation. Here you will find syntax rules for interface tables and functions.

Data Exchange with the EdgeTX Model Setup

An EdgeTX model has several data components that can be exchanged with Lua scripts. This section gives an overview.

In general terms, there are two different types of data that can be exchanged with EdgeTX:

  • Values, which generally fall on a scale between -1024 and 1024, also sometimes reported as -100% to 100%, e.g. for mixer values and channel outputs.

  • Switches, which are either true or false.

Global Variables is a value data source that can return a value between -1024 and 1024. Examples of value sources are:

  • Global Variables

  • Sticks, sliders and knobs

  • Trim values

  • Input lines

  • Channel outputs

  • Trainer channel inputs

  • Telemetry sensors

  • Logical switches

  • Switch positions, testing if a physical switch is in a particular position, e.g. SA↑.

  • Trim buttons

  • Transmitter and telemetry activity

It can be very confusing that some source can be read both as a value and as a switch. As an example, elevator trim can be read as the current value of the trim:

local id = getFieldInfo("trim-ele")
local eleTrim = getValue(id)

Or it can be read as the current value of the trim button position:

local idUp = getSwitchIndex(CHAR_TRIM .. "Eu")
local idDown = getSwitchIndex(CHAR_TRIM .. "Ed")
local eleUp = getSwitchValue(idUp)
local eleDown = getSwitchValue(idDown)

These are really two different things, as the elevator trim is an internal value stored by the radio, which is changed with the trim button, and the button is a physical button.

But it can also be a more direct comparison, e.g. the 3-position switch B, which can be read as a value source with:

local idB = getFieldInfo("sb")
local swBvalue = getValue(idB) -- a value of -1024, 0 or 1024

Or the current position of switch B can be read with:

local idBup = getSwitchIndex("SB" .. CHAR_UP)
local idBdown = getSwitchIndex("SB" .. CHAR_DOWN)
local swBup = getSwitchValue(idBup)
local swBdown = getSwitchValue(idBdown)

Hopefully, these examples illustrated the differences between values and switches, and showed how these can be retrieved in a Lua script.

You can also send data the other way: from Lua to the EdgeTX model setup.

To send a value, use a global variable: model.setGlobalVariable(index, fm, value). If you use the default GV setting, where all other flight modes use the value of FM0, then you can use 0 for fm.

To send a switch, setup a STICKY type logical switch, and then use setStickySwitch(index, true/false). Notice that a blank sticky switch STICKY(---, ---) is ON when the model is first loaded. If you want a sticky switch to be OFF by default then use the value of the switch itself as V1, i.e. L01 = STICKY(L01, ---) will be off by default.

The following table gives an overview of the Lua API functions that can be used to exchange data with the EdgeTX model setup.

Function
Description

getFieldInfo(name)

Gets the meta-index of a value source with name.

getValue(index)

Gets the current value of a source, where index is from the above.

getFlightMode()

Returns the current flight mode number and name. Do not confuse with model.getFlightMode, which is a completely different function!

model.getGlobalVariable( index, fm)

Read the value of a global variable between -1024 and 1024. You can use the above to get the current flioght mode for fm, or you can setup the GV to always use the value from FM0.

model.setGlobalVariable( index, fm, value)

Sets the value of a global variable.

setTelemetryValue(id, subID, instance, value, ...)

This function can send data from Lua to a telemetry sensor. If it is running, then the sensor will show up with Discover Sensors. This can be used to log values generated by Lua.

getLogicalSwitchValue( index)

Get the value of a logical switch.

setStickySwitch(id, value)

Set the value of a STICKY type logical switch.

getSwitchIndex(name)

Get the meta-index of a switch source with name.

getSwitchName(index)

Get the name of a switch source.

getSwitchValue(index)

Get the value of a switch source.

getPhysicalSwitches()

Get a list of physical switches on the radio. Can be used to make a selection list.

getShmVar(index)

Get the value of a shared memory variable. These are little "mail boxes" provided as a way to send data between Lua widgets and other Lua scripts like Mixer and Function scripts.

setShmVar(index, value)

Set the value of a shared memory variable.

model.setTimer(timer, value)

Set the timer to value.

model.getTimer(timer)

Read the timer.

Flags and Pattern Constants

Many of the lcd functions accept parameters named flags and patterns. The names and their meanings are described below.

Flags

Patterns

A specific data source type, e.g. Global Variables, can be indexed directly with an index that starts with 0 for the first one. This can be a little confusing, as e.g. GV1 for FM0 is read with , because GV1 is the first global variable, and FM0 is the first flight mode. But as long as you remember that all direct indices start with 0 for the first one, you should be fine!

There is a way to access a value of any such type with a meta-index. You use the function where name can be any of the valid source names listed . It returns a table with a description of the value source, including the field id, which is the meta-index.

You can use id with the function to read the current value. You can also use name directly, but this is less efficient, as EdgeTX does a linear search for the name every time it is called. Therefore, the procedure of first extracting the meta-index from getFieldInfo(name).id, and then using that, is recommended.

For switches, uses a direct index to read this specific type of switch sources, again using the index 0 for LS1 etc. But there are also several types of switch sources, such as:

You can find the meta-index of a particular switch source with , where name is exactly the name that you see in the radio menus where you can select a switch source.

You can read the current value of a switch source with as a true/false value.

Name
Description
Version
Notes
Name
Description
model.getGlobalVariable(0, 0)
getFieldInfo(name)
here
getValue(id)
getLogicalSwitchValue(index)
getSwitchIndex(name)
getSwitchValue(index)

0

normal font, default precision for numeric

XXLSIZE

jumbo font

2.0.6

DBLSIZE

double size font

MIDSIZE

mid sized font

SMLSIZE

small font

BOLD

bold font

Only color displays. This is a font size on its own - cannot be combined with other font size flags.

SHADOWED

shadow font

Only color displays

INVERS

inverted display

BLINK

blinking text

LEFT

left justify

2.0.6

Default for most functions not related to bitmaps

RIGHT

right justify

CENTER

center justify

Only color displays

VCENTER

center vertically

2.5.0

Only color displays

PREC1

single decimal place

PREC2

two decimal places

GREY_DEFAULT

grey fill

TIMEHOUR

display hours

Only for drawTimer

FORCE

pixels will be black

ERASE

pixels will be white

DOTTED

lines will appear dotted

Touch Event Constants

In addition to the key events described in the previous section, radios with a color touch screen also provide touch events to the widget scripts.

The following touch events are passed in the event argument to the widget script refresh function (when in full screen mode), just like the key events. The following touch events are provided:

Touch Event Name
Description

EVT_TOUCH_FIRST

When the finger touches down on the screen

EVT_TOUCH_TAP

If the finger leaves the screen after a quick tap

EVT_TOUCH_BREAK

If the finger leaves the screen without tap or slide

EVT_TOUCH_SLIDE

Repeats while the finger is sliding on the screen

In addition to the above touch events a touchState table is passed to refresh with the following addional data fields:

touchState fields
Description

x, y

Current touch point

startX, startY

Point where slide started

slideX, SlideY

Movement since previous SLIDE event (or start of slide)

swipeUp / swipeDown / swipeLeft / swipeRight

The field is present and equal to true if a swipe event occurred in that direction

tapCount

Counts the number of consecutive taps

Notes:

  • touchState is nil if event is not a touch event. This can be used to test if we have a touch event or a key event.

    • Since Lua evaluates a nil value to false and everything else to true:

    • if touchState then we have a touch event.

  • x, y are present for all touch events.

  • startX, startY, slideX, slideY are only present with EVT_TOUCH_SLIDE.

  • swipeUp / swipeDown / swipeLeft / swipeRight may be present only withEVT_TOUCH_SLIDE.

  • tapCount is zero for anything but EVT_TOUCH_TAP.

io.close(file)

Closes file. Note that files are automatically closed when their handles are garbage collected, but that takes an unpredictable amount of time to happen.

Color Constants

On radios with color display, a color may be added to the flags described above.

There are two types of color constants: one that is an index into a table holding a palette of theme colors, and one that is just a color.

Indexed colors

These are the theme colors plus CUSTOM_COLOR, and they can be changed with the function lcd.setColor(color_index, color). Please note: if an indexed color is changed, then it changes everywhere that it is used. For the theme colors, this is not only in other widgets, but everywhere throughout the radio's user interface!

  • COLOR_THEME_PRIMARY1

  • COLOR_THEME_PRIMARY2

  • COLOR_THEME_PRIMARY3

  • COLOR_THEME_SECONDARY1

  • COLOR_THEME_SECONDARY2

  • COLOR_THEME_SECONDARY3

  • COLOR_THEME_FOCUS

  • COLOR_THEME_EDIT

  • COLOR_THEME_ACTIVE

  • COLOR_THEME_WARNING

  • COLOR_THEME_DISABLED

  • CUSTOM_COLOR

Literal colors

These color constants cannot be changed:

  • BLACK

  • WHITE

  • LIGHTWHITE

  • YELLOW

  • BLUE

  • DARKBLUE

  • GREY

  • DARKGREY

  • LIGHTGREY

  • RED

  • DARKRED

  • GREEN

  • DARKGREEN

  • LIGHTBROWN

  • DARKBROWN

  • BRIGHTGREEN

  • ORANGE

Deprecated color constants

These should no longer be used, but they are included for backwards compatibility. The old OpenTX API had a large number of indexed theme colors, and these have been mapped to the new theme colors as follows:

  • ALARM_COLOR -> COLOR_THEME_WARNING

  • BARGRAPH_BGCOLOR -> COLOR_THEME_SECONDARY3

  • BARGRAPH1_COLOR -> COLOR_THEME_SECONDARY1

  • BARGRAPH2_COLOR -> COLOR_THEME_SECONDARY2

  • CURVE_AXIS_COLOR -> COLOR_THEME_SECONDARY2

  • CURVE_COLOR -> COLOR_THEME_SECONDARY1

  • CURVE_CURSOR_COLOR -> COLOR_THEME_WARNING

  • HEADER_BGCOLOR -> COLOR_THEME_FOCUS

  • HEADER_COLOR -> COLOR_THEME_SECONDARY1

  • HEADER_CURRENT_BGCOLOR -> COLOR_THEME_FOCUS

  • HEADER_ICON_BGCOLOR -> COLOR_THEME_SECONDARY1

  • LINE_COLOR -> COLOR_THEME_PRIMARY3

  • MAINVIEW_GRAPHICS_COLOR -> COLOR_THEME_SECONDARY1

  • MAINVIEW_PANES_COLOR -> COLOR_THEME_PRIMARY2

  • MENU_TITLE_BGCOLOR -> COLOR_THEME_SECONDARY1

  • MENU_TITLE_COLOR -> COLOR_THEME_PRIMARY2

  • MENU_TITLE_DISABLE_COLOR -> COLOR_THEME_PRIMARY3

  • OVERLAY_COLOR -> COLOR_THEME_PRIMARY1

  • SCROLLBOX_COLOR -> COLOR_THEME_SECONDARY3

  • TEXT_BGCOLOR -> COLOR_THEME_SECONDARY3

  • TEXT_COLOR -> COLOR_THEME_SECONDARY1

  • TEXT_DISABLE_COLOR -> COLOR_THEME_DISABLED

  • TEXT_INVERTED_BGCOLOR -> COLOR_THEME_FOCUS

  • TEXT_INVERTED_COLOR -> COLOR_THEME_PRIMARY2

  • TITLE_BGCOLOR -> COLOR_THEME_SECONDARY1

  • TRIM_BGCOLOR -> COLOR_THEME_FOCUS

  • TRIM_SHADOW_COLOR -> COLOR_THEME_PRIMARY1

  • WARNING_COLOR -> COLOR_THEME_WARNING

Key Event Constants

This page describes the value that is passed to scripts in the event parameter. It is used in Telemetry and One-Time scripts, as well as widget scripts in full screen mode.

The key event mechanism

Each time a key is pressed, held and released a number of events get generated. Here is a typical flow:

  • when a key is pressed a FIRST event is generated

  • if the key continues to be pressed, then after a while a LONG event is generated

  • if the key continues to be pressed, then a REPEAT events are being generated

  • when the key is released a BREAK event is generated

Couple of examples:

  • a short press on key would generate: FIRST, BREAK

  • a longer pres on key would generate: FIRST, LONG, BREAK

  • even longer press: FIRST, LONG, REPEAT,REPEAT, ..., BREAK

  • kill immediately after the key press would generate: FIRST

  • kill after the long key press would generate: FIRST, LONG

Constants

  • key number

  • type of event

The two fields are combined into one single number. Some of these combinations are defined as constants and are available to Lua scripts:

Key Event Name
Comments

EVT_MENU_BREAK

MENU key release

EVT_PAGE_BREAK

PAGE key release

EVT_PAGE_LONG

MENU key long press

EVT_ENTER_BREAK

ENT key release

EVT_ENTER_LONG

ENT key long press

EVT_EXIT_BREAK

EXIT key release

EVT_PLUS_BREAK

+ key release

EVT_MINUS_BREAK

- key release

EVT_PLUS_FIRST

+ key press

EVT_MINUS_FIRST

- key press

EVT_PLUS_REPT

+ key repeat

EVT_MINUS_REPT

- key repeat

Radios with rotary encoder (X7 and Horus) have also:

Key Event Name
Comments

EVT_ROT_BREAK

rotary encoder release

EVT_ROT_LONG

rotary encoder long press

EVT_ROT_LEFT

rotary encoder rotated left

EVT_ROT_RIGHT

rotary encoder rotated right

Virtual events

Given the large number of radios supported by OpenTX, and the large difference in keys available on those, a set of VIRTUAL KEYS has been defined and are mapped to best fit available hardware

Virtual Key Event Name
Comments

EVT_VIRTUAL_NEXT_PAGE

for PAGE navigation

EVT_VIRTUAL_PREV_PAGE

for PAGE navigation

EVT_VIRTUAL_ENTER

EVT_VIRTUAL_ENTER_LONG

EVT_VIRTUAL_MENU

EVT_VIRTUAL_MENU_LONG

EVT_VIRTUAL_NEXT

for FIELDS navigation

EVT_VIRTUAL_NEXT_REPT

for FIELDS navigation

EVT_VIRTUAL_PREV

for FIELDS navigation

EVT_VIRTUAL_PREV_REPT

for FIELDS navigation

EVT_VIRTUAL_INC

for VALUES navigation

EVT_VIRTUAL_INC_REPT

for VALUES navigation

EVT_VIRTUAL_DEC

for VALUES navigation

EVT_VIRTUAL_DEC_REPT

for VALUES navigation

This normal key event sequence can be altered with the function. Any time this function is called (after the FIRST event) all further key events for this key will be suppressed until the next key press of this key. Examples:

The event parameter in the and scripts run function actually carries two pieces of information:

killEvents(key)
Telemetry
One-Time

Special Character Constants

The radio's special characters can be used with the following text constants.

Please note that the special characters are only available for standard and BOLD font sizes.

  • CHAR_RIGHT

  • CHAR_LEFT

  • CHAR_UP

  • CHAR_DOWN

  • CHAR_DELTA

  • CHAR_STICK

  • CHAR_POT

  • CHAR_SLIDER

  • CHAR_SWITCH

  • CHAR_TRIM

  • CHAR_INPUT

  • CHAR_FUNCTION

  • CHAR_CYC

  • CHAR_TRAINER

  • CHAR_CHANNEL

  • CHAR_TELEMETRY

  • CHAR_LUA

Introduction

This section includes Acknowledgments and Getting Started.

Wizard Script

TODO: Need to determine status of wizard in 2.2

Screen Constants

Name
Description

LCD_W

width in pixels

LCD_H

height in pixels

GREY()

Returns gray value which can be used in LCD functions

@status current Introduced in 2.0.13

Parameters

none

Return value

  • (number) a value that represents amount of greyness (from 0 to 15)

Notice

Only available on Taranis

General Functions

Constants

This section describes various constants that are provided for Lua by EdgeTX.

Lua Basics

Lua is a small but powerful language. This section will explain a few of the most important concepts.

Introduction

Lua was chosen for OpenTX, and hence also EdgeTX, because it is a small language designed to be highly extensible by libraries written in C and C++, so it can be integrated into other systems like EdgeTX. It is also relatively efficient, both in terms of memory and CPU usage, and hence well suited for the radios.

In addition to the provided libraries, Lua has a very elegant mechanism for loading new Lua code modules during run-time. A lot of the elegance comes from the way that the loading mechanism meshes with another concept supported by Lua: first class functions with closures.

First Class Functions

In Lua, a function declaration is really "syntactic sugar" for assigning a variable to the chunk of code that is called when the function is invoked, i.e.

local function f(x) return x + 1 end

is the same as

local f = function(x) return x + 1 end

You can even add functions to Lua tables, i.e.

t = { f = f }

will add the above function to the table t, as a field that is also called f. Does that look familiar to the return statement required at the end of a Lua script?

Yes indeed, because a script is really an anonymous function that returns a list of functions to the system. The function declarations assign variables to chunks of function code, these variables are added to the list returned at the end of the script, and the system then calls the functions periodically to run the script. So the script itself is run one time initially, and subsequently the functions returned by the last statement are called periodically.

Closures

Another important concept that goes with first-class functions, is closures. This is the environment of the function with the variable names that the function can see. Please consider the following function counter that returns another function:

The function is returned directly without being assigned to a variable name. The closure of the function returned is the body of the function counter, containing both the arguments start and step, and the local variable x. So if c1 = counter(1, 1) then c1() will return 1, 2, 3, ... when called repeatedly, and if c2 = counter(2, 3) then c2() will return 2, 5, 8, ...

Likewise, the local variables that you declare outside the functions of your script can be used by all of the functions in your script, and they persist between function calls, but they are not visible to other scripts.

Functions with Variable Number of Arguments

Please consider this function:

if event == EVT_VIRTUAL_ENTER or event == EVT_VIRTUAL_EXIT then

can be replaced by

if match(event, EVT_VIRTUAL_ENTER, EVT_VIRTUAL_EXIT) then

You can also use ... directly as a comma separated list of values, e.g. local a, b, c = ... will assign the three variables to the three first arguments following x, or nil if none are given.

References

Computer science pioneer Christopher Strachey introduced the concept of functions as first-class objects in his paper F from 1967. What it means is that functions can be treated as other variables: as arguments passed in function calls, as results returned from function calls, and a function identifier can be re-assigned to another chunk of function code, just like a variable ca be assigned to a new value.

The are a little trickier, as you can register multiple instances of the same widget script, and all of these instances run within the same Lua closure. Therefore, local variables declared outside any functions in a widget script are shared among all of the instances of that script. But each call to the create(...) function returns a new widget list to the system. And since this list is unique to each instance, you can add private instance variables to it.

It takes an argument x and a list ... A vararg list is just like a list of arguments separated by commas, and you can call the function with any number of arguments greater than 1. Inside the function, you can also treat ... like a comma separated list of variables, e.g. in the above function, ... is converted to a table by {...} just like you could construct a table by e.g. {a, b, c}. The table is iterated with the ipairs function to look for an element matching the first argument x. So e.g. the following statement

The helpful, both if you want to learn more about Lua, and if you want to search for answers to specific questions.

Key Events
Touch Events
Flags and Patterns
Colors
Screen size
local function counter(start, step)
  local x = start

  return function()
    local y = x
    x = x + step
    return y
  end
end
local function match(x, ...)
  for i, y in ipairs({...}) do
    if x == y then
      return true
    end
  end
  return false
end
closure
undamental Concepts in Programming Languages
widget scripts
vararg
Lua 5.2 Reference Manual

Drawing Flags and Colors

This section will give some technical details for radios with a color screen.

An argument with drawing flags can be given to the various functions that draw on the LCD screen. The lower half of the flags (bits 1-16) are the flag attributes shown below, and the upper half of the flags (bits 17-32) are a color value.

Since the flags are bits, you can add them up to combine, as long as you only add each flag one time. If you add the same flag twice, then it will add up to the next bit over, e.g. INVERS + INVERS = VCENTER. If you want to add a flag to a value where it may already be set, then use flags = bit32.bor(flags, INVERS).

RGB_FLAG decides how the color value is encoded into the upper half (bits 17-32).

If RGB_FLAG = 1, then a 16-bit RGB565 color is stored. This is used directly by the system to draw a color on the screen.

You should not change RGB_FLAG explicitly; this is handled automatically by the various functions and Lua constants. But you should be aware of the following.

  • If no color is given to the flags with a drawing function, RGB_FLAGS = 0 and the color index = 0. Therefore, the default color is stored in the color table under this index, and you can change the default color with lcd.setColor(0, color).

Colors in EdgeTX versus OpenTX

OpenTX only supports indexed colors in drawing functions, so you must first call lcd.setColor to change e.g. CUSTOM_COLOR, and then call the LCD drawing function with that indexed color. In EdgeTX, you can use either type of color for drawing functions, so you are no longer forced to constantly call lcd.setColor. You can also store any color in local variables, and then use these when drawing, thus effectively creating your own color theme.

In OpenTX, lcd.RGB returns a 16 bit RGB565 value, but in EdgeTX it returns a 32 bit flags value with the 16 bit RGB565 value in the upper half (bits 17-32). Therefore, colors in EdgeTX are not binary compatible with colors in OpenTX. But if you use the functions lcd.RGB, lcd.setColor, and lcd.getColor, then your code should work the same way in EdgeTX as in OpenTX.

Unfortunately, older versions of OpenTX disabled the function lcd.RGB when the screen is not available for drawing, so it could only be called successfully from the refresh function in widgets and from the run function in One-Time scripts. Therefore, some existing widget scripts set up colors with hard coded color constants instead of calling lcd.RGB during initialization, and this is not going to work with EdgeTX, because of the different binary format. But in the current version of OpenTX this issue has been fixed, so you can replace the hard coded color constants with lcd.RGB values.

Not all of the flags below should be directly manipulated from Lua, but those that are meant to be set directly by Lua, are accessible by the .

If RGB_FLAG = 0, then an index into a color table is stored. This color table holds a default color (index 0), the theme colors, and CUSTOM_COLOR. The entries in the color table can be changed with the function . The advantage of this system is that the color changes everywhere that this indexed color is used, and this is how different color themes are created. Notice that changing the theme colors affects the entire user interface of your radio!!

must have an as its first argument, because this will be the index of the color in the table being changed. Giving another color, e.g. ORANGE, as the first argument will result in nothing.

always returns a RGB color. This can be used to "save" an indexed color before you change it.

obviously returns a RGB color.

lcd.setColor
lcd.getColor
lcd.RGB
Lua flag constants
lcd.setColor
indexed color

accessTelemetryPush()

This functions allows for sending SPORT / ACCESS telemetry data toward the receiver, and more generally, to anything connected SPORT bus on the receiver or transmitter.

When called without parameters, it will only return the status of the output buffer without sending anything.

@status current Introduced in 2.3

Parameters

  • module module index (0 = internal, 1 = external)

  • rxUid receiver index

  • sensorId physical sensor ID

  • frameId frame ID

  • dataId data ID

  • value value

Return value

  • boolean data queued in output buffer or not.

chdir(directory)

Change the working directory

@status current Introduced in 2.3.0

Parameters

  • directory (string) New working directory

Return value

none

crossfireTelemetryPop()

Pops a received Crossfire Telemetry packet from the queue.

@status current Introduced in 2.2.0

Parameters

none

Return value

  • nil queue does not contain any (or enough) bytes to form a whole packet

  • multiple returns 2 values:

    • command (number)

    • packet (table) data bytes

defaultStick(channel)

Get stick that is assigned to a channel. See Default Channel Order in General Settings.

@status current Introduced in 2.0.0

Parameters

  • channel (number) channel number (0 means CH1)

Return value

  • number Stick assigned to this channel (from 0 to 3)

getAvailableMemory()

Get available memory remaining in the Heap for Lua.

Parameters

none

Return value

  • usage (number) a value returned in b

getGeneralSettings()

Returns (some of) the general radio settings

@status current Introduced in 2.0.6, imperial added in TODO, language and voice added in 2.2.0, gtimer added in 2.2.2.

Parameters

none

Return value

  • table with elements:

    • battWarn (number) radio battery range - warning value

    • battMin (number) radio battery range - minimum value

    • battMax (number) radio battery range - maximum value

    • imperial (number) set to a value different from 0 if the radio is set to the

      IMPERIAL units

    • language (string) radio language (used for menus)

    • voice (string) voice language (used for speech)

    • gtimer (number) radio global timer in seconds (does not include current session)

Logical Switch Function Constants

These constants give the type of logical switch function.

  • LS_FUNC_NONE

  • LS_FUNC_VEQUAL

  • LS_FUNC_VALMOSTEQUAL

  • LS_FUNC_VPOS

  • LS_FUNC_VNEG

  • LS_FUNC_RANGE

  • LS_FUNC_APOS

  • LS_FUNC_ANEG

  • LS_FUNC_AND

  • LS_FUNC_OR

  • LS_FUNC_XOR

  • LS_FUNC_EDGE

  • LS_FUNC_EQUAL

  • LS_FUNC_GREATER

  • LS_FUNC_LESS

  • LS_FUNC_DIFFEGREATER

  • LS_FUNC_ADIFFEGREATER

  • LS_FUNC_TIMER

  • LS_FUNC_STICKY

getDateTime()

Return current system date and time that is kept by the RTC unit

Parameters

none

Return value

  • table current date and time, table elements:

    • year (number) year

    • mon (number) month

    • day (number) day of month

    • hour (number) hours

    • hour12 (number) hours in US format

    • min (number) minutes

    • sec (number) seconds

    • suffix (text) am or pm

Special Function Constants

These constants determine the type of a Special Function

  • FUNC_OVERRIDE_CHANNEL

  • FUNC_TRAINER

  • FUNC_INSTANT_TRIM

  • FUNC_RESET

  • FUNC_SET_TIMER

  • FUNC_ADJUST_GVAR

  • FUNC_VOLUME

  • FUNC_SET_FAILSAFE

  • FUNC_RANGECHECK

  • FUNC_BIND

  • FUNC_PLAY_SOUND

  • FUNC_PLAY_TRACK

  • FUNC_PLAY_VALUE

  • FUNC_PLAY_SCRIPT

  • FUNC_RESERVE5

  • FUNC_BACKGND_MUSIC

  • FUNC_BACKGND_MUSIC_PAUSE

  • FUNC_VARIO

  • FUNC_HAPTIC

  • FUNC_LOGS

  • FUNC_BACKLIGHT

  • FUNC_SCREENSHOT

  • FUNC_RACING_MODE

  • FUNC_DISABLE_TOUCH

Included Lua Libraries

Telemetry Scripts

Overview

Telemetry scripts are used for building customized screens. Each model can have up to three active scripts as configured on the model's telemetry configuration page. The same script can be assigned to multiple models.

Please note: Telemetry scripts are only available on radios with telemetry screens, such as e.g. FrSky Taranis models (including Xlite), Radiomaster TX12 and and Jumper T12.

Lifetime

  • Telemetry scripts are loaded when the model is selected.

  • init function is called one time when the script is loaded

  • background function is periodically; both when the telemetry screen is visible and when it is not.

  • run function is called periodically only when the telemetry screen is visible

  • script is stopped and disabled if it misbehaves (e.g. run-time error or low memory)

  • all telemetry scripts are stopped if a one-time script is running (see One-time scripts)

File Location

Scripts are located on the SD card in the folder /SCRIPTS/TELEMETRY/<name>.lua. File name length (without extension) must be 6 characters or less (this limit was 8 characters in OpenTX 2.1).

Interface

Every script must include a return statement at the end, defining its interface to EdgeTX. This statement returns a table with the following fields:

  • init function (optional)

  • background function (optional)

  • run function

Example

Notes:

Lua Standard Libraries
Included

package

-

coroutine

-

table

since OpenTX 2.3.8

(color LCD radios only)

since OpenTX 2.1.0 (with limitations)

os

-

string

since OpenTX 2.1.7

bit32

since OpenTX 2.1.0

math

since OpenTX 2.0.0

debug

-

The event parameter indicates which transmitter key has been pressed (see ).

local function init()
  -- init is called once when model is loaded
end

local function background()
  -- background is called periodically
end

local function run(event)
  -- run is called periodically only when screen is visible
end

return { run = run, background = background, init = init }
io
Key Events

crossfireTelemetryPush()

This functions allows for sending telemetry data toward the TBS Crossfire link.

When called without parameters, it will only return the status of the output buffer without sending anything.

@status current Introduced in 2.2.0, retval nil added in 2.3.4

Parameters

  • command command

  • data table of data bytes

Return value

  • boolean data queued in output buffer or not.

  • nil incorrect telemetry protocol.

defaultChannel(stick)

Get channel assigned to stick. See Default Channel Order in General Settings

@status current Introduced in 2.0.0

Parameters

  • stick (number) stick number (from 0 to 3)

Return value

  • number channel assigned to this stick (from 0 to 3)

  • nil stick not found

getLogicalSwitchValue(id)

Reads the value of a logical switch.

@status current Introduced in 2.6

Parameter

  • id: integer identifying the logical switch (zero for L01 etc.).

Return value

  • value: true/false.

getFlightMode(mode)

Return flight mode data.

@status current Introduced in 2.1.7

Parameters

  • mode (number) flight mode number to return (0 - 8). If mode parameter

    is not specified (or contains invalid value), then the current flight mode data is returned.

Return value

  • multiple returns 2 values:

    • (number) (current) flight mode number (0 - 8)

    • (string) (current) flight mode name

getGlobalTimer()

Returns radio timers

@status current Introduced added in 2.3.0.

Parameters

none

Return value

  • table with elements:

  • gtimer (number) radio global timer in seconds

  • session (number) radio session in seconds

  • ttimer (number) radio throttle timer in seconds

  • tptimer (number) radio throttle percent timer in seconds

getRAS()

Return the RAS value or nil if no valid hardware found

@status current Introduced in 2.2.0

Parameters

none

Return value

  • number representing RAS value. Value bellow 0x33 (51 decimal) are all ok, value above 0x33 indicate a hardware antenna issue.

    This is just a hardware pass/fail measure and does not represent the quality of the radio link

Notice

RAS was called SWR in the past

getRSSI()

Get RSSI value as well as low and critical RSSI alarm levels (in dB)

@status current Introduced in 2.2.0

Parameters

none

Return value

  • rssi RSSI value (0 if no link)

  • alarm_low Configured low RSSI alarm level

  • alarm_crit Configured critical RSSI alarm level

getRotEncSpeed()

Return rotary encoder current speed

@status current Introduced in 2.3.10

Parameters

none

Return value

  • number in list: ROTENC_LOWSPEED, ROTENC_MIDSPEED, ROTENC_HIGHSPEED

  return 0 on radio without rotary encoder

getRtcTime()

Return current RTC system date as unix timstamp (in seconds since 1. Jan 1970)

Please note the RTC timestamp is kept internally as a 32bit integer, which will overflow in 2038.

Parameters

none

Return value

  • number Number of seconds elapsed since 1. Jan 1970

getSourceIndex(sourceName)

Status: current Introduced in 2.6

Parameters

Return value

  • 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 e.g. 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.

sourceName: string naming a value source as it is shown on radio menus where you can select it. Notice that many names have in them.

special characters

getShmVar(id)

Gets the value of a shared memory variable that can be used for passing data between Lua widgets and other Lua scripts.

@status current Introduced in 2.6

Parameters

  • id: integer between 1 and 16 identifying the shared memory variable.

Return value

  • value: integer. The value of the shared memory variable.

Notice

Only available on radios with color display

getSwitchName(switchIndex)

@status current Introduced in 2.6

Parameter

  • switchIndex: integer identifying a switch as returned by getSwitchIndex(positionName) or fields in the table returned by model.getLogicalSwitch(switch) identifying switches.

Return value

  • value: string naming the switch position as it is shown on radio menus where a switch can be chosen.

getSourceName(sourceIndex)

Status: current Introduced in 2.6

Parameters

  • sourceIndex: integer identifying a value source as returned by getSourceIndex(sourceName) or the id field in the table returned by getFieldInfo.

Return value

  • 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 e.g. getValue(index) will work with the indices used here.

getSwitchIndex(positionName)

@status current Introduced in 2.6

Parameters

Return value

  • value: integer. The switchIndex, which can be used as input for `getSwitchName(switchIndex)` and `getSwitchValue(switchIndex)`. Also corresponds to the fields in the table returned by `model.getLogicalSwitch(switch)` identifying switches.

positionName: string naming a switch position as it is shown on radio menus where you can select a switch. Notice that many names have special characters in them like arrow up/down etc. (see ).

Special Character Constants

getSwitchValue(switchIndex)

@status current Introduced in 2.6

Parameter

  • switchIndex: integer identifying a switch as returned by getSwitchIndex(positionName) or fields in the table returned by model.getLogicalSwitch(switch) identifying switches.

Return value

  • value: true/false. The value of the switch.

getFieldInfo(source)

Return detailed information about field (source)

The list of valid sources is available:

OpenTX Version
Radio

2.0

2.1

2.2

2.3

@status current Introduced in 2.0.8, 'unit' field added in 2.2.0

Parameters

  • source can be an identifier (number) or a name (string) of the source.

Return value

  • table information about requested field, table elements:

    • id (number) field identifier

    • name (string) field name

    • desc (string) field description

  • nil the requested field was not found

,

, ,

, , ,

'unit' (number) unit identifier

Full list
all
X9D and X9D+
X9E
X9D and X9D+
X9E
Horus
X9D and X9D+
X9E
X7
Horus

getTxGPS()

Return the internal GPS position or nil if no valid hardware found

@status current Introduced in 2.2.2

Parameters

none

Return value

  • table representing the current radio position

    • lat (number) internal GPS latitude, positive is North

    • lon (number) internal GPS longitude, positive is East

    • 'numsat' (number) current number of sats locked in by the GPS sensor

    • 'fix' (boolean) fix status

    • 'alt' (number) internal GPS altitude in 0.1m

    • 'speed' (number) internal GPSspeed in 0.1m/s

    • 'heading' (number) internal GPS ground course estimation in degrees * 10

    • 'hdop' (number) internal GPS horizontal dilution of precision

getUsage()

Get percent of already used Lua instructions in current script execution cycle.

@status current Introduced in 2.2.1

Parameters

none

Return value

  • usage (number) a value from 0 to 100 (percent)

getTime()

Return the time since the radio was started in multiple of 10ms

The timer internally uses a 32-bit counter which is enough for 497 days so overflows will not happen.

@status current Introduced in 2.0.0

Parameters

none

Return value

  • number Number of 10ms ticks since the radio was started Example:

    run time: 12.54 seconds, return value: 1254

getValue(source)

Returns the value of a source.

The list of fixed sources:

OpenTX Version
Radio

2.0

2.1

2.2

2.3

In OpenTX 2.1.x the telemetry sources no longer have a predefined name. To get a telemetry value simply use it's sensor name. For example:

  • Altitude sensor has a name "Alt"

  • to get the current altitude use the source "Alt"

  • to get the minimum altitude use the source "Alt-", to get the maximum use "Alt+"

@status current Introduced in 2.0.0, changed in 2.1.0, Cels+ and Cels- added in 2.1.9

Parameters

  • source can be an identifier (number) (which was obtained by the getFieldInfo())

    or a name (string) of the source.

Return value

  • value current source value (number). Zero is returned for:

    • non-existing sources

    • for all telemetry source when the telemetry stream is not received

    • far all non allowed sensors while FAI MODE is active

  • table GPS position is returned in a table:

    • lat (number) latitude, positive is North

    • lon (number) longitude, positive is East

    • pilot-lat (number) pilot latitude, positive is North

    • pilot-lon (number) pilot longitude, positive is East

  • table GPS date/time, see getDateTime()

  • table Cells are returned in a table (except where no cells were detected in which case the returned value is 0):

    • table has one item for each detected cell:

    • key (number) cell number (1 to number of cells)

    • value (number) current cell voltage

Notice

Getting a value by its numerical identifier is faster then by its name. While Cels sensor returns current values of all cells in a table, a Cels+ or Cels- will return a single value - the maximum or minimum Cels value.

,

, ,

, , ,

all
X9D and X9D+
X9E
X9D and X9D+
X9E
Horus
X9D and X9D+
X9E
X7
Horus

getVersion()

Return OpenTX version

@status current Introduced in 2.0.0, expanded in 2.1.7, radio type strings changed in 2.2.0, os name added in EdgeTX 2.4.0

Example

This example also runs in OpenTX versions where the function returned only one value:

local function run(event)
  local ver, radio, maj, minor, rev, osname = getVersion()
  print("version: "..ver)
  if radio then print ("radio: "..radio) end
  if maj then print ("maj: "..maj) end
  if minor then print ("minor: "..minor) end
  if rev then print ("rev: "..rev) end
  if osname then print ("osname: "..osname) end
  return 1
end

return {  run=run }

Output of the above script in simulator:

version: 2.4.0
radio: tx16s-simu
maj: 2
minor: 4
rev: 0
osname: EdgeTX

Parameters

none

Return value

  • string OpenTX version (ie "2.1.5")

  • multiple values (available since 2.1.7):

    • (string) OpenTX version (ie "2.1.5")

    • (string) radio type: x12s, x10, x9e, x9d+, x9d or x7.

      If running in simulator the "-simu" is added

    • (number) major version (ie 2 if version 2.1.5)

    • (number) minor version (ie 1 if version 2.1.5)

    • (number) revision number (ie 5 if version 2.1.5)

      Since EdgeTX 2.4.0, sixth value added

    • (string) OS name (i.e. EdgeTX or nil if OpenTX)

killEvents(key)

@status current Introduced in 2.0.0

Parameters

  • key (number) key to be killed, can also include event type (only the key part is used)

Return value

none

Stops key state machine. See for the detailed description.

Key Events

loadScript(file [, mode], [,env])

Return values are same as from Lua API loadfile() method: If the script was loaded w/out errors then the loaded script (or "chunk") is returned as a function. Otherwise, returns nil plus the error message.

@status current Introduced in 2.2.0

Example

  fun, err = loadScript("/SCRIPTS/FUNCTIONS/print.lua")
  if (fun ~= nil) then
     fun("Hello from loadScript()")
  else
     print(err)
  end

Parameters

  • file (string) Full path and file name of script. The file extension is optional and ignored (see mode param to control which extension will be used). However, if an extension is specified, it should be ".lua" (or ".luac"), otherwise it is treated as part of the file name and the .lua/.luac will be appended to that.

  • mode (string) (optional) Controls whether to force loading the text (.lua) or pre-compiled binary (.luac) version of the script. By default OTx will load the newest version and compile a new binary if necessary (overwriting any existing .luac version of the same script, and stripping some debug info like line numbers). You can use mode to control the loading behavior more specifically. Possible values are:

    • b only binary.

    • t only text.

    • T (default on simulator) prefer text but load binary if that is the only version available.

    • bt (default on radio) either binary or text, whichever is newer (binary preferred when timestamps are equal).

    • Add x to avoid automatic compilation of source file to .luac version.

      Eg: "tx", "bx", or "btx".

    • Add c to force compilation of source file to .luac version (even if existing version is newer than source file).

      Eg: "tc" or "btc" (forces "t", overrides "x").

    • Add d to keep extra debug info in the compiled binary.

      Eg: "td", "btd", or "tcd" (no effect with just "b" or with "x").

  • env (integer) See documentation for Lua function loadfile().

Return value

  • function The loaded script, or nil if there was an error (e.g. file not found or syntax error).

  • string Error message(s), if any. Blank if no error occurred.

Notice

Note that you will get an error if you specify mode as "b" or "t" and that specific version of the file does not exist (eg. no .luac file when "b" is used). Also note that mode is NOT passed on to Lua's loader function, so unlike with loadfile() the actual file content is not checked (as if no mode or "bt" were passed to loadfile()).

Load a Lua script file. This is similar to Lua's own API method, but it uses OpenTx's optional pre-compilation feature to save memory and time during load.

loadfile()

playFile(name)

Play a file from the SD card

@status current Introduced in 2.0.0, changed in 2.1.0

Parameters

  • path (string) full path to wav file (i.e. “/SOUNDS/en/system/tada.wav”)

    Introduced in 2.1.0: If you use a relative path, the current language is appended

    to the path (example: for English language: /SOUNDS/en is appended)

Return value

none

multiBuffer(address[,value])

This function reads/writes the Multi protocol buffer to interact with a protocol².

@status current Introduced in 2.3.2

Parameters

  • address to read/write in the buffer

    @param (optional): value to write in the buffer

Return value

  • buffer value (number)

playDuration(duration [, hourFormat])

Play a time value (text to speech)

@status current Introduced in 2.1.0

Parameters

  • duration (number) number of seconds to play. Only integral part is used.

  • hourFormat (number):

    • 0 or not present play format: minutes and seconds.

    • != 0 play format: hours, minutes and seconds.

Return value

none

playTone(frequency, duration, pause [, flags [, freqIncr]])

Play a tone

@status current Introduced in 2.1.0

Parameters

  • frequency (number) tone frequency in Hz (from 150 to 15000)

  • duration (number) length of the tone in milliseconds

  • pause (number) length of the silence after the tone in milliseconds

  • flags (number):

    • 0 or not present play with normal priority.

    • PLAY_BACKGROUND play in background (built in vario function uses this context)

    • PLAY_NOW play immediately

  • freqIncr (number) positive number increases the tone pitch (frequency with time), negative number decreases it. The frequency changes every 10 milliseconds, the change is freqIncr * 10Hz. The valid range is from -127 to 127.

Return value

none

playHaptic(duration, pause [, flags])

Generate haptic feedback

@status current Introduced in 2.2.0

Parameters

  • duration (number) length of the haptic feedback in milliseconds

  • pause (number) length of the silence after haptic feedback in milliseconds

  • flags (number):

    • 0 or not present play with normal priority

    • PLAY_NOW play immediately

Return value

none

playNumber(value, unit [, attributes])

Play a numerical value (text to speech)

@status current Introduced in 2.0.0

Parameters

  • value (number) number to play. Value is interpreted as integer.

  • unit (number) unit identifier [Full list]((../appendix/units.html))

  • attributes (unsigned number) possible values:

    • 0 or not present plays integral part of the number (for a number 123 it plays 123)

    • PREC1 plays a number with one decimal place (for a number 123 it plays 12.3)

    • PREC2 plays a number with two decimal places (for a number 123 it plays 1.23)

Return value

none

popupConfirmation(title, message, event)

Raises a pop-up on screen that asks for confirmation

@status current Introduced in 2.2.0, changed from (title, event) to (title, message, event) in 2.3.8

Parameters

  • title (string) title to display

  • message (string) text to display

  • event (number) the event variable that is passed in from the Run function (key pressed)

Return value

  • "CANCEL" user pushed EXIT key

Notice

Use only from stand-alone and telemetry scripts.

popupWarning(title, event)

Raises a pop-up on screen that shows a warning

@status current Introduced in 2.2.0

Parameters

  • title (string) text to display

  • event (number) the event variable that is passed in from the Run function (key pressed)

Return value

  • "CANCEL" user pushed EXIT key

Notice

Use only from stand-alone and telemetry scripts.

popupInput(title, event, input, min, max)

Raises a pop-up on screen that allows uses input

@status current Introduced in 2.0.0

Parameters

  • title (string) text to display

  • event (number) the event variable that is passed in from the Run function (key pressed)

  • input (number) value that can be adjusted by the +/­- keys

  • min (number) min value that input can reach (by pressing the -­ key)

  • max (number) max value that input can reach

Return value

  • number result of the input adjustment

  • "OK" user pushed ENT key

  • "CANCEL" user pushed EXIT key

Notice

Use only from stand-alone and telemetry scripts.

serialWrite(str)

@param str (string) String to be written to the serial port.

Writes a string to the serial port. The string is allowed to contain any character, including 0.

@status current Introduced in 2.3.10

Parameters

none

Return value

none

serialRead([num])

@param num (optional): maximum number of bytes to read. If non-zero, serialRead will read up to num characters from the buffer. If 0 or left out, serialRead will read up to and including the first newline character or the end of the buffer. Note that the returned string may not end in a newline if this character is not present in the buffer.

Reads characters from the serial port. The string is allowed to contain any character, including 0.

@status current Introduced in 2.3.8

Parameters

none

Return value

  • str string. Empty if no new characters were available.

resetGlobalTimer([type])

Resets the radio global timer to 0.

@status current Introduced in 2.2.2, param added in 2.3

Parameters

  • (optional) : if set to 'all', throttle ,throttle percent and session timers are reset too

                  if set to 'session', radio session timer is reset too
                  if set to 'ttimer', radio throttle timer is reset too
                  if set to  'tptimer', radio throttle percent timer is reset too

Return value

none

setSerialBaudrate(baudrate)

Set baudrate for serial port(s) affected to LUA

@status current Introduced in 2.3.12

Parameters

baudrate Desired baudrate

Return value

none

sportTelemetryPop()

Pops a received SPORT packet from the queue. Please note that only packets using a data ID within 0x5000 to 0x50FF (frame ID == 0x10), as well as packets with a frame ID equal 0x32 (regardless of the data ID) will be passed to the LUA telemetry receive queue.

@status current Introduced in 2.2.0

Parameters

none

Return value

  • nil queue does not contain any (or enough) bytes to form a whole packet

  • multiple returns 4 values:

    • sensor ID (number)

    • frame ID (number)

    • data ID (number)

    • value (number)

setShmVar(id, value)

Sets the value of a shared memory variable that can be used for passing data between Lua widgets and other Lua scripts.

@status current Introduced in 2.6

Parameters

  • id: integer between 1 and 16 identifying the shared memory variable.

  • value: integer. The value of the shared memory variable.

Return value

none

Notice

Only available on radios with color display

sources([first[, last]])

This is an iterator function over value sources.

for sourceIndex, sourceName in sources() do ...

will iterate over all available value sources.

Parameters

  • first: the first source index. If nil or omitted, the first available source is used.

  • last: the last soure index. If nil or omitted, the last available source is used.

Status

current Introduced in 2.6

setTelemetryValue(id, subID, instance, value [, unit [, precision [, name]]])

@status current Introduced in 2.2.0

Parameters

  • id Id of the sensor, valid range is from 0 to 0xFFFF

  • subID subID of the sensor, usually 0, valid range is from 0 to 7

  • instance instance of the sensor (SensorID), valid range is from 0 to 0xFF

  • value fed to the sensor

  • precision the precision of the sensor

    • 0 or not present no decimal precision.

    • != 0 value is divided by 10^precision, e.g. value=1000, prec=2 => 10.00.

  • name (string) Name of the sensor if it does not yet exist (4 chars).

    • not present Name defaults to the Id.

    • present Sensor takes name of the argument. Argument must have name surrounded by quotes: e.g., "Name"

Return value

  • true, if the sensor was just added. In this case the value is ignored (subsequent call will set the value)

Notice

All three parameters id, subID and instance can't be zero at the same time. At least one of them must be different from zero.

unit unit of the sensor

Full list

setStickySwitch(id, value)

Sets the value of a sticky logical switch.

@status current Introduced in 2.6

Parameters

  • id: integer identifying the sticky logical switch (zero for LS1 etc.).

  • value: true/false. The new value of the sticky logical switch.

Return value

  • bufferFull: true/false. This function sends a message from Lua to the logical switch processor via a buffer with eight slots that are read 10 times per second. If the buffer is full, then a true value is returned, and no message was sent (i.e. the switch was not changed).

Note

  • If you create an empty sticky switch STICKY(---, ---) then it will be ON by default. If you want a sticky switch that is OFF by default, and can be controlled by this function, then use the switch itself as the source for V1, e.g. L11 = STICKY(L11, ---)

switches([first[, last]])

This is an iterator function over switch positions.

for switchIndex, switchName in switches() do ...

will iterate over all available switch positions.

Parameters

  • first: the first switch index. If nil or omitted, the first available switch is used.

  • last: the last switch index. If nil or omitted, the last available switch is used.

Status

Current Introduced in 2.6

model.deleteFlightModes()

Clear all flightModes

@status current Introduced in 2.3.10

Parameters

none

Return value

none

model.deleteInputs()

Delete all Inputs

@status current Introduced in 2.0.0

Parameters

none

Return value

none

sportTelemetryPush()

This functions allows for sending SPORT telemetry data toward the receiver, and more generally, to anything connected SPORT bus on the receiver or transmitter.

When called without parameters, it will only return the status of the output buffer without sending anything.

@status current Introduced in 2.2.0, retval nil added in 2.3.4

Parameters

  • sensorId physical sensor ID

  • frameId frame ID

  • dataId data ID

  • value value

Return value

  • boolean data queued in output buffer or not.

  • nil incorrect telemetry protocol.

model.defaultInputs()

Set all inputs to defaults

@status current Introduced in 2.0.0

Parameters

none

Return value

none

model.deleteInput(input, line)

Delete line from specified input

@status current Introduced in 2.0.0

Parameters

  • input (unsigned number) input number (use 0 for Input1)

  • line (unsigned number) input line (use 0 for first line)

Return value

none

model.deleteMix(channel, line)

Delete mixer line from specified Channel

@status current Introduced in 2.0.0

Parameters

  • channel (unsigned number) channel number (use 0 for CH1)

  • line (unsigned number) mix number (use 0 for first line(mix))

Return value

none

model.getCustomFunction(function)

Get Custom Function parameters

@status current Introduced in 2.0.0, TODO rename function

Parameters

  • function (unsigned number) custom function number (use 0 for CF1)

Return value

  • nil requested custom function does not exist

  • table custom function data:

    • switch (number) switch index

    • func (number) function index

    • name (string) Name of track to play (only returned only returned if action is play track, sound or script)

    • value (number) value (only returned only returned if action is not play track, sound or script)

    • mode (number) mode (only returned only returned if action is not play track, sound or script)

    • param (number) parameter (only returned only returned if action is not play track, sound or script)

    • active (number) 0 = disabled, 1 = enabled

model.deleteMixes()

Remove all mixers

@status current Introduced in 2.0.0

Parameters

none

Return value

none

model.getFlightMode(index)

Return input data for given input and line number

@status current Introduced in 2.3.10

Parameters

  • index (unsigned number) flight mode number (use 0 for FM0)

Return value

  • nil requested input or line does not exist

  • table input data:

    • name (string) input line name

    • switch (number) input switch index

    • fadeIn (number) fade in value (in 0.1s)

    • fadeOut (number) fade out value (in 0.1s)

    • trimsValues (table) table of trim values:

      • key is trim number (zero based)

      • value is trim value

    • trimsModes (table) table of trim mode:

      • key is trim number (zero based)

      • value is trim mode

model.getCurve(curve)

Get Curve parameters

Note that functions returns the tables starting with index 0 contrary to LUA's usual index starting with 1

@status current Introduced in 2.0.12

Parameters

  • curve (unsigned number) curve number (use 0 for Curve1)

Return value

  • nil requested curve does not exist

  • table curve data:

    • name (string) name

    • type (number) type

    • smooth (boolean) smooth

    • points (number) number of points

    • y (table) table of Y values:

      • key is point number (zero based)

      • value is y value

    • x (table) only included for custom curve type:

      • key is point number (zero based)

      • value is x value

model.getGlobalVariable(index, flight_mode)

Return current global variable value

Example:

  -- get GV3 (index = 2) from Flight mode 0 (FM0)
  val = model.getGlobalVariable(2, 0)

Parameters

  • index zero based global variable index, use 0 for GV1, 8 for GV9

  • flight_mode Flight mode number (0 = FM0, 8 = FM8)

Return value

  • nil requested global variable does not exist

  • number current value of global variable

Notice

a simple warning or notice

model.getInfo()

Get current Model information

@status current Introduced in 2.0.6, changed in 2.2.0, filename added in 2.6.0.

Parameters

none

Return value

  • table model information:

    • name (string) model name

    • bitmap (string) bitmap name (not present on X7)

    • filename (string) model filename

model.getInput(input, line)

Return input data for given input and line number

@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3, inputName added 2.3.10, flighmode reworked in 2.3.11

Parameters

  • input (unsigned number) input number (use 0 for Input1)

  • line (unsigned number) input line (use 0 for first line)

Return value

  • nil requested input or line does not exist

  • table input data:

    • name (string) input line name

    • inputName (string) input input name

    • source (number) input source index

    • weight (number) input weight

    • offset (number) input offset

    • switch (number) input switch index

    • curveType (number) curve type (function, expo, custom curve)

    • curveValue (number) curve index

    • carryTrim (boolean) input trims applied

    • 'flightModes' (number) bit-mask of active flight modes