-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
script language as an alternative to rules #5689
Comments
looks great! Much more intuitive (to me) |
Nicely thought out. Looks very good! |
Cool, will try! |
Looks nice and very usable. Proposal: Sometimes I'm still fighing with each single byte when using rules. |
@curzon01 ok, implementation is now nearly complete. (string catenation and string compare are now also supported) |
I believe this is what Norbert was trying to say.
vs.
eliminates "then" and "endif" saving 7 bytes of code space for each use of an if clause. |
ok, is implemented use either if, then,else,endif or if a==b { |
updated to current tasmota
|
@gemu It looks promising to me too! In your fork I noticed it replaces rules but does it still use the same Settings area memory allocations? If so it would be great if you provided a PR for implementation in Tasmota. Pls keep it as short as possible so without SML and other changes related to your fork as I like it to be as modular as possible. |
@arendst remark: |
Thx. As there were/are some issues with the dash (-) I will investigate the impact of a change to underscore (_) solving these issues too. |
Just released 6.5.0.11 with a user option to change the minus to underscore. Now enforcing underscore. |
Mhh, will generate many issues questions (breaks backwards compatibility) for nearly all Home Automation sytems. What do you think only to swap (via ifdef...) when script ruels are activated via #define? |
Agree partly as it will just delay the issues coming up. As the define is user configurable they can always change it back to "-". |
Yes, no problem for users who compile there own version. Our experience in Discord chat is that most users do use the provided prebuild ones. If the install the new version on a fresh device no standard setup described for the mainstream home automation solutions does work. |
I appreciate your work. Let's decide that if there too many related issues we'll change the default back (reluctantly). |
Yes, let see what happens. |
or have a settable user option to change this behavior? setoption64 ? |
As discussed with @Jason2866 I'll do a series of tests to see the impact on memory compared with rules. |
SetOption64 it will be. Default 0 keeps "-", 1 will be "_". No other choices allowed. Why didn't I come up with this ... |
So by using setoption for keeping the old behavior we change one type of issues ("hey, sensors no longer work in my home automation") to another ("hey, I can't use new rule scripts with my sensor"). Breaking rev-comp is inconvenient, but sometimes it is justified, especially if by making this change other issues related to -/_ can be solved, like @arendst wrote. Another edit: and with this setoption, we'll have two groups of users to keep separate docs in rules. Or we will have to add remarks everywhere that syntax for sensors names in triggers etc depend on a setoption. Just to save users from updating their home automation settings by simply replacing - with _ and doing a restart. IMO keeping the option to choose between the two behaviors will keep creating issues. |
…sensor index separator 6.5.0.11 20190517 * Add command SetOption64 0/1 to switch between "-" or "_" as sensor index separator impacting DS18X20, DHT, BMP and SHT3X sensor names (#5689)
At least now they can change it on the fly ... |
Add initial support for Scripts as replacement for Rules. Default disabled but can be enabled in my_user_config.h (#5689)
That behaviour is intended. |
Can I disassociate the button and the relais in script language like it is possilble with rules? I can't find a way to use the buttons only in my script without toggling the relais. |
I see the answer to the question by @spakecdk , but I'm still having trouble trying to figure out how to set a variable from an MQTT message that originates from somewhere other than the local Tasmota device running the script. For my specific application, I want to be able to change a thermostat setpoint in the Tasmota script from another MQTT device/message. With Rules, this could be done by sending a message to cmnd/mqttTopic/mem or cmnd/mqttTopic/var. By reading the scripting documentation, it might seem that this could be accomplished in some fashion by using the subscribe command (which I have compiled into the firmware) and listening in the >E section of the code. Unfortunately, I've tried dozens of different combinations and have been unsuccessful. Any pointers from anyone on how to accomplish this in the scripting engine? Thanks! |
You can send a mqtt message like cmnd/tasmota/Script >Temp=22 to change the var Temp in your Script. This works for me. You don't need to add something to your Script. |
If you use buttontopic, you have to be aware that when mqtt or wifi got disconnected, your button will start controlling relay1. The fallback feature. |
Thank you both for the response. I was eventually able to write to the variable using the subscribe method. But the the way that @giessener showed is much more straight forward and worked perfectly. This is the way I have it set up now. Plus I don't have to wory about making sure Tasmota is subscribed to a topic. Thanks for the help! |
@ascillato I know that! The buttontopic is a workaround for me. Do you have a better method to control things in the script without toggle the relay? |
@giessener I don't know. May be @gemu2015 knows |
one option would be to omit the tasmota setup and handle iOs yourself. >D or you only define the relays in tasmota and the button in scripter >D >B >F |
Is there a way to compare strings? E.g. myText = "Hello World" |
@gemu2015 I'm unsure about a feature of scripts described in the docu called "dynamic or self modifying code":
This didn't work for me. Can you please explain it in more detail? Example:
Am I using it wrong? |
I love the scripting - much more logical flow (at least for people with programming background). I have one project up and running where "rules" approach was failing due to an inacceptable lag. Scripting rules! ;-)
|
@martinvana Probably it is better to ask directly for help in gemu2015 github |
@martinvana the notation of JSON access is equivalent to rules the # char separates elements of the JSON payload the >T section is called from sensors (TelePeriod JSON messages) the >E section ist called from results (RESULT JSON messages) if you want to set a variable in a script you may simply set it by sending |
Yay! Thanks @gemu2015 ! Once I get through this "learning experience" - where is the best place to share my example(s) to augment the documentation? |
Funny... I have just started to tinker with scripts and got stuck at the same spot as you as I want to send data to my tasmota device... Just a couple of hours after you. I have not managed to send a correct MQTT message using home assistant dev tools but with a stand alone MQTT client I can set a variable using the following... Topic: cmnd/tasmota_BExxxx/Script Replace tasmota_BExxxx with whatever you have as topic in your MQTT configuration. |
@mattiassjogren Thank you! |
Is there any possibility to receive and decode MQTT messages generated by Domoticz? I am trying to connect BECA (Tuya) thermostat to domoticz via MQTT. I have success with reporting to domoticz but I am not able to find way how to set thermostat values from Domoticz. Thanks. |
Sorry, how can I set the timezone in the script? And in what section? |
I struggle with the command "swb" which I interpreted as binary. |
swb() writes a single byte to the serial port swb(0x80) |
Just did exactly this and just got 00 00 00 in "CuteCom" on the monitoring Serial USB-Device, so somehow this is not working as expected.
Output in CuteCom: |
swb() is now fixed |
Good Morning, Can you may have a closer look? |
i did test this function and it worked like expected. also your previous 0 0 0 was not what it should. the previous version by error always emitted FF FF FF. and there should not be 2 characters per swb() check your com settings |
I have Wemos D1 mini and can't read values (only in script! of DS18b20 on D0 GPIO16 and analog value of A0 connected to Capactive soil moisture sensor v 1.2 SENSOR = {"Time":"2022-05-29T14:57:55","ANALOG":{"pH0":13.55},"DS18B20":{"Id":"0000000C2CDF","Temperature":22.6},"TempUnit":"C"} value of analog in Rules (not Scripting) is shown under ANALOG#pH0. Temperature not checked Tasmota 11.1.0 How to display values of PH and TEMPERATURE in tasmota Script ? |
json MQTT values must be evaluated in >T (or >E for status) section only, you need a helper variable as intermediate storage >T ... |
Works ! . Thanks |
i always disliked the syntax of rules. therefore i developed a script language.
see initial doku below. it is now default on my fork. it is work in progress and not yet ready for pr but works quite well already. you may give it a try =>https://github.com/gemu2015/Sonoff-Tasmota
Script Language for Tasmota
As an alternative to rules. (about 14,2k flash size, variable ram size)
In submenu Configuration => edit script
1535 bytes max script size (uses rules buffer)
to enable:
#define USE_SCRIPT
#undef USE_RULES
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
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:
special variables (read only):
these variables are cleared after reading true
system vars (for debugging)
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 %%
special cmds:
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:
OR
you may NOT mix both methods
also possible e.g.
remarks:
the last closing bracket must be on a single line
the condition may not be enclosed in brackets
konsole script cmds
example script
meant to show some of the possibilities
(actually this code ist too large)
>D
; define all vars here
p:mintmp=10 (p:means permanent)
p:maxtmp=30
t:timer1=30 (t:means countdown timer)
t:mt=0
i:count=0 (i:means auto counter)
hello="hello world"
string="xxx"
url="[192.168.178.86]"
hum=0
temp=0
timer=0
dimmer=0
sw=0
rssi=0
param=0
col=""
ocol=""
chan1=0
chan2=0
chan3=0
ahum=0
atemp=0
tcnt=0
hour=0
>B
string=hello+"how are you?"
=>print BOOT executed
=>print %hello%
=>mp3track 1
; list gpio pin definitions
for cnt 0 16 1
tmp=pd[cnt]
=>print %cnt% = %tmp%
next
; get gpio pin for relais 1
tmp=pn[21]
=>print relais 1 is on pin %tmp%
; pulse relais over raw gpio
spin(tmp 1)
delay(100)
spin(tmp 0)
; raw pin level
=>print level of gpio1 %pin[1]%
; pulse over tasmota cmd
=>power 1
delay(100)
=>power 0
>T
hum=BME280#Humidity
temp=BME280#Temperature
rssi=Wifi#RSSI
string=SleepMode
if chg[rssi]>0
then =>print rssi changed to %rssi%
endif
if temp>30
and hum>70
then =>print damn hot!
endif
>S
; every second but not completely reliable time here
; use upsecs and uptime or best t: for reliable timers
; call subrountines with parameters
=#sub1("hallo")
=#sub2(999)
; stop timer after expired
if timer1==0
then timer1=-1
=>print timer1 expired
endif
; auto counter with restart
if count>=10
then =>print 10 seconds over
count=0
endif
if upsecs%5==0
then =>print %upsecs% (every 5 seconds)
endif
; not recommended for reliable timers
timer+=1
if timer>=5
then =>print 5 seconds over (may be)
timer=0
endif
dimmer+=1
if dimmer>100
then dimmer=0
endif
=>dimmer %dimmer%
=>WebSend %url% dimmer %dimmer%
; show on display
dprec0
=>displaytext [c1l1f1s2p20] dimmer=%dimmer%
=>print %upsecs% %uptime% %time% %sunrise% %sunset% %tstamp%
if time>sunset
and time< sunrise
then
; night time
if pwr[1]==0
then =>power1 1
endif
else
; day time
if pwr[1]>0
then =>power1 0
endif
endif
; clr display on boot
if boot>0
then =>displaytext [z]
endif
; frost warning
if temp<0
and mt<=0
then =#sendmail("frost alert")
; alarm only every 5 minutes
mt=300
=>mp3track 2
endif
; var has been updated
if upd[hello]>0
then =>print %hello%
endif
; send to Thingspeak every 60 seconds
; average data in between
if upsecs%60==0
then
ahum/=tcnt
atemp/=tcnt
=>Websend [184.106.153.149:80]/update?key=PYUZMVWCICBW492&field1=%atemp%&field2=%ahum%
tcnt=0
atemp=0
ahum=0
else
ahum+=hum
atemp+=temp
tcnt+=1
endif
hour=int(time/60)
if chg[hour]>0
then
; exactly every hour
=>print full hour reached
endif
if time>5 {
=>print more then 5 minutes after midnight
} else {
=>print less then 5 minutes after midnight
}
; publish abs hum every teleperiod time
if mqtts>0
and upsecs%tper==0
then
; calc abs humidity
tmp=pow(2.718281828 (17.67*temp)/(temp+243.5))
tmp=(6.112*tmp*hum*18.01534)/((273.15+temp)*8.31447215)
=>Publish tele/%topic%/SENSOR {"Script":{"abshum":%tmp%}}
endif
; subroutines
#sub1(string)
=>print sub1: %string%
#sub2(param)
=>print sub2: %param%
#sendmail(string)
=>sendmail [smtp.gmail.com:465:user:passwd:sender@gmail.de:rec@gmail.de:alarm] %string%
>E
=>print event executed!
; check if switch changed state
sw=sw[1]
if chg[sw]>0
then =>power1 %sw%
endif
hello="event occured"
; check for Color change (Color is a string)
col=Color
; color change needs 2 string vars
if col!=ocol
then ocol=col
=>print color changed %col%
endif
; or check change of color channels
chan1=Channel[1]
chan2=Channel[2]
chan3=Channel[3]
if chg[chan1]>0
or chg[chan2]>0
or chg[chan3]>0
then => color has changed
endif
; compose color string for red
col=hn(255)+hn(0)+hn(0)
=>color %col%
>R
=>print restarting now
a real example
epaper 29 with sgp30 and bme280
some vars are set from iobroker
DisplayText substituted to save script space
>D
hum=0
temp=0
press=0
ahum=0
tvoc=0
eco2=0
zwz=0
wr1=0
wr2=0
wr3=0
otmp=0
pwl=0
tmp=0
DT="DisplayText"
; preset units in case they are not available
punit="hPa"
tunit="C"
>B
;reset auto draw
=>%DT% [zD0]
;clr display and draw a frame
=>%DT% [x0y20h296x0y40h296]
>T
; get tele vars
temp=BME280#Temperature
hum=BME280#Humidity
press=BME280#Pressure
tvoc=SGP30#TVOC
eco2=SGP30#eCO2
ahum=SGP30#aHumidity
tunit=TempUnit
punit=PressureUnit
>S
// update display every teleperiod time
if upsecs%tper==0
then
dprec2
=>%DT% [f1p7x0y5]%temp% %tunit%
=>%DT% [p5x70y5]%hum% %%[x250y5t]
=>%DT% [p11x140y5]%press% %punit%
=>%DT% [p10x30y25]TVOC: %tvoc% ppb
=>%DT% [p10x160y25]eCO2: %eco2% ppm
=>%DT% [p10c26l5]ahum: %ahum% g^m3
dprec0
=>%DT% [p25c1l5]WR 1 (Dach) : %wr1% W
=>%DT% [p25c1l6]WR 2 (Garage): %-wr3% W
=>%DT% [p25c1l7]WR 3 (Garten): %-wr2% W
=>%DT% [p25c1l8]Aussentemperatur: %otmp% C
=>%DT% [x170y95r120:30f2p6x185y100] %pwl% %%
; now update screen
=>%DT% [d]
endif
>E
>R
another real example
ILI 9488 color LCD Display shows various energy graphs
display switches on and off with proximity sensor
BMP280 and vl5310x
some vars are set from iobroker
>D
temp=0
press=0
zwz=0
wr1=0
wr2=0
wr3=0
otmp=0
pwl=0
tmp=0
dist=0
DT="DisplayText"
punit="hPa"
tunit="C"
hour=0
>B
=>%DT% [z]
// define 2 graphs, 2. has 3 tracks
=>%DT% [zCi1G2656:5:20:400:80:1440:-5000:5000:3Ci7f3x410y20]+5000 W[x410y95]-5000 W [Ci7f1x70y3] Zweirichtungsz~80hler - 24 Stunden
=>%DT% [Ci1G2657:5:120:400:80:1440:0:5000:3Ci7f3x410y120]+5000 W[x410y195]0 W [Ci7f1x70y103] Wechselrichter 1-3 - 24 Stunden
=>%DT% [Ci1G2658:5:120:400:80:1440:0:5000:16][Ci1G2659:5:120:400:80:1440:0:5000:5]
=>%DT% [f1s1b0:260:260:100:50:2:11:4:2:Rel 1:b1:370:260:100:50:2:11:4:2:Dsp off:]
=>mp3volume 100
=>mp3track 4
>T
; get some tele vars
temp=BMP280#Temperature
press=BMP280#Pressure
tunit=TempUnit
punit=PressureUnit
dist=VL53L0X#Distance
; check proximity sensor to switch display on/off
; to prevent burn in
if dist>300
then
if pwr[2]>0
then
=>power2 0
endif
else
if pwr[2]==0
then
=>power2 1
endif
endif
>S
; update graph every teleperiod
if upsecs%tper==0
then
dprec2
=>%DT% [f1Ci3x40y260w30Ci1]
=>%DT% [Ci7x120y220t]
=>%DT% [Ci7x180y220T]
=>%DT% [Ci7p8x120y240]%temp% %tunit%
=>%DT% [Ci7x120y260]%press% %punit%
=>%DT% [Ci7x120y280]%dist% mm
dprec0
=>%DT% [g0:%zwz%g1:%wr1%g2:%-wr2%g3:%-wr3%]
if zwz>0
then
=>%DT% [p-8x410y55Ci2Bi0]%zwz% W
else
=>%DT% [p-8x410y55Ci3Bi0]%zwz% W
endif
=>%DT% [p-8x410y140Ci3Bi0]%wr1% W
=>%DT% [p-8x410y155Ci16Bi0]%-wr2% W
=>%DT% [p-8x410y170Ci5Bi0]%-wr3% W
endif
; chime every full hour
hour=int(time/60)
if chg[hour]>0
then =>mp3track 4
endif
>E
>R
The text was updated successfully, but these errors were encountered: