stefanbode / Sonoff-Tasmota

Provide ESP8266 based itead Sonoff with Web, MQTT and OTA firmware using Arduino IDE, enhanced with I2C options
GNU General Public License v3.0
126 stars 40 forks source link

Rules: IF ELSE ELSEIF and AND OR Support #188

Closed flashtel closed 5 years ago

flashtel commented 5 years ago
### BUG DESCRIPTION Hi, I've compiled with the following #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) #define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+4k2 code, -332 bytes mem) I've tried the most basic rules. 20:23:19 MQT: stat/------/house/bathroom/RESULT = {"Rule1":"ON","Once":"OFF","StopOnError":"OFF","Free":427,"Rules":"on system#boot do var1 0 endon on POWER1#STATE do if (var1!=1) power3 on endif endon"} 20:23:24 CMD: power1 on 20:23:24 Wait for Motorstop 500 20:23:25 MQT: stat/my/house/bathroom/RESULT = {"POWER1":"ON"} 20:23:25 MQT: stat/my/house/bathroom/POWER1 = ON 20:23:25 RUL: POWER1#STATE performs "if (var1!=1) power3 on endif" 20:23:25 Shutter unknown ### REQUESTED INFORMATION _Make sure these boxes are checked before submitting your issue. Thank you_ **FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED** - [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md) - [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues) - [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting) - [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers) - [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4) - [ ] Device used (i.e. Sonoff Basic) : 4chProR1 - [ ] Tasmota binary firmware version number used : Sonoff-Tasmota 6.6.0.10 stb-1.11 by Theo Arends/ Selfcompiled - [ ] Development IDE - Compiler / Upload tools used : Arduino 1.8.5 (OSX) - [ ] Provide the output of command ``status 0`` : ``` STATUS 0 OUTPUT HERE: 20:30:38 CMD: status 0 20:30:38 MQT: stat/my/house/bathroom/STATUS = {"Status":{"Module":23,"FriendlyName":["Sonoff","Sonoff2","Sonoff3","Sonoff4"],"Topic":"house/bathroom","ButtonTopic":"0","Power":0,"PowerOnState":3,"LedState":1,"LedMask":"FFFF","SaveData":1,"SaveState":1,"SwitchTopic":"0","SwitchMode":[0,0,0,0,0,0,0,0],"ButtonRetain":0,"SwitchRetain":0,"SensorRetain":0,"PowerRetain":0}} 20:30:38 MQT: stat/my/house/bathroom/STATUS1 = {"StatusPRM":{"Baudrate":115200,"GroupTopic":"sonoffs","OtaUrl":"http://10.0.12.220:80/ota/sonoff.4chpro.bin","RestartReason":"Software/System restart","Uptime":"0T00:40:41","StartupUTC":"2019-09-15T11:49:57","Sleep":50,"CfgHolder":259,"BootCount":7,"SaveCount":49,"SaveAddress":"FB000"}} 20:30:38 MQT: stat/my/house/bathroom/STATUS2 = {"StatusFWR":{"Version":"6.6.0.10 stb-1.11(sonoff)","BuildDateTime":"2019-09-15T19:24:51","Boot":31,"Core":"2_5_0","SDK":"3.0.0-dev(c0f7b44)"}} 20:30:38 MQT: stat/my/house/bathroom/STATUS3 = {"StatusLOG":{"SerialLog":2,"WebLog":2,"SysLog":0,"LogHost":"10.0.12.220","LogPort":514,"SSId":["flashtwo",""],"TelePeriod":300,"Resolution":"558180C0","SetOption":["0000C009","280500000100060000005A64000000000000","C0000000"]}} 20:30:38 MQT: stat/my/house/bathroom/STATUS4 = {"StatusMEM":{"ProgramSize":541,"Free":460,"Heap":20,"ProgramFlashSize":1024,"FlashSize":1024,"FlashChipId":"144051","FlashMode":3,"Features":["00000809","8FC00287","003683A1","22B617CD","01001BC0","00000001"],"Drivers":"1,2,3,4,6,8,9,10,12,16,18,19,20,21,22,24","Sensors":"1,2,3,4,5,6,7,8,9,10,14,15,17,18,20,22,26,34"}} 20:30:38 MQT: stat/my/house/bathroom/STATUS5 = {"StatusNET":{"Hostname":"house/bathroom-0249","IPAddress":"10.0.12.34","Gateway":"10.0.12.1","Subnetmask":"255.255.255.0","DNSServer":"8.8.8.8","Mac":"60:01:94:97:E0:F9","Webserver":2,"WifiConfig":4}} 20:30:38 MQT: stat/my/house/bathroom/STATUS6 = {"StatusMQT":{"MqttHost":"10.0.12.220","MqttPort":1883,"MqttClientMask":"DVES_%06X","MqttClient":"DVES_97E0F9","MqttUser":"DVES_USER","MqttCount":1,"MAX_PACKET_SIZE":1000,"KEEPALIVE":30}} 20:30:38 MQT: stat/my/house/bathroom/STATUS7 = {"StatusTIM":{"UTC":"Sun Sep 15 12:30:38 2019","Local":"Sun Sep 15 20:30:38 2019","StartDST":"Sun Mar 31 02:00:00 2019","EndDST":"Sun Oct 27 03:00:00 2019","Timezone":"+08:00","Sunrise":"13:26","Sunset":"02:04"}} 20:30:38 MQT: stat/my/house/bathroom/STATUS10 = {"StatusSNS":{"Time":"2019-09-15T20:30:38","Epoch":1568550638,"SHUTTER-1":{"position":100, "direction":0},"SHUTTER-2":{"position":0, "direction":0}}} 20:30:38 MQT: stat/my/house/bathroom/STATUS11 = {"StatusSTS":{"Time":"2019-09-15T20:30:38","Epoch":1568550638,"Uptime":"0T00:40:41","UptimeSec":2441,"Heap":20,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"MqttCount":1,"POWER1":"OFF","POWER2":"OFF","POWER3":"OFF","POWER4":"OFF","Wifi":{"AP":1,"SSId":"flashtwo","BSSId":"04:18:D6:00:F8:1E","Channel":1,"RSSI":94,"LinkCount":1,"Downtime":"0T00:00:05","DeepSleep":0,"Heap":21216}}} ``` - [ ] Provide the output of console when you experience your issue if apply : _(Please use_ ``weblog 4`` _for more debug information)_ ``` CONSOLE OUTPUT HERE: 20:31:32 CMD: weblog 4 20:31:32 MQT: stat/my/house/bathroom/RESULT = {"WebLog":4} 20:31:33 CFG: Saved to flash at FA, Count 50, Bytes 4100 20:31:50 CMD: power1 on 20:31:50 SRC: WebConsole from 10.0.12.56 20:31:50 Switched relay: 1 by I 20:31:50 Wait for Motorstop 500 20:31:50 Shutter 0: Target: 20000, powerstatelocal 1 20:31:50 MQT: stat/my/house/bathroom/RESULT = {"POWER1":"ON"} 20:31:50 MQT: stat/my/house/bathroom/POWER1 = ON 20:31:50 RUL: POWER1#STATE performs "if (var1!=1) power3 on endif" 20:31:50 SRC: Rule 20:31:50 Shutter unknown 20:31:51 MQT: stat/my/house/bathroom/RESULT = {"Command":"Unknown"} 20:31:51 Shutter 0: Real Pos. 20000, Stoppos: 100, relay: 0, direction 1, pulsetimer: 0, rtcshutter: 0.2 [s], operationtime 0 20:31:51 MQT: stat/my/house/bathroom/SHUTTER1 = 100 20:31:51 SRC: Shutter 20:31:51 Switched relay: 1 by Shutter 20:31:51 MQT: stat/my/house/bathroom/RESULT = {"POWER1":"OFF"} 20:31:51 MQT: stat/my/house/bathroom/POWER1 = OFF 20:31:51 MQT: tele/my/house/bathroom/RESULT = {"SHUTTER-1":{"position":100, "direction":0}} ``` ### TO REPRODUCE _Steps to reproduce the behavior:_ rule1 on system#boot do var1 0 endon on POWER1#STATE do if (var1!=1) power3 on endif endon power1 on ### EXPECTED BEHAVIOUR _A clear and concise description of what you expected to happen._ if statement should be processed in rule, power3 should turn on ### SCREENSHOTS _If applicable, add screenshots to help explain your problem._ ### ADDITIONAL CONTEXT _Add any other context about the problem here._ I'm using a 4ch-pro R1 with a shutter (shutter-2) and an awning window (shutter-1), which also has an actuator on it. I need to build logic such that command window open (shutter-1), checks to see "if" shutter is open (shutter-2), then open window (shutter-1), elseif open shutter (shutter-2), then open window (shutter-1). command shutter close )shutter-2) checks to see "if" window is closed (shutter-1), then close shutter (shutter-2), elseif close window (shutter-1), then close shutter (shutter-2). I"m not sure if there is a way to do this without the IF ELSE ELSEIF and AND OR Support, I was thinking I might be able to build it with the break statement, if I can't get it to work. First time running up the code today, very impressed. I did it on 4ch ProR1 and DualR2. Everything else has been excellent. The documentation was good, very easy to implement. **(Please, remember to close the issue when the problem has been addressed)**
flashtel commented 5 years ago

