Skip to content
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

Closed
gemu2015 opened this issue Apr 23, 2019 · 59 comments
Closed

script language as an alternative to rules #5689

gemu2015 opened this issue Apr 23, 2019 · 59 comments
Labels
enhancement Type - Enhancement that will be worked on

Comments

@gemu2015
Copy link
Contributor

gemu2015 commented Apr 23, 2019

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:

>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)

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

>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)
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
int(x) = gets the integer part of x (like floor)
hn(x) = converts x (0..255) zu a hex nibble 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 %%

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
dprecx 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)

#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)

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

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

@joba-1
Copy link
Contributor

joba-1 commented Apr 23, 2019

looks great! Much more intuitive (to me)

@blakadder
Copy link
Collaborator

Nicely thought out. Looks very good!

@blakadder blakadder added the feature request (devs?) Action - awaiting response from developers label Apr 23, 2019
@Jason2866
Copy link
Collaborator

Cool, will try!

@ascillato2 ascillato2 added enhancement Type - Enhancement that will be worked on and removed feature request (devs?) Action - awaiting response from developers labels Apr 24, 2019
@curzon01
Copy link
Contributor

Looks nice and very usable.

Proposal: Sometimes I'm still fighing with each single byte when using rules.
Words like then and endif cost valuable script space. Would it be possible using { } for blocks in general independently if the leading keyword is if or else?

@gemu2015
Copy link
Contributor Author

@curzon01
i don't see what you mean. you can put any code lines between then and endif. its like on endon but much more flexible.

ok, implementation is now nearly complete. (string catenation and string compare are now also supported)
needs a lot of testing now before pr

@meingraham
Copy link
Collaborator

@gemu2015 ,

I believe this is what Norbert was trying to say.

if (condition) then
  action(s)
else
  alternate action(s)
endif

vs.

if (condition) {
  action(s)
}
else {
  alternate action(s)
}

eliminates "then" and "endif" saving 7 bytes of code space for each use of an if clause.

@gemu2015
Copy link
Contributor Author

gemu2015 commented Apr 25, 2019

ok, is implemented use either if, then,else,endif or

if a==b {
action(s)
} else {
alternate action(s)
}
by the way in the above notation if you count all chars you save only 3 bytes!

@gemu2015
Copy link
Contributor Author

gemu2015 commented Apr 27, 2019

updated to current tasmota
here is a wemos binary +doku for testing:https://www.dropbox.com/s/y2vu0890ur02h92/wemos-d1%2Bdoku.zip?dl=0

  • updated doku now supporting subroutines, for next loops etc

This was referenced Apr 30, 2019
@arendst
Copy link
Owner

arendst commented May 15, 2019

@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.

@gemu2015
Copy link
Contributor Author

@arendst
yes it replaces rules and uses the same memory in settings.
i am constantly expanding the capabilities and optimizing the code but will provide a pr in the next week or so
i would have preferred having a few beta testers to cope with more possible use cases then i have.

remark:
one prerequisite is that sensor names may not contain any math operators. i had to replace the '-' from sht3 drivers with '_'. (only digits, letters and underscore should be allowed in sensor names)
don't know if any other sensors are affected too.

@arendst
Copy link
Owner

arendst commented May 17, 2019

Thx.

As there were/are some issues with the dash (-) I will investigate the impact of a change to underscore (_) solving these issues too.

@arendst
Copy link
Owner

arendst commented May 17, 2019

Just released 6.5.0.11 with a user option to change the minus to underscore.

Now enforcing underscore.

@Jason2866
Copy link
Collaborator

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?

@arendst
Copy link
Owner

arendst commented May 17, 2019

Agree partly as it will just delay the issues coming up.

As the define is user configurable they can always change it back to "-".

@Jason2866
Copy link
Collaborator

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.
On the other side i do agree sometimes cuts have to been made to get rid of old stuff.
Your project, your decision! We can handle the upcoming questions in Discord 😀

@arendst
Copy link
Owner

arendst commented May 17, 2019

I appreciate your work.

Let's decide that if there too many related issues we'll change the default back (reluctantly).

@Jason2866
Copy link
Collaborator

Yes, let see what happens.

@gemu2015
Copy link
Contributor Author

or have a settable user option to change this behavior? setoption64 ?

@effelle
Copy link
Contributor

effelle commented May 17, 2019

As discussed with @Jason2866 I'll do a series of tests to see the impact on memory compared with rules.
But yes, I like this new syntax. Thanks @gemu2015!

@arendst
Copy link
Owner

arendst commented May 17, 2019

SetOption64 it will be.

