diff --git a/Tasmota-Scripting-Language.md b/Tasmota-Scripting-Language.md new file mode 100644 index 00000000..90fd1868 --- /dev/null +++ b/Tasmota-Scripting-Language.md @@ -0,0 +1,257 @@ +Script Language for Tasmota - An alternative to Tasmota [Rules](Rules). + +[Script Cookbook](Script-Cookbook) + +To use, you must compile your own firmware. Add the following compiler directives to `user_config_override.h`: +``` +#ifndef USE_RULES +#define USE_SCRIPT # adds about 17k flash size, variable ram size +#endif +#ifdef USE_RULES +#undef USE_RULES +#endif +``` + +**Optional Features** + +These features are enabled by adding the following `#define` compiler directive parameters and compile the firmware. These are explained further below in the article. + +| Feature | Description | +| -- | -- | +USE_SCRIPT_FATFS CS_PIN | enables SD card support (on spi bus) also enables 4k script buffer +USE_SCRIPT_FATFS_EXT | enables additional FS commands +SDCARD_DIR | enables support for WEBUI for SD card directory up and download +USE_24C256 | enables use of 24C256 i2c eeprom to expand script buffer (defaults to 4k) +SUPPORT_MQTT_EVENT | enables support for subscribe unsubscribe +USE_TOUCH_BUTTONS | enable virtual touch button support with touch displays + +To enter a script, go to `Configuration` =\> `Edit script` in the Tasmota web UI menu +Max script size (uses rules buffer): 1535 bytes + +Up to 50 variables (45 numeric and 5 strings, maybe changed by #define) +Freely definable variable names (all names are intentionally case sensitive) +Nested if,then,else up to a level of 8 +Math operators **+,-,\*,/,%,&,|,^** +all operators may be used in the op= form e.g. **+=** +Left right evaluation with optional brackets +all numbers are float +e.g. temp=hum\*(100/37.5)+temp-(timer\*hum%10) +no spaces allowed between math operations +Comparison operators **==,!=,\>,\>=,<,<=** +**and** , **or** support +hexadecimal numbers are supported with prefix 0x + +strings support **+** and **+=** operators +string comparison **==,!=** +max string size = 19 chars (default, can be increased or decreased by optional >D parameter) + +**Comments** start with **;** + +**Sections** defined: + +>**\>D ssize** +ssize = optional max stringsize (default=19) +define and init variables here, must be the first section, no other code allowed +**p:**vname specifies permanent vars (the number of permanent vars is limited by tasmota rules space (50 bytes) +numeric var=4 bytes, string var=lenght of string+1) +**t:**vname specifies countdown timers, if >0 they are decremented in seconds until zero is reached. see example below +**i:**vname specifies auto increment counters if >=0 (in seconds) +**m:**vname specifies a median filter variable with 5 entries (for elimination of outliers) +**M:**vname specifies a moving average filter variable with 8 entries (for smoothing data) +(max 5 filters in total m+M) optional another filter lenght (1..127) can be given after the definition. +filter vars can be accessed also in indexed mode vname[x] (index = 1...N, index 0 returns current array index pointer) +by this filter vars can be used as arrays + +>all variable names length taken together may not exceed 256 characters, so keep variable names as short as possible. +memory is dynamically allocated as a result of the D section. +copying a string to a number or reverse is supported + +>**\>B** +executed on BOOT time + +>**\>T** +executed on teleperiod time (**SENSOR** and **STATE**), get tele vars only in this section +remark: json variable names (like all others) may not contain math operators like - , you should set setoption64 1 to replace - with underscore + +>**\>F** +executed every 100 ms + +>**\>S** +executed every second + +>**\>E** +executed e.g. on power change and mqtt **RESULT** + +>**\>R** +executed on restart, p vars are saved automatically after this call + +special variables (read only): + +>**upsecs** = seconds since start +**uptime** = minutes since start +**time** = minutes since midnight +**sunrise** = sunrise minutes since midnight +**sunset** = sunset minutes since midnight +**tper** = teleperiod (may be set also) +**tstamp** = timestamp (local date and time) +**topic** = mqtt topic +**gtopic** = mqtt group topic +**prefixn** = prefix n = 1-3 +**pwr[x]** = tasmota power state (x = 1-N) +**pc[x]** = tasmota pulse counter value (x = 1-4) +**tbut[x]** = touch screen button state (x = 1-N) +**sw[x]** = tasmota switch state (x = 1-N) +>**pin[x]** = gpio pin level (x = 0-16) +**pn[x]** = pin number for sensor code x, 99 if none +**pd[x]** = defined sensor for gpio pin nr x none=999 +**gtmp** = global temperature +**ghum** = global humidity +**gprs** = global pressure +**pow(x y)** = calculates the power of x^y +**med(n x)** = calculates a 5 value median filter of x (2 filters possible n=0,1) +**int(x)** = gets the integer part of x (like floor) +**hn(x)** = converts x (0..255) to a hex nibble string +**st(svar c n)** = stringtoken gets the n th substring of svar separated by c +**s(x)** = explicit conversion from number x to string +**mqtts** = state of mqtt disconnected=0, connected>0 +**wifis** = state of wifi disconnected=0, connected>0 + +>**hours** = hours +**mins** = mins +**secs** = seconds +**day** = day of month +**wday** = day of week +**month** = month +**year** = year + +these variables are cleared after reading true +>**chg[var]** = true if a variables value was changed (numeric vars only) +**upd[var]** = true if a variable was updated +**boot** = true on BOOT +**tinit** = true on time init +**tset** = true on time set +**mqttc** = true on mqtt connect +**mqttd** = true on mqtt disconnect +**wific** = true on wifi connect +**wifid** = true on wifi disconnect + +system vars (for debugging) +>**stack** = stack size +**heap** = heap size +**ram** = used ram size +**slen** = script length +**micros** = running microseconds +**millis** = running milliseconds +**loglvl** = loglevel of script cmds, may be set also + +remarks: +if you define a variable with the same name as a special variable that special variable is discarded + +**Tasmota** cmds start with **=\>** +within cmds you can replace text with variables with **%varname%** +a single percent sign must be given as **%%** +**->** is equivalent but doesnt send mqtt or any weblog (silent execute, usefull to reduce traffic) + +**special** cmds: + +>**=\> print** prints to info log for debugging + +to save code space nearly no error messages are provided. However it is taken care of that at least it should not crash on syntax errors. +if a variable does not exist a **???** is given on commands +if a **SENSOR** or **STATUS** or **RESULT** message or a var does not exist the destination variable is NOT updated. + +2 possibilities for conditionals: +>**if** a==b +**and** x==y +**or** k==i +**then** => do this +**else** => do that +**endif** + +OR + +>**if** a==b +**and** x==y +**or** k==i **{** + => do this +**} else {** + => do that +**}** + +you may NOT mix both methods + +also possible e.g. + +>if var1-var2==var3*var4 +then + +remarks: +the last closing bracket must be on a single line +the condition may not be enclosed in brackets + +>**break** exits a section or terminates a for next loop +**dpx** sets decimal precision to x (0-9) +**svars** save permanent vars +**delay(x)** pauses x milliseconds (should be as short as possible) +**spin(x m)** set gpio pin x (0-16) to value m (0,1) only the last bit is used, so even values set the pin to zero and uneven values set the pin to 1 +**spinm(x m)** set pin mode gpio pin x (0-16) to mode m (input=0,output=1,input with pullup=2) +**ws2812(array)** copies an array (defined with m:name) to the WS2812 LED chain the array should be defined as long as the number of pixels. the color is coded as 24 bit RGB + +>**#name** names a subroutine, subroutines are called with **=#name** +**#name(param)** names a subroutines with a parameter is called with **=#name(param)** +subroutines end with the next '#' or '>' line or break, may be nested +params can be numbers or strings and on mismatch are converted + +>**for var from to inc** +**next** +specifies a for next loop, (loop count must not be less then 1) + +>**switch x** +**case a** +**case b** +**ends** +specifies a switch case selector (numeric or string) + +**sd card support** +enable by CARD_CS = gpio pin of card chip select (+ 10k flash) +\#define USE_SCRIPT_FATFS CARD_CS +sd card uses standard hardware spi gpios: mosi,miso,sclk +max 4 files open at a time +allows for e.g. logging sensors to a tab delimited file and then download (see example below) +the download of files may be executed in a kind of "multitasking" when bit 7 of loglvl is set (128+loglevel) +without multitasking 150kb/s (all processes are stopped during download), with multitasking 50kb/s (other tasmota processes are running) +script itself is also stored on sdcard with a default size of 4096 chars + + +enable sd card directory support (+ 1,2k flash) +\#define SDCARD_DIR +shows a web sdcard directory (submeu of scripter) where you can +upload and download files to/from sd card + + +>**fr=fo("fname" m)** open file fname, mode 0=read, 1=write (returns file reference (0-3) or -1 for error) +**res=fw("text" fr)** writes text to (the end of) file fr, returns number of bytes written +**res=fr(svar fr)** reads a string into svar, returns bytes read (string is read until delimiter \t \n \r or eof) +**fc(fr)** close file +**ff(fr)** flush file, writes cached data and updates directory +**fd("fname")** delete file fname +**flx(fname)** create download link for file (x=1 or 2) fname = file name of file to download +**fsm** return 1 if filesystem is mounted, (valid sd card found) + +extended commands (+0,9k flash) +\#define USE_SCRIPT_FATFS_EXT +>**fmd("fname")** make directory fname +>**frd("fname")** remove directory fname +>**fx("fname")** check if file fname exists +>**fe("fname")** execute script fname (max 2048 bytes, script file must start with '>' char on the 1. line) + + +**konsole script cmds** +>**script 1 or 0** switch script on or off +**script >cmdline** executes the script cmdline +can be used e.g. to set variables e.g. **script >mintmp=15** +more then one line may be executed seperated by a semicolon e.g. **script >mintmp=15;maxtemp=40** +script itself cant be set because the size would not fit the mqtt buffers + +**subscribe,unsubscribe** +>if \#defined SUPPORT_MQTT_EVENT command subscribe and unsubscribe are supported. in contrast to rules no event is generated but the event name specifies a variable defined in D section and this variable is automatically set on transmission of the subscribed item