Run script if device left on for a period of time? [Solved]
Moderator: leecollings
-
- Posts: 82
- Joined: Monday 01 December 2014 13:28
- Target OS: Raspberry Pi / ODroid
- Domoticz version: Beta
- Location: London, UK
- Contact:
Run script if device left on for a period of time?
I know it's possible to detect if a device is turned on, and also to determine how long it has been left on for.
However, is it possible to trigger a script based on whether a device has been left on for, say, an hour, rather than having a script running every few minutes to check this?
Thanks
However, is it possible to trigger a script based on whether a device has been left on for, say, an hour, rather than having a script running every few minutes to check this?
Thanks
- waaren
- Posts: 6028
- Joined: Tuesday 03 January 2017 14:18
- Target OS: Linux
- Domoticz version: Beta
- Location: Netherlands
- Contact:
Re: Run script if device left on for a period of time?
Yes this is possible. Using the "easy" way with cancelQueuedCommands and afterSec() methods. Works most of the times but not if domoticz or system is restarted between time device was switched On and scheduled Off time. (See first script)doh wrote: ↑Friday 03 May 2019 12:29 I know it's possible to detect if a device is turned on, and also to determine how long it has been left on for.
However, is it possible to trigger a script based on whether a device has been left on for, say, an hour, rather than having a script running every few minutes to check this?
Thanks
and a somewhat more complicated method where Off time is stored in persistent data and script to switch Off device is triggered by a delayed HTTP callback. Using this method it's possible to switch lights Off even after a system reboot or domoticz restart. (see 2nd script)
Both methods use a default maxOnSeconds that can be overruled by putting maxOnSeconds: xxxx in the device description field, where xxxx is the amount of seconds the device should stay max. on.
All devices to be considered can be put in the on = devices {} section; either as a list of devicenames or as (a list) of wildcarded devicenames.
Code: Select all
return {
on = { devices = {"device1", "device2"}}, -- Devices to be checked (can be wildcarded names)
logging = { level = domoticz.LOG_ERROR, -- change to Debug when script does not do what's expected
marker = "maxOn" },
execute = function(dz, item)
local defaultMaxOnSeconds = 3600 -- default max on time in seconds
local function logWrite(str,level)
dz.log(tostring(str),level or dz.LOG_DEBUG)
end
local function deviceMaxOnSeconds(device)
local maxOnSeconds
if device.description ~= nil and device.description ~= "" then
_, _, maxOnSeconds = string.find(device.description,"maxOnSeconds:(%s*%d+)") -- Check if the description field has "maxOnTime: " followed by an integer (max seconds)
logWrite (device.name .. " max on time: " .. ( maxOnSeconds or defaultMaxOnSeconds ))
end
return ( maxOnSeconds or defaultMaxOnSeconds )
end
item.cancelQueuedCommands()
if item.active then
logWrite(item.name .. ": " .. deviceMaxOnSeconds(item))
item.switchOff().silent().afterSec(deviceMaxOnSeconds(item))
end
end
}
Code: Select all
scriptVar = "maxOndevices"
return {
on = { timer = { "at *:17" }, -- Additional check once every hour to ensure no devices are left behind after system boot or domoticz restart
httpResponses = { scriptVar .. '*' },
devices = {"device1", "device2"}}, -- Devices to be checked (can be wildcarded names)
logging = { level = domoticz.LOG_ERROR, -- change to Debug when script does not do what's expected
marker = "maxOn" },
data = { activeDevices = { initial = {}}},
execute = function(dz, item)
local defaultMaxOnSeconds = 3600 -- default max on time in seconds
local function logWrite(str,level)
dz.log(tostring(str),level or dz.LOG_DEBUG)
end
local function deviceMaxOnSeconds(device)
local maxOnSeconds
if device.description ~= nil and device.description ~= "" then
_, _, maxOnSeconds = string.find(device.description,"maxOnSeconds:(%s*%d+)") -- Check if the description field has "maxOnTime: " followed by an integer (max seconds)
logWrite (device.name .. " max on time: " .. ( maxOnSeconds or defaultMaxOnSeconds ))
end
return ( maxOnSeconds or defaultMaxOnSeconds )
end
local function scheduleStillActiveCheck(device,delay)
local url = dz.settings['Domoticz url'] .. "/json.htm?type=command¶m=addlogmessage&message=" ..
dz.utils.urlEncode(device.name .. " will be switched Off; if still active")
dz.openURL({
url = url,
method = 'GET',
callback = scriptVar .. "_" .. device.idx
}).afterSec(delay)
end
if item.isDevice and not item.active then
dz.data.activeDevices[item.idx] = nil
elseif item.isDevice and item.active then
local maxOnSeconds = deviceMaxOnSeconds(item)
logWrite(item.name .. " is Active for max " .. maxOnSeconds .. " seconds.")
scheduleStillActiveCheck(item,maxOnSeconds)
dz.data.activeDevices[item.idx] = dz.time.dDate + maxOnSeconds
elseif item.isTimer or item.isHTTPResponse then
for key, value in pairs(dz.data.activeDevices) do
if dz.devices(key).active and ( dz.devices(key).lastUpdate.secondsAgo <= dz.data.activeDevices[key] ) then
dz.data.activeDevices[key] = nil
dz.devices(key).switchOff().silent()
end
end
end
end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
-
- Posts: 84
- Joined: Friday 12 May 2017 20:03
- Target OS: -
- Domoticz version:
- Contact:
Re: Run script if device left on for a period of time?
@Waaren,
I'm using this script to check if doors/windows are left open longer than wanted.
I don't understand this line of code:
You add 'dz.time.dDate + maxOnSeconds', so it will take a whole lot of time for lastUpdate.secondsAgo to become bigger, no?
once the device triggers, the program waits for 'delay' seconds to launch the url. Isn't it enough to just check if the device is active?
Thanks
I'm using this script to check if doors/windows are left open longer than wanted.
I don't understand this line of code:
Code: Select all
if dz.devices(key).active and ( dz.devices(key).lastUpdate.secondsAgo <= dz.data.activeDevices[key] ) then
once the device triggers, the program waits for 'delay' seconds to launch the url. Isn't it enough to just check if the device is active?
Thanks
- waaren
- Posts: 6028
- Joined: Tuesday 03 January 2017 14:18
- Target OS: Linux
- Domoticz version: Beta
- Location: Netherlands
- Contact:
Re: Run script if device left on for a period of time?
If you are sure that in between the device have not been switched Off and back On that would be enough.geertvercamer wrote: ↑Thursday 11 February 2021 20:57 once the device triggers, the program waits for 'delay' seconds to launch the url. Isn't it enough to just check if the device is active?
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
-
- Posts: 84
- Joined: Friday 12 May 2017 20:03
- Target OS: -
- Domoticz version:
- Contact:
Re: Run script if device left on for a period of time?
ah, ok, I see why now but still not how.
suppose maxOnSeconds = 60
dz.data.activeDevices[item.idx] = dz.time.dDate + maxOnSeconds
this sets quite big a value, all the seconds since 01/01/1970, so over 51 years in seconds
if dz.devices(key).active and ( dz.devices(key).lastUpdate.secondsAgo <= dz.data.activeDevices[key] ) then
secondsAgo is a duration, right? So this test is only false if my door would be open for more then 51 years, 1 month, 13 days and 10 hours
shouldn't you compare the lastUpdate timestamp in seconds to the dz.data.activeDevices[key]?
Or am i missing something completely here?
Thanks!
suppose maxOnSeconds = 60
dz.data.activeDevices[item.idx] = dz.time.dDate + maxOnSeconds
this sets quite big a value, all the seconds since 01/01/1970, so over 51 years in seconds
if dz.devices(key).active and ( dz.devices(key).lastUpdate.secondsAgo <= dz.data.activeDevices[key] ) then
secondsAgo is a duration, right? So this test is only false if my door would be open for more then 51 years, 1 month, 13 days and 10 hours
shouldn't you compare the lastUpdate timestamp in seconds to the dz.data.activeDevices[key]?
Or am i missing something completely here?
Thanks!
- waaren
- Posts: 6028
- Joined: Tuesday 03 January 2017 14:18
- Target OS: Linux
- Domoticz version: Beta
- Location: Netherlands
- Contact:
Re: Run script if device left on for a period of time?
Probably because there were still some bugs in the scriptgeertvercamer wrote: ↑Saturday 13 February 2021 10:04 ah, ok, I see why now but still not how.
Or am i missing something completely here?

I fixed them in below version and added some debug log lines to make it more clear what happens
Code: Select all
local scriptVar = 'maxOndevices'
return
{
on =
{
timer = -- Additional check once every hour to ensure no devices are left behind after system boot or domoticz restart
{
'at *:17' ,
'every minute', -- for debug only
},
httpResponses =
{
scriptVar .. '*',
},
devices = -- Devices to be checked (can be wildcarded names)
{
'device1' ,
'device2' ,
},
},
logging =
{
level = domoticz.LOG_DEBUG, -- change to Debug when script does not do what's expected
marker = 'maxOn',
},
data =
{
activeDevices =
{
initial = {}
}
},
execute = function(dz, item)
local defaultMaxOnSeconds = 3600 -- default max on time in seconds
local function deviceMaxOnSeconds(device)
local maxOnSeconds
if device.description ~= nil and device.description ~= '' then
maxOnSeconds = device.description:match('maxOnTime:(%s*%d+)') -- Check if the description field has 'maxOnTime: int' (in seconds)
dz.log (device.name .. ' max on time: ' .. ( maxOnSeconds or defaultMaxOnSeconds ), dz.LOG_DEBUG)
end
return ( maxOnSeconds or defaultMaxOnSeconds )
end
local function scheduleStillActiveCheck(device,delay)
local url = dz.settings['Domoticz url'] .. '/json.htm?type=command¶m=addlogmessage&message=' ..
dz.utils.urlEncode(device.name .. ' will be switched Off; if still active')
dz.openURL({
url = url,
method = 'GET',
callback = scriptVar .. '_' .. device.idx
}).afterSec(delay + 1)
end
if item.isDevice and not item.active then
dz.data.activeDevices[item.idx] = nil
elseif item.isDevice and item.active then
local maxOnSeconds = deviceMaxOnSeconds(item)
dz.log(item.name .. ' is activated for max ' .. maxOnSeconds .. ' seconds.', dz.LOG_DEBUG)
scheduleStillActiveCheck(item, maxOnSeconds)
dz.data.activeDevices[item.idx] = os.time() + maxOnSeconds
elseif item.isTimer or item.isHTTPResponse then
for key, value in pairs(dz.data.activeDevices) do
dz.log('Comparing ' .. dz.devices(key).name .. ' dz.data: ' .. math.floor(dz.data.activeDevices[key]) .. ' against ' .. os.time(), dz.LOG_DEBUG)
if dz.devices(key).active and dz.data.activeDevices[key] < os.time() then
dz.log( 'Switching off ' .. dz.devices(key).name , dz.LOG_DEBUG)
dz.data.activeDevices[key] = nil
dz.devices(key).switchOff().silent()
elseif dz.devices(key).active then
dz.log(dz.devices(key).name .. ' can be left on for another ' .. math.floor( dz.data.activeDevices[key] - os.time() ) .. ' seconds' , dz.LOG_DEBUG)
else
dz.log( 'No action needed for ' .. dz.devices(key).name .. ' needed. It is already Off. ', dz.LOG_DEBUG)
end
end
end
end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Re: Run script if device left on for a period of time?
Tnx, for the script. I have a few issues.
In the logging I find.
That callback is from an other script. So it looks like the "scriptVar" is used from an other script.
Also I found that
The original is logged as:
It is not working for me, I had to use hardcoded "http://127.0.0.1:8080" for the url
Any ideas?
In the logging I find.
Code: Select all
Debug: maxOn: OpenURL: callback = waterpeilGrebbe_38
Also I found that
Code: Select all
local url = dz.settings['Domoticz url'] .. '/json.htm?type=command¶m=addlogmessage&message=' ..
Code: Select all
Debug: maxOn: OpenURL: url = http://0.0.0.0:8080/json.htm?
Any ideas?
- waaren
- Posts: 6028
- Joined: Tuesday 03 January 2017 14:18
- Target OS: Linux
- Domoticz version: Beta
- Location: Netherlands
- Contact:
Re: Run script if device left on for a period of time?
ChangeEddyG wrote: ↑Saturday 13 February 2021 12:19That callback is from an other script. So it looks like the "scriptVar" is used from an other script.Code: Select all
Debug: maxOn: OpenURL: callback = waterpeilGrebbe_38
Code: Select all
scriptVar =
Code: Select all
local scriptVar =
Did you set your location andAlso I found thatIt is not working for me, I had to use hardcoded "http://127.0.0.1:8080" for the urlCode: Select all
local url = dz.settings['Domoticz url'] .. '/json.htm?type=command¶m=addlogmessage&message=' ..
Local Networks (no username/password):
in the settings ?
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Re: Run script if device left on for a period of time?
Yes, stupid me. The "local" worked of course.
Yes, mylocation is set (from the initial start of my Domoticz), local network like 127.0.0.* and a few in 192.168.2.* even Domoticz it self.
But it comes back with 0.0.0.0
Yes, mylocation is set (from the initial start of my Domoticz), local network like 127.0.0.* and a few in 192.168.2.* even Domoticz it self.
But it comes back with 0.0.0.0
- waaren
- Posts: 6028
- Joined: Tuesday 03 January 2017 14:18
- Target OS: Linux
- Domoticz version: Beta
- Location: Netherlands
- Contact:
Re: Run script if device left on for a period of time?
Can you try and change it to below line? That will take care of an IPv6 type of address.
Code: Select all
127.0.0.*;192.168.2.*;::1
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
- waaren
- Posts: 6028
- Joined: Tuesday 03 January 2017 14:18
- Target OS: Linux
- Domoticz version: Beta
- Location: Netherlands
- Contact:
Re: Run script if device left on for a period of time?
If that does not work could it be that you start domoticz with the option -wwwbind 0.0.0.0 ?waaren wrote: ↑Saturday 13 February 2021 20:26Can you try and change it to below line? That will take care of an IPv6 type of address.
Code: Select all
127.0.0.*;192.168.2.*;::1
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Re: Run script if device left on for a period of time?
Sorry for the delay.
I already have IPv6 added and I do not use -wwwbind 0.0.0.0 to start domoticz.
But my workaround of hardcode 127.0.0.1 works without errors.
Tnx.
I already have IPv6 added and I do not use -wwwbind 0.0.0.0 to start domoticz.
But my workaround of hardcode 127.0.0.1 works without errors.
Tnx.
- waaren
- Posts: 6028
- Joined: Tuesday 03 January 2017 14:18
- Target OS: Linux
- Domoticz version: Beta
- Location: Netherlands
- Contact:
Re: Run script if device left on for a period of time?
OK. Can you please add
Code: Select all
utils.log(_gv, utils.LOG_FORCE)
It might help in identifying what causes your issue and if it can be solved it could prevent the same for others. Thx !
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Re: Run script if device left on for a period of time?
I did that and now I see in the logging ->
I restarted Domoticz and I also see:
In /etc/init.d/domoticz.sh there is NO parameter of wwwbind
This is the partial output of 'sudo systemctl status domoticz.service'
Code: Select all
["domoticz_wwwbind"]="0.0.0.0"
Code: Select all
Status: WebServer(HTTP) started on address: 0.0.0.0 with port 8080
Status: WebServer(SSL) started on address: 0.0.0.0 with port 443
Status: Camera: settings (re)loaded
Starting shared server on: 0.0.0.0:6144
This is the partial output of 'sudo systemctl status domoticz.service'
Code: Select all
Process: 836 ExecStart=/etc/init.d/domoticz.sh start (code=exited, status=0/SUCCESS)
Tasks: 39 (limit: 4915)
CGroup: /system.slice/domoticz.service
└─1338 /home/pi/domoticz/domoticz -daemon -www 8080 -loglevel info -log /var/log/domoticz.log -dbase /home/pi/domoticz/domoticz.db
- waaren
- Posts: 6028
- Joined: Tuesday 03 January 2017 14:18
- Target OS: Linux
- Domoticz version: Beta
- Location: Netherlands
- Contact:
Re: Run script if device left on for a period of time?
OK I guess somewhere in your config the wwwbind is set to 0.0.0.0 but I have no idea where to search for it.EddyG wrote: ↑Monday 15 February 2021 16:20 I did that and now I see in the logging ->Code: Select all
["domoticz_wwwbind"]="0.0.0.0"
Until you find it, probably the easiest is to just keep using your work around.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
-
- Posts: 84
- Joined: Friday 12 May 2017 20:03
- Target OS: -
- Domoticz version:
- Contact:
Re: Run script if device left on for a period of time?
Code: Select all
dz.data.activeDevices[key] < os.time()
Last edited by geertvercamer on Tuesday 16 February 2021 16:15, edited 1 time in total.
- waaren
- Posts: 6028
- Joined: Tuesday 03 January 2017 14:18
- Target OS: Linux
- Domoticz version: Beta
- Location: Netherlands
- Contact:
Re: Run script if device left on for a period of time?
No because you set it at an earlier stage togeertvercamer wrote: ↑Monday 15 February 2021 17:43won't this always give true?Code: Select all
dz.data.activeDevices[key] < os.time()
os.time() + maxOnSeconds
So it it will only become true after maxOnSeconds seconds passed by since it was set.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
-
- Posts: 84
- Joined: Friday 12 May 2017 20:03
- Target OS: -
- Domoticz version:
- Contact:
Re: Run script if device left on for a period of time? [Solved]
I think I get it. The function scheduleStillActiveCheck is called which fires the URL after x seconds, but doesn't wait for maxOnSeconds + 1 to return.
Thanks waaren!
Thanks waaren!
Who is online
Users browsing this forum: No registered users and 1 guest