Script that sends redundant on/of commands to switches

In this subforum you can show projects you have made, or you are busy with. Please create your own topic.

Moderator: leecollings

Post Reply
DaaNMaGeDDoN
Posts: 55
Joined: Thursday 23 October 2014 19:01
Target OS: Linux
Domoticz version: beta
Location: Eindhoven, the Netherlands
Contact:

Script that sends redundant on/of commands to switches

Post by DaaNMaGeDDoN »

Hi there, for some time i was getting a bit frustrated some devices far away from my rfxtrx443e were not picking up on commands they were sent.
I tried several antennas and although this improved the situation, from time to time i still found some devices turned on while domoticz thought it had turned them off and vice-versa.
For instance sometimes the toilet fan which is in the attic is turning long after domoticz had turned it off...it simply had missed the command.

So i started thinking how to have some mechanism in place that works pretty universally on some pre-defined devices i would like to have the last command send a couple more times just to be sure they switch. In theory if the chance the device misses a command is 1/5, repeating the command 3 times would decrease that chance to (1/5)^3=1/125

The solution was not as straight forward as expected: simply triggering on a devicechanged and sending the same device the same command again would create a loop, so i didnt even go there. So what about triggering on uservariables changes? Also that wouldn't work: one (device) script could update a uservar, but by design that does not trigger the uservar script. Which i think is kinda strange because there are enough other ways to create loops, which are 'allowed', anyway, moving on. Are time-based scripts an option? Na not really; again i could check if a device changed in the passed minute, but i would still have to find something that prevents it from looping, besides the delay is huge. So how about dummy devices? Should i have to create one dummydevice per device for every device i need to check? Argh can't have that!
So what now?

Experimenting with the options above i got to a solution, that still has a couple of caveats i can think of (see disclaimers), but has worked quite well in the last couple of hours testing.
The idea is as follows: use one device-triggered script and use a dummydevice with some uservars to "keep track" of the need to send some devices the last command again, with a small delay.
In more detail the script can be split in 3 sections:
1. Listen for one particular devicechange: if a dummydevice called 'State:PendingDeviceDoubleCheck' is turned ON (and only ON): check for pending redundant commands, queue one for each that has at least one pending and do nothing else.
2. listen for a devicechanged that matches one of our pre-defined devices. When triggered, check against the relevant uservar to see if there were pending redundant commands to be sent to that device. If so, decrement that uservar (since whe got to this part of the script, we can assume this is the result of an earlier scheduled devicechange from section1). If not we can assume this is the initial command and we need to schedule a couple more: set that uservar to 'doublechecks'.
3. compare the needed+pending redundant commands (sumpendingdoublechecks) to the "scheduled" (sumscheduleddoublechecks) commands queued, if there are more pending than scheduled: make sure the script is triggered again by turning ON the dummydevice with a delay, else just set the dummydev to "OFF", which is just esthetic.

Before you go just head over and copy-paste the script:
Disclaimers:
- this (currently) only works with ON/OFF switches, do not attempt to use it for any other types of switches like dimmers and such - i will however probably try to get that working too ;)
- you will need to create the dummy ON/OFF device "State:PendingDeviceDoubleCheck" and uservars <devicename>_pendingdoublecheck (type int) before you put any device in the array 'devices'.
- if you are already using switches that provide domoticz with feedback, this script of course isn't necessary.
- if a device toggles again within the period it has "pending doublechecks" the script is not able to keep track of that and will simply count down the pending doublechecks for that device and not reset it to "doublechecks" - this will probably happen only once in a milion years, but you have been warned: don't use this script for switches that switch often.
- the script has been designed to cope with mutliple devices that need redundant commands overlapping in time, so far this seems to work ok.
- don't be a fool and set the 'doublechecks' very high or the 'delay' very low; if you really don't know why, you should not even have kept reading until here - no offence meant.
- the script looks pretty complex and as such it will likely have bugs, however if you plan to use it, start off small with one device, keep a keen eye on the log.
- make sure to try to understand the script and please share any concerns or bugs here, thanks!