Default 0 keeps "-", 1 will be "_". No other choices allowed.

Why didn't I come up with this ...

@jziolkowski
Copy link
Contributor

jziolkowski commented May 17, 2019

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.

arendst added a commit that referenced this issue May 17, 2019
…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)
@arendst
Copy link
Owner

arendst commented May 17, 2019

At least now they can change it on the fly ...

arendst added a commit that referenced this issue May 18, 2019
Add initial support for Scripts as replacement for Rules. Default disabled but can be enabled in my_user_config.h (#5689)
@ascillato
Copy link
Contributor

That behaviour is intended.

@giessener
Copy link

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.

@bkirkman
Copy link

bkirkman commented Jan 3, 2020

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!

@giessener
Copy link

giessener commented Jan 4, 2020

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.
I also managed to disassociate the Buttons from the Relais by setting the buttontopic to something useless.

@ascillato
Copy link
Contributor

ascillato commented Jan 4, 2020

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.

@bkirkman
Copy link

bkirkman commented Jan 4, 2020

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!

@giessener
Copy link

giessener commented Jan 4, 2020

@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?

@ascillato
Copy link
Contributor

@giessener I don't know. May be @gemu2015 knows

@gemu2015
Copy link
Contributor Author

gemu2015 commented Jan 4, 2020

one option would be to omit the tasmota setup and handle iOs yourself.

>D
pin0=0
>B
; set GPIO zero as input with pullup
spinm(0 2)
; set gpio 13 as relay output
spinm(13 1)
>F
pin0=pin[0]
if chg[pin0]>0
and pin0==0
then
print pin changed
print toggle relay
if pin[13]>0
then spin(13 0)
else spin(13 1)
endif
endif

or you only define the relays in tasmota and the button in scripter

>D
pin0=0

>B
; set GPIO zero as input with pullup
spinm(0 2)
; relay 1 defined in tasmota

>F
pin0=pin[0]
; if pin changed
if chg[pin0]>0
; and pressed
and pin0==0
then
; toggle power
if pwr[0]==0
then ->power0 1
else ->power0 0
endif
endif

@paolomorabito
Copy link

Is there a way to compare strings? E.g.

myText = "Hello World"
if myText.contains("World") then .... else ....

@maxela
Copy link
Contributor

maxela commented Mar 2, 2020

@gemu2015 I'm unsure about a feature of scripts described in the docu called "dynamic or self modifying code":

=(svar) executes a routine whose name is passed as a string in a variable

This didn't work for me. Can you please explain it in more detail?

Example:

>D
svar=""

>B
svar="sub1"

>S
=(svar)

#sub1
=>print sub1 was called
#

Am I using it wrong?

@martinvana
Copy link

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! ;-)
Now I reached a point when I may need help:
Compiled with (among other) #define USE_SCRIPT_STATUS
Yet I didn't figure out how to trigger the >U section.
All I am trying to do is setting a script variable from a JSON. Didn't find a complete example or good definition of syntax anywhere.
I am doing my best to send a JSON message either through Tasmota Console or through "Publish a Packet" in Home Assistant Developer Tools panel (MQTT)
cmnd/PIR_entrance/STATE {"TwilightRange":44}
(Not sure whether there should be "=" before the left curly bracket, tried all combinations.
Also the formatting with "hash" like the one from an example below isn't clear to me.
rssi=Wifi#RSSI
What would be corresponding JSON packet to match?
However, this is not my imminent problem since the code in the >U section doesn't even get triggered. When I send a JSON message, the teleperiod ">T" section get executed, though.
Simplified script is below. I guess I am missing something fundamental?
(The >P >b >S sections are not exactly relevant - except for fixing my ego that the code actually can do anything meaningful ;-) )
Thanks - Martin

>D	; define all vars here
; PIR_Light attempt 20200705_2111
: Just (desperate) testing how to set variable out from JSON payload
t_minute=59
ssid=""
tm_twlt=25

>B ; Boot section
print =========== >B section  =============
dp0
=>print Power1=%pwr[1]%

>T
print =========== >T section  =============
=>Publish tele/%topic%/LIGHT {"Script": {"TwilightRange":%tm_twlt%}}

; Read the status JSON payload
>U
print =========== >U section JSON payload  =============
rssi=Wifi#RSSI
print RSSI= %rssi%
tm_twlt=Time#TwilightRange
print >U %tm_twlt%

>P
=>print Power1=%pwr[1]%
>b
if bt[1]==0 {  
 print =========== >b section  =============
 print TwilightRange %tm_twlt%
}