HI,

I should have included this information

Program Version 6.6.0.10 stb-1.11(sonoff)

2019-09-15T19:24:51 2_5_0/3.0.0-dev(c0f7b44)

Thanks

flashtel commented 5 years ago

Hi,

I think it is this bug 6405. The "shutter unknown" message confused me. I tried again in 6.6.0 standard and get the same behaviour. When using shutter/window in this configuration I'm not sure I can user most of the shutter code because any movement needs to check with the state of the "interlocked" shutter/window. It may be this is a RFE.

https://github.com/arendst/Sonoff-Tasmota/issues/6405

stefanbode commented 5 years ago

Please can you use. shutteropen or shutterclose as a command in the rule instead of power on. This makes it more easy. Also please confirm that the shutter operates normal in all other conditions.

stefanbode commented 5 years ago

I just read through the 6405. Please let me know, if this is fixed in the original branch. The. I can sync mine again.

flashtel commented 5 years ago

Hi,

It's fixed with this one.

https://github.com/arendst/Sonoff-Tasmota/pull/6406/files

If you could patch the code that would be fantastic.

I've been building the logic on the standard dev branch.

I did try to see if I could add the patch but I don't have enough understanding.

I would prefer to use the shutter functionality.

Thanks Paul

Screen Shot 2019-09-18 at 3 43 31 pm
flashtel commented 5 years ago