Hope this helps, cheers Daan.

Code: Select all

commandArray = {}

local devices={'Bathroom Vent', 'Toilet Vent', 'Kitchen Boiler'}
local doublechecks=2
local delay=5
local debug=true

for e,v in pairs (devicechanged) do
	if (e=='State:PendingDeviceDoubleCheck' and v=='On') then
		if debug then print("State:PendingDeviceDoubleCheck was turned on") end
		for n,device in pairs (devices) do
			if (tonumber(uservariables[device..'_pendingdoublecheck'])>0) then
				if debug then print("Sending device:"..device.." the command "..otherdevices[device].." again") end
				commandArray[#commandArray+1]={[device]=otherdevices[device]}
			end
		end
	else
		local sumscheduleddoublechecks=0
		local sumpendingdoublechecks=0
		for n,device in pairs(devices) do
			if (e==device) then
				if debug then print("found a matching candidate:"..device) end
				local pendingdoublecheck=tonumber(uservariables[device..'_pendingdoublecheck'])
				if (pendingdoublecheck>0) then
					if debug then print("matching candidate:"..device.." has pendingdoublecheck="..pendingdoublecheck.." decrementing...") end
					commandArray[#commandArray+1]={['Variable:'..device..'_pendingdoublecheck']=tostring(pendingdoublecheck-1)}
					sumscheduleddoublechecks=sumscheduleddoublechecks+1
				else 
					if debug then print("matching candidate:"..device.." has pendingdoublecheck="..pendingdoublecheck.." setting to "..doublechecks) end
					commandArray[#commandArray+1]={['Variable:'..device..'_pendingdoublecheck']=tostring(doublechecks)}
					sumpendingdoublechecks=sumpendingdoublechecks+doublechecks
				end
				for n,device in pairs (devices) do
					if (tonumber(uservariables[device..'_pendingdoublecheck'])>0) then
						sumpendingdoublechecks=sumpendingdoublechecks+tonumber(uservariables[device..'_pendingdoublecheck'])
					end
				end
				if debug then print("sumpendingdoublechecks:"..sumpendingdoublechecks) end
				if debug then print("sumscheduleddoublechecks:"..sumscheduleddoublechecks) end
				if (sumpendingdoublechecks>sumscheduleddoublechecks) then
					if debug then print("sumpendingdoublechecks is higher than sumscheduleddoublechecks:making sure this script is triggered again after "..delay) end
					commandArray[#commandArray+1]={['State:PendingDeviceDoubleCheck']='On AFTER '..delay}
				elseif (sumpendingdoublechecks<=sumscheduleddoublechecks and otherdevices['State:PendingDeviceDoubleCheck']=='On') then
					if debug then print("sumpendingdoublechecks is equal or less to sumscheduleddoublechecks, setting State:PendingDeviceDoubleCheck=Off ") end
					commandArray[#commandArray+1]={['State:PendingDeviceDoubleCheck']='Off'}
				end
			end
		end
	end
end

return commandArray
User avatar
jvdz
Posts: 2330
Joined: Tuesday 30 December 2014 19:25
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.107
Location: Netherlands
Contact:

Re: Script that sends redundant on/of commands to switches

Post by jvdz »

Daan,

Couldn't you also take the approach that when doing the switch On/Off command with LUA you simply return multiple On or Off commands with something like this script: (Untested)

Code: Select all

commandArray = {}

DeviceName="Ventilator"
Repeat=3   -- number of times to send On
Delay=5    -- Delay time between sends

for i = 1, Repeat do
	if i == 1 then 
		commandArray[i]={[DeviceName] = "On"}
	else		
		commandArray[i]={[DeviceName] = "On AFTER " .. tostring(i*Delay}
	end
end

return commandArray
Jos
New Garbage collection scripts: https://github.com/jvanderzande/GarbageCalendar
DaaNMaGeDDoN
Posts: 55
Joined: Thursday 23 October 2014 19:01
Target OS: Linux
Domoticz version: beta
Location: Eindhoven, the Netherlands
Contact:

Re: Script that sends redundant on/of commands to switches

Post by DaaNMaGeDDoN »

Hi Jos :)
Yes, but there is one big issue with that approach: whenever the device is turned off (after being turned on) _within_ the timeperiod there are still pending redundant commands queued the device would turn on and off repeatedly.
The problem with the command On/Off AFTER is that you can't cancel them; so another devicechange in the other direction would be problematic. I tend to be very careful using the AFTER and FOR commands for that reason.
That is why my script uses the dummydev, and evaluates what needs to be done at the "moment it was planned", not beforehand.
Btw, i have used such a script like you describe for a dimmer in bedroom to create some sort of a wakeup-/goingtosleep experience. Same problem applies there: if i am hasty and get out of bed and i turn the dimmer higher by some other means it will soon be turned down again because of the queued "Set Level x AFTER y" that i queued earlier hitting the "i am awake" switch ;)
Thanks for sharing your thoughts though, can help to think myself this could be done more easily.
User avatar
jvdz
Posts: 2330
Joined: Tuesday 30 December 2014 19:25
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.107
Location: Netherlands
Contact:

Re: Script that sends redundant on/of commands to switches

Post by jvdz »

Makes sense indeed.
I am not aware of any option to kill commands for a device still on the "stack to be processed", which would be required in this case.
Maybe an idea for a future release. :)

Thanks
Jos
New Garbage collection scripts: https://github.com/jvanderzande/GarbageCalendar
User avatar
Egregius
Posts: 2592
Joined: Thursday 09 April 2015 12:19
Target OS: Linux
Domoticz version: v2024.7
Location: Beitem, BE
Contact:

Re: Script that sends redundant on/of commands to switches

Post by Egregius »

You could also use z-wave and don't worry about that anymore :P
DaaNMaGeDDoN
Posts: 55
Joined: Thursday 23 October 2014 19:01
Target OS: Linux
Domoticz version: beta
Location: Eindhoven, the Netherlands
Contact:

Re: Script that sends redundant on/of commands to switches

Post by DaaNMaGeDDoN »

Egregius wrote:You could also use z-wave and don't worry about that anymore :P
And worry more about my bank account ;)

Maybe i'm not looking in the right places, so help me here: it seems z-wave switches are about twice the price of for instance KiKu switches, right?
User avatar
Egregius
Posts: 2592
Joined: Thursday 09 April 2015 12:19
Target OS: Linux
Domoticz version: v2024.7
Location: Beitem, BE
Contact:

Re: Script that sends redundant on/of commands to switches

Post by Egregius »

Something like that I guess. About €50 each.
But I was kind of joking, don't worry. Everyone his own budget and priorities.
DaaNMaGeDDoN
Posts: 55
Joined: Thursday 23 October 2014 19:01
Target OS: Linux
Domoticz version: beta
Location: Eindhoven, the Netherlands
Contact:

Re: Script that sends redundant on/of commands to switches

Post by DaaNMaGeDDoN »

Egregius wrote:Something like that I guess. About €50 each.
But I was kind of joking, don't worry. Everyone his own budget and priorities.
No worries, no offence taken. In fact i have considered using Zwave and the like because of the handshake, which is much more reliable.
Unfortunately i have too many things i would like to control and i am indeed the kind of person that likes to get the most out of minimal means by efficient use, i guess this script is a good example hehe.
In the meantime i am experimenting with electronics and mcu's to create some diy switches and dimmers that connect to wifi, i think they might be faster and of course can "talk back".
Of course that is not something i would put in a friends house/business environment ;)
Btw so far the script performed beautifully. Havent had one of the switches missing a command since.
TheeDude
Posts: 46
Joined: Wednesday 07 October 2015 0:43
Target OS: Linux
Domoticz version:
Contact:

Re: Script that sends redundant on/of commands to switches

Post by TheeDude »

Thanks for a great script!
Just tested this on two Nexa WMR-3500 that I am using to turn on/off Preheater to my and my partner´s car.
My switch is working just fine, but her´s having problems turning off, weird..
Never had a problem turning on, but off, and it have been working good turning off with my computer or phone, but not automatically by script.
Even though Domoticz sent the off command.

Hope this works, the real test will be next week when she goes off to work!

Thanks!
DaaNMaGeDDoN
Posts: 55
Joined: Thursday 23 October 2014 19:01
Target OS: Linux
Domoticz version: beta
Location: Eindhoven, the Netherlands
Contact:

Re: Script that sends redundant on/of commands to switches

Post by DaaNMaGeDDoN »

TheeDude wrote:Thanks for a great script!
...
Hope this works, the real test will be next week when she goes off to work!

Thanks!
And did it work?
I hope it did, here it works fine.
TheeDude
Posts: 46
Joined: Wednesday 07 October 2015 0:43
Target OS: Linux
Domoticz version:
Contact:

Re: Script that sends redundant on/of commands to switches

Post by TheeDude »

Well, the script itself worked just fine.
But, it didnt help in my situation.
It didn't turn off with 3 thries.
I moved The switch a couple of centimeters just to try.
Then another switch I have 2 meters away stopped working.


So I guess I had some interference or something just right there.

I solved it with a external antenna to the Rfxcom in the attic.

http://thedude.ath.cx/owncloud/index.ph ... ySisKc0rXW
With this antenna.
Then it works just fine

Skickat från min E6553 via Tapatalk
liverp111
Posts: 1
Joined: Tuesday 17 November 2015 12:23
Target OS: OS X
Domoticz version:
Contact:

Re: Script that sends redundant on/of commands to switches

Post by liverp111 »

Giving the lock swithches to decreae the chances
bertbigb
Posts: 147
Joined: Thursday 13 August 2015 13:36
Target OS: NAS (Synology & others)
Domoticz version: beta
Location: Netherlands
Contact:

Re: Script that sends redundant on/of commands to switches

Post by bertbigb »

Thanks for this script, it works great.
Would be nice when in Domoticz self you could set this behavior for a switch.
Would make the use of the KaKu a lot more trustfull
Best regards Bert

Synology DS1517+ - DSM 6.2
Raspberry PI2-B, Raspberry Nano - Raspberry PI3 - model B
Xiaomi Gateway - Philips HUE Lights - Zwave - RFXCom(E) with KaKu and other 433MHz devices - Yeelight Lights - Toon
DaaNMaGeDDoN
Posts: 55
Joined: Thursday 23 October 2014 19:01
Target OS: Linux
Domoticz version: beta
Location: Eindhoven, the Netherlands
Contact:

Re: Script that sends redundant on/of commands to switches

Post by DaaNMaGeDDoN »

I wanted to thank you for the feedback and add i have just tested and confirmed this works just as good with dimmers!!
Make sure before you put dimmers in your devices array the otherdevices['some dimmer'] returns something like "Set Level: 40%" because that seems nowadays something that is accepted as an input command. This can easily be seen by putting debug to true, adding a dimmer and adding the appropriate uservar.
Happy homeautomation!
DaaNMaGeDDoN
Posts: 55
Joined: Thursday 23 October 2014 19:01
Target OS: Linux
Domoticz version: beta
Location: Eindhoven, the Netherlands
Contact:

Re: Script that sends redundant on/of commands to switches

Post by DaaNMaGeDDoN »

Sorry i yelled too soon, there are 2 problems with dimmers: 1st the level tends to be set lower than the initial setting (probably i will need to use the _svalues table) and secondly the off command for a dimmer needs to be handled differently. To be continued.
DaaNMaGeDDoN
Posts: 55
Joined: Thursday 23 October 2014 19:01
Target OS: Linux
Domoticz version: beta
Location: Eindhoven, the Netherlands
Contact:

Re: Script that sends redundant on/of commands to switches

Post by DaaNMaGeDDoN »

Hi, i had another look and got it fixed for dimmers now too. I compensated for the fact sometimes the dimmer percentage is rounded to far down. E.g. setting the dimmer slider via the webinterface to 33% (corresponding sValue:5) works, but when you take that value and simply use it in a script, it will be rounded down to some lesser value. This will happen for any value thats not 20,40,60,80 percent and without the necessary modifications the script would set the dimmer down to one of those values when sending the redundant commands.
The solution is in

Code: Select all

local value=math.ceil(otherdevices_svalues[device]*100/15)
which will give a usable percentage to send again. With that the script becomes compatible with 15-step dimmers (e.g. KlikAanKlikUit, if you use different dimmers you may need to change some of the code). The full script is now:

Code: Select all

commandArray = {}

--put your devices in this array:
local devices={'device1', 'dimmer1', 'device2, ... '} 
local doublechecks=4
local delay=7
local debug=true

for e,v in pairs (devicechanged) do
	if (e=='State:PendingDeviceDoubleCheck' and v=='On') then
		if debug then print("State:PendingDeviceDoubleCheck was turned on") end
		for n,device in pairs (devices) do
			if (tonumber(uservariables[device..'_pendingdoublecheck'])>0) then
				if debug then print("Sending device:"..device.." the command "..otherdevices[device].." again") end
				if ((tostring(otherdevices[device])):sub(1,9)=="Set Level") then
					if debug then print("Its a dimmer, level needs to be adjusted!") end
					local value=math.ceil(otherdevices_svalues[device]*100/15)
					if debug then print("Setting to level:"..value.."%") end
					commandArray[#commandArray+1]={[device]="Set Level "..value}
				else
					commandArray[#commandArray+1]={[device]=otherdevices[device]}
				end
			end
		end
	else
		local sumscheduleddoublechecks=0
		local sumpendingdoublechecks=0
		for n,device in pairs(devices) do
			if (e==device) then
				if debug then print("found a matching candidate:"..device) end
				local pendingdoublecheck=tonumber(uservariables[device..'_pendingdoublecheck'])
				if (pendingdoublecheck>0) then
					if debug then print("matching candidate:"..device.." has pendingdoublecheck="..pendingdoublecheck.." decrementing...") end
					commandArray[#commandArray+1]={['Variable:'..device..'_pendingdoublecheck']=tostring(pendingdoublecheck-1)}
					sumscheduleddoublechecks=sumscheduleddoublechecks+1
				else 
					if debug then print("matching candidate:"..device.." has pendingdoublecheck="..pendingdoublecheck.." setting to "..doublechecks) end
					commandArray[#commandArray+1]={['Variable:'..device..'_pendingdoublecheck']=tostring(doublechecks)}
					sumpendingdoublechecks=sumpendingdoublechecks+doublechecks
				end
				for n,device in pairs (devices) do
					if (tonumber(uservariables[device..'_pendingdoublecheck'])>0) then
						sumpendingdoublechecks=sumpendingdoublechecks+tonumber(uservariables[device..'_pendingdoublecheck'])
					end
				end
				if debug then print("sumpendingdoublechecks:"..sumpendingdoublechecks) end
				if debug then print("sumscheduleddoublechecks:"..sumscheduleddoublechecks) end
				if (sumpendingdoublechecks>sumscheduleddoublechecks) then
					if debug then print("sumpendingdoublechecks is higher than sumscheduleddoublechecks:making sure this script is triggered again after "..delay.." seconds") end
					commandArray[#commandArray+1]={['State:PendingDeviceDoubleCheck']='On AFTER '..delay}
				elseif (sumpendingdoublechecks<=sumscheduleddoublechecks and otherdevices['State:PendingDeviceDoubleCheck']=='On') then
					if debug then print("sumpendingdoublechecks is equal or less to sumscheduleddoublechecks, setting State:PendingDeviceDoubleCheck=Off ") end
					commandArray[#commandArray+1]={['State:PendingDeviceDoubleCheck']='Off'}
				end
			end
		end
	end
end

return commandArray
Hope this helps others too, it's been in place at home for some weeks now and i can really tell the difference. Hope this helps others too, if it does let me know, i appreciate the feedback :)
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest