{{ network:lua_logo.png?nolink&100|}} ====== Introduction to Lua programming ====== WebHMI allows you to create custom programs (scripts) in [[https://en.wikipedia.org/wiki/Lua | Lua]] 5.1 language. The scripts are managed in the **Setup -> Scripts** menu item. If you have no experience with Lua language read this tutorial at first [[ https://gist.github.com/pateltej/bfec90ff449595f12236 | Lua in 15 minutes]]. Each WebHMI script should contain a function named **main**. It will be called at the right time (depending on the settings of the script - in each cycle, when you act on the dashboard or when changing the value of the register, etc). Also, the entire script will be executed once when the daemon is started. This is necessary to compile the Lua script and validate it. This means that all the code from the global scope (that is, outside the main function, the main function will not be called) will be executed. This can be useful for initializing some variables, etc. Each script has its own global scope. It is impossible to access global variables and functions from one script in another. The **main** function will receive one special parameter //userId//. This is ID of the user that executed this script. If the script is being executed in each loop or when the register is changed, **userId** will be zero. If script is being executed from any dashboard then userId will contain user's id. Here is an example of a simple script for WebHMI: --[[ these vars will be assigned only once global var will keep their values between scans BUT NOT between project restarts!!! -- for saving data between project restarts use D or DSxxx registers or key-value storage --]] first_scan = true -- first scan flag GLOBAL_CONSTANT_1 = 100 -- UPPER case preferrable for constants local now1 = 0 -- global because outside scope of main function main (userId) now2 = 0 -- also global because no "local" before if first_scan then first_scan = false -- some actions only made once upon project restart end now1 = os.time () -- get time from Lua function now2 = GetReg ( "systemTime" ) -- get time form register with "systemTime" alias if (now1 == now2) then DEBUG ( "both time are equal" ) else ERROR ( "something wrong with time ... " ) end end -- main WebHMI imposes the following restrictions on standard Lua functions and libraries: * such functions and tables are __not available__: require, print, loadfile, dofile, os.execute, os.getenv, os.remove, os.rename, os.tmpname, package, debug.debug, debug.getfenv, debug.getregistry, arg * libraries are __not available__: io In addition to the standard Lua functions, WebHMI also defines additional functions which are described in this manual. For the convenience of working with registers from Lua programs, each register can be assigned a symbolic name and be accessed from Lua with this name. This name is specified in the register settings in the **Script alias** field: {{ network:alias_in_reg_list2.png?800 |}} In the example above, alias "systemTime" was used in GetReg function to read system time from internal WebHMI register with id = 1. An example of a simple script that shows the calls of some WebHMI functions: function main (userId) local randomVal = GetReg("random_val"); SetReg("random_val_copy", randomVal); WriteReg("result", randomVal + 2); AddInfoMessage("This is a Lua script", userId); AddWarningMessage("Warning. This is a Lua script", userId); AddAlertMessage("Alert! This is a Lua script", userId); SendSMS("380501234567", "This is a test SMS"); ERROR("This message will be added to communication log with ERROR level"); INFO("This message will be added to communication log with INFO level"); DEBUG("This message will be added to communication log with DEBUG level"); TRACE("This message will be added to communication log with TRACE level"); end Despite the fact that the built-in editor checks the syntax of the program, it is not able to detect all the errors that can occur during the execution of the script. If any error occurs during script execution, it will be displayed in communication log (**Maintenance->WebHMI Log**). For example, once this script will be executed, an error will occur because variable **random** was not declared. function main (userId) local v1 = GetReg("Drying_Humidity1_Value"); v1 = v1 + random; -- error is here, without random everything is ok SetReg("Drying_Humidity1_Value", v1); WriteReg("Drying_Humidity1_Value", v1); AddInfoMessage(v1, userId); end There will be such records in WebHMI Log: Jan 23 12:09:27.047: ERROR: LUA scripts: Can't execute LUA script #1. Error #2: [string "Calculate humidity"]:4: attempt to perform arithmetic on a nil value (global 'random') Jan 23 12:09:27.551: ERROR: LUA scripts: Can't execute LUA script #1. Error #2: [string "Calculate humidity"]:4: attempt to perform arithmetic on a nil value (global 'random') Jan 23 12:09:28.051: ERROR: LUA scripts: Can't execute LUA script #1. Error #2: [string "Calculate humidity"]:4: attempt to perform arithmetic on a nil value (global 'random') Here we see that the error occurred while trying to perform an arithmetic operation with an undefined variable (value is **nil**). The error occurred in script with id=1, its name was 'Calculate humidity', the error occurred in line number 4 at 12:09:27.047. The variable that caused the error is called 'random'. Thus, using this log you can find all runtime errors in your scripts. Also for debugging you can use watch console window, which is available in [[lua:scripts_editor]].