This what I wrote on the latest release of the standard development code and it works.

It would be alot easier / better solution if I could run it on your shutter code. The way it is, it has to complete a cycle before you can stop or reverse it. ie if there is something obstruction, you can't stop it completing a close cycle from the inputs once initiated.

Shutters arrive Friday, windows are already working on the stefanbode shutter code.

mem1 0/1 Shutter1 Open/Closed (Awning Window) mem2 0/1 Shutter2 Open/Closed (Shutter) mem3 Awning Window Open/Close Time Seconds mem4 Shutter Open/Close TIme Seconds

rule1 on event#SHUTTEROPEN1 do if (mem1 != 1 and mem2 != 1); power4 off; power3 on; ruletimer3 %mem4%; var1 1; elseif (mem1 != 1); power2 off; power1 on; ruletimer1 %mem3%; endif endon on event#SHUTTERCLOSE1 do if (mem1 != 0); power1 off; power2 on; ruletimer2 %mem3%; endif endon

rule2 on event#SHUTTEROPEN2 do if (mem2 != 1); power4 off; power3 on; ruletimer3 %mem4%; endif endon on event#SHUTTERCLOSE2 do if (mem1 != 0 and mem2 != 0); power1 off; power2 on; ruletimer2 %mem3%; var2 1; elseif (mem2 != 0); power3 off; power4 on; ruletimer4 %mem4%; endif endon

rule3 on Rules#Timer=1 do backlog mem1 1; power1 off; endon on Rules#Timer=2 do if (var2 != 1); mem1 0; power2 off; else; mem1 0; power2 off; power3 off; power4 on; ruletimer4 %mem4%; var2 0; endif endon on Rules#Timer=3 do if (var1 != 1); mem2 1; power3 off; else; mem2 1; power3 off; power2 off; power1 on; ruletimer1 %mem3%; var1 0; endif endon on Rules#Timer=4 do backlog mem2 0; power4 off; endon

stefanbode commented 5 years ago

Please check it out, if it now works for you

stefanbode commented 5 years ago

Hi, I have really a hard time to guess what your rules are doing. Anyhow some comments. The power commands could be replaced with shutteropen, shutterclose and shutterstop. more easy to read and save some memory. Interesting: I was not aware than event#shutteropen1 is working.

flashtel commented 5 years ago

HI,

Thankyou so much for the prompt response.

I would like to be able to contribute more to sofware coding, I have hardware fabrication cability facility. If you ever want a custom switch built I can do that. In fact I am thinking of doing an 8 channel dry relay based on ESP-WROOM2, maybe an input chip for say 12 inputs on a header to take care of open/stop/close per shutter. If only I didn't have to work all the time..

A couple of things

1) I'm getting a compile error attached.

Did you put the defines in user_config_override.h

define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem)

define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+4k2 code, -332 bytes mem)

