Ok, as nobody was able to help me on this, I have expiremented myself and in the end got myself a working program. As others may have the same issues, I add my script code here
Code: Select all
local setdelay = 10
-- ADD DEVICES JUST ABOVE THE PROGRAM EXECUTION WITH return {
-- NO MORE CONFIGURING UNTIL THAT BLOCK OF CODE
local function addnewdevicelink (devicearray, virtual, physical, action, groupname)
local new = {}
if type(physical) == "table" then
for k, v in pairs(physical) do
addnewdevicelink(devicearray,virtual,v,action,groupname)
end
else
-- First set the name to device "name", even when empty (only for a new device)
new["name"]=groupname
local found=false
for k, v in pairs(devicearray) do
if k==virtual then
found=true
end
end
if not(found) then
devicearray[virtual]=new
end
-- now add device to the list (should always exist now)
local new = {}
new[physical]=action
local found=false
for k, v in pairs(devicearray) do
if k==virtual then
v[physical]=action
found=true
end
end
end
end
local function createdevicelist (linklist)
local returnarray = {}
for virt, val in pairs(linklist) do
if type(val) == "table" then
for real, action in pairs(val) do
if real ~= "name" then -- ignoring the 'name' device
local found = false
for icount=1,#returnarray do
if returnarray[icount]==real then
found = true
end
end
if not(found) then
table.insert(returnarray,real)
end
end
end
end
end
return returnarray
end
local function returnmatch(linklist,foundid) -- only the first virtual device will be returned
local returnarray = {}
local found = false
for virt, val in pairs(linklist) do
if type(val) == "table" then
for real, action in pairs(val) do
if real == foundid then
if not(found) then
returnarray[virt] = action
found = true
end
end
end
end
end
return returnarray
end
local function returnname(linklist,virtid) -- only the first virtual device will be returned
local foundname = ""
local found = false
for virt, val in pairs(linklist) do
if virt==virtid then
if type(val) == "table" then
for real, action in pairs(val) do
if real == "name" then
if not(found) then
foundname = action
found = true
end
end
end
end
end
end
return foundname
end
function vertoon (a)
local retstring = ""
if type(a) == "table" then
for k, v in pairs(a) do
if type(v) == "table" then
retstring = retstring .. " " .. k .. " = { " .. vertoon(v) .. "},"
else
retstring = retstring .. " " .. k .. " = " .. v .. ","
end
end
else
retstring = retstring .. a .. ","
end
return retstring
end
local workarray = {}
-- ADD DEVICES HERE
addnewdevicelink(workarray,VDI_winkellicht,DID_winkellicht,ACT_followvirtual+ACT_notify,"Winkellicht")
addnewdevicelink(workarray,VDI_etalage,DID_etalage,ACT_onlyretryoff+ACT_notify,"Etalage")
addnewdevicelink(workarray,VDI_eetkamerlicht,{DID_eetkamerlicht, DID_eetkamergroot},ACT_donothing,"Eetkamer")
-- FINISH CONFIGURING HERE
return {
on = {
devices = createdevicelist(workarray),
},
execute = function( dz, trig, info )
for key, value in pairs(returnmatch(workarray,trig.id)) do
if key > 0 then
if dz.devices(key).active ~= trig.active then
if value >= 10 then
value = value - 10
dz.helpers.sendTelegram(domoticz, TEL_sysalarmgroup, 'Value mismatch ' .. returnname(workarray,key) .. ' between ' .. key .. ' and ' .. trig.id)
end
if value == ACT_followvirtual then
dz.log('Need to Reset ' .. trig.id .. ', ' .. returnname(workarray,key),dz.LOG_FORCE)
if dz.devices(key).active then trig.switchOn().afterSec(setdelay)
else trig.switchOff().afterSec(setdelay)
end
end
if value == ACT_onlyretryoff then
if not(dz.devices(key).active) then
dz.log('Need to Reset ' .. trig.id .. ', ' .. returnname(workarray,key),dz.LOG_FORCE)
trig.switchOff().afterSec(setdelay)
end
end
if value == ACT_onlyretryon then
if dz.devices(key).active then
dz.log('Need to Reset ' .. trig.id .. ', ' .. returnname(workarray,key),dz.LOG_FORCE)
trig.switchOn().afterSec(setdelay)
end
end
end
else
dz.log('device ' .. trig.id .. ' not found in matchlist (' .. key .. "," .. value .. ")", dz.LOG_FORCE)
end
end
end
}
a) Sorry that my devices are in Dutch. I hope you have a grasp of things they do anyway (winkellicht=shoplight,eetkamer=diningroom,etalage=shopwindow)
b) I have set up global_data to have all the devices as variable names. When a device fails and needs to be replaced by another, I just have to change the device numbers there and all my other scripts just keep on functioning without any alteration.
- VDI = Virtual Device ID's
- DID = Device ID's of real devices {I am switching over from letting buttons and scripts change the status of the real device, but must change a virtual device that in turn switches one or multiple devices}
- ACT = Actions on what to do when there is a mismatch. I have defined:
- ACT_donothing = 0
ACT_followvirtual = 1
ACT_onlyretryoff = 2
ACT_onlyretryon = 3
ACT_notify = 10 -- this is a + action (e.g. ACT_followvirtual+ACT_notify)
c) Notification to my mobile device is done via a Telegram messaging function in my global_data
d) As any aftermin etc are executed by the virtual device, I do not need to take any of that info with me to the real devices
e) Make sure your physical switches are set to poling, otherwise they will never notify you that they have not executed the switch-command
f) I put a delay option (here set to 10 seconds) to prevent lights switching too fast, especially when a loop failure occurs. But this might be set to zero.
g) Easy ways to test this is to switch a powerplug by the button on it, or to change the state of the physical device in Domoticz, without changing the virtual value first.
h) Make sure your dashboard or dashticz do not show physical switches anymore, but just the virtual switches
i) I just finished programming it, but have only limitly tested it. So if you use it, use it as is and be aware, problems my pop up at any time. (you need to tweek it to your needs anyway)