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