2) event#anything will work to trigger a rules. I've just used your naming standard to make it easy to switch between standard code and shutter code. I just update between %fulltopic%/backlog/shutteropen1 %fulltopic%/event/shutteropen1

3) If the window opens when the shutter is closed, the window will hit the shutter. If the shutter closes when the window is open, the shutter will hit the window.

So logic just adds 2 conditions.

i) Command window open, is window closed, is shutter closed >> open shutter then open window else is window closed, open window

ii) Command shutter close, is window open, is shutter open >> close window then close shutter else is shutter closed, close window

Yes I very much want to use the shutteropen/close commands and the shutter position capability of your code. At the moment I'm just using rule timers and variables in rules with standard code. Yours will make those rules much simpler and easier to read/debug.

To fully utilise your code with the use case I think it may not be possible with rules, I'm going to give it ago.

Any close shutter movement needs check if the window is closed and if not close window fully before moving.

Any window open movement needs to check the shutter is fully open if not open it fully before moving.

It needs to maintain shutter positions through a reboot.

Thanks again, awesome code.

Screen Shot 2019-09-19 at 7 25 57 AM

stefanbode commented 5 years ago

maybe the script is a solution for it I recently added sht[ to get the actual position of a shutter and you can use "=> shutteropen" to move the shutter. This change will be part of the merge process.

flashtel commented 5 years ago

I think that will be perfect. I'm really happy with the window/shutter setup I have used. It's just really clunky doing the programming without the shutter code.

I've done everything in 24Vdc so I can use on the Bathroom Window and I have "open" for everything incase of fire.

I'd like to add a wiki article, not sure how?

I edit in a version of my repository cloned from the latest version and then it's a pull-request??

I'm happy to contribute if it helps others. I think there should be more on the 24V systems, they are a lot safer in case of fire/power and the DC simu roller shutter motors are noticeably faster (more noise as well). The Shutter company says they last longer as well.

Thanks

Screen Shot 2019-09-27 at 2 19 34 PM

rule1 on event#SHUTTEROPEN1 do if (mem1 != 1 and mem2 != 1); power4 off; power3 on; ruletimer3 %mem4%; var1 1; elseif (mem1 != 1); power2 off; power1 on; ruletimer1 %mem3%; endif endon
on event#SHUTTERCLOSE1 do if (mem1 != 0); power1 off; power2 on; ruletimer2 %mem3%; endif endon on Mem1#STATE=0 do publish stat/myplace/house/office/shutter SHUTTERCLOSE1 endon on Mem1#STATE=1 do publish stat/myplace/house/office/shutter SHUTTEROPEN1 endon

rule2 on event#SHUTTEROPEN2 do if (mem2 != 1); power4 off; power3 on; ruletimer3 %mem4%; endif endon on event#SHUTTERCLOSE2 do if (mem1 != 0 and mem2 != 0); power1 off; power2 on; ruletimer2 %mem3%; var2 1; elseif (mem2 != 0); power3 off; power4 on; ruletimer4 %mem4%; endif endon on MEM2#STATE=0 do publish stat/myplace/house/office/shutter SHUTTERCLOSE2 endon on MEM2#STATE=1 do publish stat/myplace/house/office/shutter SHUTTEROPEN2 endon

rule3 on Rules#Timer=1 do backlog mem1 1; power1 off; endon on Rules#Timer=2 do if (var2 != 1); mem1 0; power2 off; else; mem1 0; power2 off; power3 off; power4 on; ruletimer4 %mem4%; var2 0; endif endon on Rules#Timer=3 do if (var1 != 1); mem2 1; power3 off; else; mem2 1; power3 off; power2 off; power1 on; ruletimer1 %mem3%; var1 0; endif endon on Rules#Timer=4 do backlog mem2 0; power4 off; endon

stefanbode commented 5 years ago

Maybe I'm just to dump for your rules. Why do you change power1 and power2 when the event is shutteropen1 or shutterclose1. The shutterprogramm takes care to operate for the relays. keep away your fingers. If you just want one shutter follow the other then this is enough: on event#SHUTTEROPEN1 do shutteropen2 on event#SHUTTEROPEN2 do shutteropen1 on event#SHUTTERCLOSE1 do shutterclose2 on event#SHUTTERCLOSE2 do shutterclose1

stefanbode commented 5 years ago

You wrote: _Any close shutter movement needs check if the window is closed and if not close window fully before moving.

Any window open movement needs to check the shutter is fully open if not open it fully before moving._ There is no need that you check this. This is all part of the shuttercode. The shutter extension knows the position and know what to to and what not to do. This is the reason why you cannot operate shutters successfull with the original branch of TASMOTA.

flashtel commented 5 years ago

I was never able to compile the shutter code with the IF/ELSE bug fix. Th error is in the thread. I really really want to use on event#SHUTTEROPEN1 do shutteropen2. Using 4ch Pro I get a compile error on

drv_10_rules line 1550 (full error in thread above)

with

define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem)