>S
if t_minute<=0 {
 print Minute Passed
 t_minute=59
} else {
 t_minute-=1
}
#

@Jason2866
Copy link
Collaborator

@martinvana Probably it is better to ask directly for help in gemu2015 github
https://github.com/gemu2015/Sonoff-Tasmota

@gemu2015
Copy link
Contributor Author

gemu2015 commented Jul 6, 2020

@martinvana
ok doku is completely misleading according >U. >U is just for receiving JSON payloads coming from status cmds send by the script itself or the console. e.g
->status 11
generates a JSON from which you may get
rssi=Wifi#RSSI

the notation of JSON access is equivalent to rules the # char separates elements of the JSON payload
in contrast to rules however the variables are case sensitiv.

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
e.g.
script >tm_twlt=30 (also from console)

@martinvana
Copy link

Yay! Thanks @gemu2015 !
the status 11 typed in console sure triggers the >U. Need to learn how to parse with the "#" but that is secondary. Just less of a "mystery".
Console entry script >tm_twlt=30 does set the variable. I can keep writing and debugging parameterized script :-)
The remaining point I am missing: How to achieve the same from JSON payload?
What should be the MQTT prefix and topic? And how to format the payload?

Once I get through this "learning experience" - where is the best place to share my example(s) to augment the documentation?
Thanks again!

@mattiassjogren
Copy link

mattiassjogren commented Jul 6, 2020

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
Payload: >tm_twlt=30

Replace tasmota_BExxxx with whatever you have as topic in your MQTT configuration.

This is how it looks using MQTTLens on a Chromebook...
Screenshot 2020-07-06 at 23 03 23

@martinvana
Copy link

@mattiassjogren Thank you!
Many details and I never got all of the combinations right
topic: cmnd/#/Script (where # substitutes the correct topic)
and payload without the curly braces formatted like you suggested was the answer.
Thanks!
cmnd/PIR_entrance/Script >tm_twlt=33

@saidlm
Copy link

saidlm commented Aug 9, 2020

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.
Well I know there is a way to do it via NodeRed but it looks to me too complicated and I am looking for another "direct" way instead.

Thanks.

@giovcris
Copy link

Sorry, how can I set the timezone in the script? And in what section?
I have the same doubt to release commands as "Setoption X" and others that usually I send by console
Thanks for the answer

@freifunkerffm
Copy link

I struggle with the command "swb" which I interpreted as binary.
Because I need to send OP-Codes in HEX like 80 83 87 (Decimal 128 131 131) via serial to control a device.
Unfortunately it looks like that "swb" is clinging somehow to the ASCII Code.
Is there a way to send hexadecimal values via serial triggered by script?
Before you ask, if I send this OP-Codes via "CuteCom" Terminal Program on my PC in HEX it woks so it is definitely Tasmota / Script related.
Thanks for an hint.

@gemu2015
Copy link
Contributor Author

swb() writes a single byte to the serial port
so your sequence would be sent by

swb(0x80)
swb(0x83)
swb(0x87)

@freifunkerffm
Copy link

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.
As an example my current script running on: Tasmota Version 2022.01.3(tasmota)-2_7_4_9(2022-01-25T09:33:35)

D
RCL=0

B
so(3 1 115200)
delay(50)
=>print Serial setup done so(3 1 115200)

S
if upd[RCL]>0
then
=>print Transmit received
swb(0x80)
delay(50)
swb(0x83)
delay(50)
swb(0x87)
delay(50)
endif

Output in CuteCom:
00000000 00 00 00

@gemu2015
Copy link
Contributor Author

swb() is now fixed

@freifunkerffm
Copy link

Good Morning,
I have sourced Tasmota again from GitHub and compiled again a version that is supporting script this morning as the status has changed to "merged".
Unfortunately the HEX-output has now changed from "00 00 00" to something different but also all the same:
00000000 c0 4e c0 4e c0 4e .N.N.N

Can you may have a closer look?
Thanks

@gemu2015
Copy link
Contributor Author

gemu2015 commented Apr 1, 2022

i did test this function and it worked like expected.
something must be wrong with your setup.

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

@gbananachewicz
Copy link

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 ?

@gemu2015
Copy link
Contributor Author

json MQTT values must be evaluated in >T (or >E for status) section only, you need a helper variable as intermediate storage
>D
ph=0

>T
ph=ANALOG#pH0

...

@gbananachewicz
Copy link

Works ! . Thanks

Repository owner locked as resolved and limited conversation to collaborators May 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement Type - Enhancement that will be worked on
Projects
None yet
Development

No branches or pull requests