Page 1 of 1
How-to: launch action after a certain time
Posted: Sunday 04 September 2022 9:42
by Patricen
Hello,
I'm trying to optimize my boiler start-up sequence, but have an issue coding this.
Currently there is a flowswitch that starts heating as soon as I do open a hot water tap. As there is a 50l hot water tank, I would like to start heating after 30s of water flow.
That was for the story.
Then, I would like to start heating after 30s, only if the water is still flowing, otherwise, no need to start.
If started, as soon as the water is not flowing anymore, stop heating.
Looks easy to write it but I can't figure out how to code it with dzvents.
Re: How-to: launch action after a certain time
Posted: Sunday 04 September 2022 11:03
by willemd
Looking at the dzvents documentation, you probably have to use the command options to handle this. Did you have a look at that?
Re: How-to: launch action after a certain time
Posted: Sunday 04 September 2022 14:17
by Patricen
Sure,
Found out afterSecs control, that I should combine with item.lastUpdate but within if function, item.lastupdate has a restriction. If the item is the one that triggered the event, lastUpdate time is the time before the event is triggered, then it is useless...
Then I need to find a trick.
Re: How-to: launch action after a certain time
Posted: Sunday 04 September 2022 16:56
by willemd
I understand, you want to trigger the flameswitch 30 seconds after the triggering of the flowswitch, but only of the flowswitch is still on. Could you use a dummy switch as intermediary?
Something like the code below ? (not tested) The script triggers itself a second time by changing the status of a dummyswitch. Not sure if this works, but easy to try out.
I think you also need to consider when you want to fill up the tank again with hot water, otherwise you will run out of hot water at some point.
Code: Select all
local idxFlowSwitch=XX, -- XX,YY,ZZ to be replaced by device numbers
local idxDummySwitch=YY,
local idxFlameSwitch=ZZ,
return {
on = {
devices = {
idxFlowSwitch,
idxDummySwitch
},
},
execute=function(domoticz,device)
if device==idxFlowSwitch then -- script triggered by flowswitch
domoticz.devices(idxDummySwitch).switchOff()
domoticz.devices(idxFlameSwitch).switchOff()
if device.state=='On' then -- flowswitch was switched to On
domoticz.devices(idxDummySwitch).switchOn().afterSec(30)
end
else -- script triggered by dummyswitch (30 seconds after flowswitch)
if domoticz.devices(idxFlowSwitch)=='On' then -- flow is still on
domoticz.devices(idxFlameSwitch).switchOn()
end
end
end
}
Re: How-to: launch action after a certain time
Posted: Monday 05 September 2022 7:05
by Patricen
Thanks, I'll check that.
Indeed, there is the dummy switch solution that I already used for another application, but I was wondering if there could be a way of coding that does not need the dummy switch.
I think you also need to consider when you want to fill up the tank again with hot water, otherwise you will run out of hot water at some point.
This switch is only intended to anticipate starting the flame before the flame starts due to temperature drop, because without the timer I want to set-up, it is very stressful for the ignition system (it is a common known failure for this type of boiler) and it unnecessarily consumes gas for short time water consumption. There is a 50l buffer tank and it looks like 60s would be the right delay time at the end. Basically, running out of hot water only happens for bathtub filling if the flowswitch is not connected to the flame control system.
"Appel ECS" is the water flowswitch and "Chaudière-Chauffe ECS" is the flame control
At the moment the code looks as below but is nos satisfying, as " if(Appel_ECS == 'On' and dz.devices('Appel ECS').lastUpdate.secondsAgo > 10)" does not work properly due to the limitation of item.lastUpdate.secondsAgo > 10 as the item triggered the thread.
dzVents documentation says :
lastUpdate: Time Object: Time when the device was updated. **Note: The lastUpdate for devices that triggered the script at hand is in fact the previousUpdate time. The real lastUpdate time for these “script triggering” devices is the current time.
The solution could be (but I don't find this really smart) to trigger using
and removing devices trigger, but I do have no idea about the required computing resources it takes to the RPI.
Code: Select all
return
{
on =
{
devices = {
'Appel ECS',
'Chaudière-Chauffe ECS'
},
timer = {'Every 10 minutes'}, -- just in case the flowswitch off is not detected, to avoid overheating
},
logging =
{
level = domoticz.LOG_debug, -- change to domoticz.LOG_ERROR when script is tested and OK
marker = 'Contrôle ECS',
},
execute = function(dz, item)
Appel_ECS = dz.devices('Appel ECS').state
dz.log('Appel ECS : ' .. Appel_ECS )
if(Appel_ECS == 'On' and dz.devices('Appel ECS').lastUpdate.secondsAgo > 10)
then
dz.devices('Chaudière-Chauffe ECS').switchOn().checkFirst()
dz.log('Démarrage chauffe ECS')
elseif(Appel_ECS == 'Off')
then
dz.devices('Chaudière-Chauffe ECS').switchOff().checkFirst()
dz.log('Arrêt chauffe ECS')
end
end
}
Re: How-to: launch action after a certain time
Posted: Tuesday 06 September 2022 19:59
by Patricen
Finally I found out a dummy solution without dummy switch...

- Capture.PNG (22.63 KiB) Viewed 3774 times
Re: How-to: launch action after a certain time
Posted: Tuesday 06 September 2022 21:22
by willemd
You said you wanted a solution in Dzvents?
Re: How-to: launch action after a certain time [SOLVED]
Posted: Sunday 18 September 2022 12:00
by rrozema
Using dzvents you can trigger a custom event. In that custom event you can send a payload. So what you can do is to have a custom event sent using the timed actions 30 seconds after the tap started running, in the payload you put the last update value of the current time the tap was opened. Next when you receive this custom event, you check if the tap is still open (status of the tap switch is "On" and last update equals the time in the payload of the custom event). If the status is "Off" by the time you receive the custom event, the tap must have been open for less han 30 seconds. If the status is "On" and the last update time on the tap switch matches the time in the payload, the tap is open for at least 30 seconds. If the status is "On" but the tap's last update differs from the time in the message's payload, the tap must have been opened, closed then re-opened within your 30 second time. It was NOT on for 30 seconds. Plus, you will probably get another custom message with a new pay load somewhat later, to which you can again do the same tests. I created a test script for this method once with a lot of help of @waaren. I never got to fully implementing it, maybe you can use this as an example for your purpose:
Code: Select all
return {
on = {
devices = {
"myTest"
},
customEvents = {
"Delayed-Auto-On*"
}
},
logging =
{
level = domoticz.LOG_ERROR,
},
execute = function(domoticz, item)
if item.isDevice then
-- if the trigger device changed to 'On' ...
if item.bState then
-- TODO: determine the delay for the device.
local delay = 20
-- ... and there is a delay > 0 seconds defined for this device...
if delay ~= nil and delay > 0 then
local Time = require('Time')
local thisUpdate = Time(os.date("%Y-%m-%d %H:%M:%S", os.time(item.lastUpdate.current)))
local name = 'Delayed-Auto-On-' .. tostring(item.idx) .. '-' .. thisUpdate.raw
local extraData = { ["idx"] = item.idx, ["bState"] = item.bState, ["thisUpdate"] = thisUpdate }
-- ... emit a customEvent after the delay.
domoticz.emitEvent(name, extraData).afterSec(delay)
else
-- No delay, activate the action right now.
-- TODO: add action here.
domoticz.log( 'Triggering action without delay', domotiz.LOG_FORCE)
end
end
elseif item.isCustomEvent then
-- If we get here, the customEvent has been triggered after the delay period. We will
-- test that:
-- 1 : bState on the device equals that which we stored in the [extra data], and
-- 2 : lastUpdate on the device equals that which we stored in [extra data].
-- If both conditions are met we know the device is still unchanged after the delay
-- and we can then start the delayed action.
if item.json == nil then
domoticz.log( 'json is missing', domoticz.LOG_ERROR)
elseif item.json.idx == nil then
domoticz.log( 'idx is missing', domoticz.LOG_ERROR)
elseif item.json.bState == nil then
domoticz.log( 'bstate is missing', domoticz.LOG_ERROR)
elseif item.json.thisUpdate == nil then
domoticz.log( 'thisUpdate is missing', domoticz.LOG_ERROR)
else
local device = domoticz.devices(item.json.idx)
if device == nil then
domoticz.log( 'device('..tostring(item.json.idx)..') not found', domoticz.LOG_ERROR)
else
local Time = require('Time')
local thisUpdate = Time(os.date("%Y-%m-%d %H:%M:%S", os.time(item.json.thisUpdate)))
if device.bState == item.json.bState and device.lastUpdate.compare(thisUpdate).compare == 0 then
-- TODO: add action here.
domoticz.log( 'Triggering action after delay', domoticz.LOG_FORCE)
end
end
end
else
domoticz.log( 'Unexpected trigger type', domoticz.LOG_ERROR)
end
end
}
To get an even more reliable result you could try to add the length of the period for each period the tap was "On" (i.e. the number of seconds between the "On" and the "Off" event) in a
persistent data with "history = true, MaxMinutes = 1" , then when you receive the custom event retrieve the sum of the periods over all times the tap was "On" in the last minute simply by calling the
statistical function domoticz.data.myVar.sum().
Re: How-to: launch action after a certain time
Posted: Tuesday 11 March 2025 13:59
by Gingerpale
Why does customEvents = { … } does not support .name attribute? ALmost all other objects support .name.
It would be useful to identify it when handling multiple customEvents in one script. E.g.:
Code: Select all
return {
on = {
devices = {'Test1', 'Test2'},
customEvents = {'delay_1_sec', 'delay_2_sec'},
},
logging = {level = domoticz.LOG_INFO, marker = 'Test',},
execute = function(domoticz, item)
if item.isDevice and item.name == 'Test1' and item.state == 'On' then
domoticz.emitEvent('delay_1_sec').afterSec(1)
elseif item.isDevice and item.name == 'Test2' and item.state == 'On' then
domoticz.emitEvent('delay_2_sec').afterSec(2)
elseif item.isDevice and item.state == 'Off' then
-- do nothing
elseif item.isCustomEvent and item.name == 'delay_1_sec' then -- item.name doesn't work!
domoticz.devices('Test1').switchOff()
elseif item.isCustomEvent and item.name == 'delay_2_sec' then -- item.name doesn't work!
domoticz.devices('Test2').switchOff()
else
-- do nothing
end
end
}
Currently the only workaround is to use the second parameter payload to indicate which one to execute, e.g.:
Code: Select all
return {
on = {
devices = {'Test1', 'Test2'},
customEvents = {'delay_x_sec',},
},
logging = {level = domoticz.LOG_INFO, marker = 'Test',},
execute = function(domoticz, item)
if item.isDevice and item.name == 'Test1' and item.state == 'On' then
domoticz.emitEvent('delay_x_sec', '1_sec').afterSec(1)
elseif item.isDevice and item.name == 'Test2' and item.state == 'On' then
domoticz.emitEvent('delay_x_sec', '2_sec').afterSec(2)
elseif item.isDevice and item.state == 'Off' then
-- do nothing
elseif item.isCustomEvent and item.data == '1_sec' then -- item.data does work!
domoticz.devices('Test1').switchOff()
elseif item.isCustomEvent and item.data == '2_sec' then -- item.data does work!
domoticz.devices('Test2').switchOff()
else
-- do nothing
end
end
}
Is there a reason for it? Or am I missing something?
Re: How-to: launch action after a certain time
Posted: Tuesday 11 March 2025 17:50
by waltervl
I never used custom events but looking at the wiki you have to use attribute .trigger for this
Eg
Code: Select all
if item.isCustomEvent and item.trigger == 'delay_1_sec' then
Re: How-to: launch action after a certain time
Posted: Tuesday 11 March 2025 20:00
by Gingerpale
Hi Walter,
I've tested it and it works! This is exactly what I was looking for.
Thx...
Re: How-to: launch action after a certain time
Posted: Wednesday 12 March 2025 8:09
by manjh
What if someone opens the hot water tap for 25 seconds? And again, and again? Eventually it would leave the boiler cold!
I know it may sound unlikely, but you should code for the worst...
Re: How-to: launch action after a certain time
Posted: Wednesday 12 March 2025 9:32
by Gingerpale
Good point,
I found a thread about that, see
viewtopic.php?t=33002
Unfortunately dz.emitEvent('myEvent').cancelQueuedCommands() doesn't work but it describes some work-around solutions.