define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+4k2 code, -332 bytes mem)

I couldn't work it out.

Thanks

stefanbode commented 5 years ago

do you have disabled rules? this is mandatory

stefanbode commented 5 years ago

I just try to compile and see the same error if the SUPPORT_IF_STATEMENT is enabled. I check with the original ode, but maybe this is an error in the main code. not the shutter code

flashtel commented 5 years ago

Main code is working, I'm running it.

I'm running a window and a shutter together. You might think of it as half the same logic required as the relay interlock to stop a short circuit.

shutter1=window shutter2=shutter

window must be fully shut before moving shutter, shutter must be fully open before moving window.

Otherwise they collied

The picture shows 2x Windows 2x Shutters

Screen Shot 2019-09-27 at 2 50 46 PM

stefanbode commented 5 years ago

Ohh, this is a very nasty situation. And not easy to solve.

flashtel commented 5 years ago

:) It's not that bad, the rules I'm using work and if you can merge to the main code 90% will be done. It would be a lot more slick if we could add an Interlock between shutter1/2 but it will give me most of what I need with the if/else rules and shutter code function as is. I really should have limit switch inputs for closed loop control. I kinda built it and then realised, open loop is OK.

stefanbode commented 5 years ago

Ok, with the recent update it compiles and yes there where many changes required to get the IF THEN ELSE into the rules. Additionally, there is a project ongoing to merge the code for the shutter into the main branch during the next week hopefully.

flashtel commented 5 years ago

I've literally reloading a 4ch Pro, will stop and try your code !

flashtel commented 5 years ago

2 issues.

1) Compile error on 4ChPro ESP8255 > ESP 2.50 > TasmotaSerial-2.4.0

If you go back to TasmotaSerial-2.3.3 it compiles and this is coming from the master on theo branch. I have to revert back on the master compile as well.

2) It won't hold config, if you issue a "topic myplace/kitchen" then a restart it won't hold. same for setoption80 1 , won't hold config.

It seem to be restarting alot as well.

I have gone back to master and everything is compiling/config hold so it's not hardware.

Thanks

-I/Users/paulfish/Documents/Arduino/libraries/TasmotaSerial-2.4.0/src" "-I/Users/paulfish/Documents/Arduino/libraries/TasmotaModbus-1.2.0/src" "-I/Users/paulfish/Documents/Arduino/libraries/NewPing-1.9.1/src" "/Users/paulfish/Documents/Arduino/libraries/TasmotaSerial-2.4.0/src/TasmotaSerial.cpp" -o "/var/folders/sv/s1hvytg927x34vtyhkrhs3sh0000gn/T/arduino_build_416404/libraries/TasmotaSerial-2.4.0/TasmotaSerial.cpp.o" /Users/paulfish/Documents/Arduino/libraries/TasmotaSerial-2.4.0/src/TasmotaSerial.cpp: In constructor 'TasmotaSerial::TasmotaSerial(int, int, int, int, int)': /Users/paulfish/Documents/Arduino/libraries/TasmotaSerial-2.4.0/src/TasmotaSerial.cpp:115:83: error: 'attachInterruptArg' was not declared in this scope attachInterruptArg(m_rx_pin, callRxRead, this, (m_nwmode) ? CHANGE : FALLING);

flashtel commented 5 years ago

It's working!!

I haven't tested on Theo's repository yet.

I'm wondering if it is possible to reference the shutter position in the if statement??

At moment I'm setting Mem1 / Mem2 at the end of Open/Close cycle trigger.

rule1 on event#shutteropen1 do if ( mem2 != 1); shutteropen2; var1 1; else shutteropen1; endif endon on event#shutterclose1 do shutterclose1 endon on shutter-1#position==0 do if (var2 == 1); shutterclose2; var2 0; mem1 0; else mem1 0; endif endon on shutter-1#position==100 do mem1 1; endon

rule2 on event#shutterclose2 do if ( mem1 != 0); shutterclose1; var2 1; else shutterclose2; endif endon on event#shutteropen2 do shutteropen2 endon on shutter-2#position==0 do mem2 0; endon on shutter-2#position==100 do if (var1 == 1); shutteropen1; var1 0; mem2 1; else mem2 1; endif endon