Page 1 of 1

Run time scripts at different intervals than every minute

Posted: Wednesday 18 November 2015 18:43
by BakSeeDaa
Time scripts run once every minute.

Maybe You have time scripts that you want to run less frequently... let's say that You want to run it every 5 minutes instead. That can't be done but you can make some clever if-statements in it. I've seen it done before by saving a user variable, a counter every minute. I wanted a different solution that didn't write to the Domoticz database 1440 times every day.

I made a LUA time script named script_time_misc.lua where it put miscellaneous tasks.

Code: Select all

-- script_time_misc.lua
-------------------------------------
commandArray = {}

local m = os.date('%M')
if (m % 5 == 0) then
	print("The 5 minute script interval reached")
	-- Put your script code here that shall run every 5 minutes
end
if (m % 10 == 0) then
	print("The 10 minute script interval reached")
	-- Put your script code here that shall run every 10 minutes
end
if (m % 30 == 0) then
	print("The 30 minute script interval reached")
	-- Put your script code here that shall run every 30 minutes
end
if (m % 60 == 0) then
	print("The 60 minute script interval reached")
	-- Put your script code here that shall run every 60 minutes
end
return commandArray
Edit: There is an enhanced version of this script a few posts below :)
Happy coding! :D

Re: Run time scripts at different intervals than every minut

Posted: Wednesday 18 November 2015 20:24
by bizziebis
Works great indeed! :)

I tried to relief my system from heavy (LUA) load every start of the minute by shifting the start time of a script by 10 seconds or more.. But that didn't work for time scripts. It just doesn't check time scripts at times like 21:30:10 so it will never trigger Image

Do you know how to achieve this? So that script A will run at 21:30:00, B on 21:30:10 and C on 21:30:20?

I don't want to use sleep commands as it will only stall LUA scripts.

It works if you use dummy switches at the end of each script like 'commandArray['DummyB']='On AFTER 10' and trigger on devicechanged DummyB, but that's really messy.

Re: Run time scripts at different intervals than every minut

Posted: Thursday 19 November 2015 8:13
by BakSeeDaa
bizziebis wrote:Works great indeed! :)

I tried to relief my system from heavy (LUA) load every start of the minute by shifting the start time of a script by 10 seconds or more.. But that didn't work for time scripts. It just doesn't check time scripts at times like 21:30:10 so it will never trigger Image

Do you know how to achieve this? So that script A will run at 21:30:00, B on 21:30:10 and C on 21:30:20?

I don't want to use sleep commands as it will only stall LUA scripts.

It works if you use dummy switches at the end of each script like 'commandArray['DummyB']='On AFTER 10' and trigger on devicechanged DummyB, but that's really messy.
I keep my time-scripts to a minimum, always using device-scripts whenever possible and I use virtual switches for schedules that occurs every day etc. Heavy LUA load every start of a minute might be because of the device changes triggered by your time script. Every device script must be evaluated every time a single device changes. You've already started to use 'On AFTER 10' and I think it's an excellent idea to use that in Your time scripts for spreading out the load more evenly each minute.

Things to keep in mind:

1) Always check the devicechanged array in the devicescripts before doing anything.

Code: Select all

if (devicechanged["Disarm Z2-Z4"]) then
    if (otherdevices_svalues["Z2 Alarm"] ~= DISARMED) then
		b.OpenURL("http://"..b.localhost.."/json.htm?type=command&param=udevice&idx="..alarmVDevs[2].."&nvalue=0&svalue=" .. b.urlencode(DISARMED))
    end
end
2) Always check the device status before changing it.

Code: Select all

if otherdevices["Radio"] ~= "Off" then commandArray["Radio"] = "Off" end
Without the check above, the radio would go "Off" even if it´s already "Off" and it would trigger all your device scripts to evaluate in a vain.

3) In cases where the exact time between the intervals is not critical, I think that it makes sense to use the following type of command in time-scripts whenever adding something to the commandarray. It will spread out the events more evenly.

Code: Select all

commandArray[#commandArray + 1]={['Radio']="On AFTER "..math.random(10,50) }
(Random delay from 10 to 50 seconds. You may want to alter that to suit your needs)


Using the form commandArray[#commandArray + 1] makes it possible to schedule multiple commands for a single device using nested tables.

Run time scripts at different intervals than every minute

Posted: Friday 20 November 2015 7:47
by mvzut
The above worries me a bit. It should not be up to the user to worry about these things. I would expect that Domoticz has a scheduler built in to make sure commands are send nicely in order without the risk of a too high CPU load or other problems.
Using event-based scripts instead of time based doesn't help me much, I have so many devices in my device list (almost 200) that I have a device trigger every few seconds (mostly temperature and other sensors updating).
Therefore I have chosen the opposite approach: I have one time-based script that updates all my virtual sensors once a minute, instead of a device script that is called every few seconds. I only use device-based scripts for handling switches. I don't do any advanced scheduling as you describe, and have never had any issues so far! My CPU load is very constant at around 3% (Raspberry Pi 2).

But maybe my situation is different, I mostly deal with updating virtual sensors & switches, less with actual switching of lights etc. all the time.

Re: Run time scripts at different intervals than every minut

Posted: Friday 20 November 2015 20:23
by ceedebee
BakSeeDaa wrote:Time scripts run once every minute.

Maybe You have time scripts that you want to run less frequently... let's say that You want to run it every 5 minutes instead. That can't be done but you can make some clever if-statements in it. I've seen it done before by saving a user variable, a counter every minute. I wanted a different solution that didn't write to the Domoticz database 1440 times every day.

I made a LUA time script named script_time_misc.lua where it put miscellaneous tasks.



Happy coding! :D
Is it posible to call another lua file or function from this script? Or is it posible to include functions in an other file into a lua script?

Re: Run time scripts at different intervals than every minut

Posted: Saturday 21 November 2015 10:10
by BakSeeDaa
ceedebee wrote:Is it posible to call another lua file or function from this script? Or is it posible to include functions in an other file into a lua script?
It certainly is. But if Your reason for that is only to make your time-script more organized You can do something like this instead:

Code: Select all

-- script_time_misc.lua
-------------------------------------
commandArray = {}

local function runEvery5min()
	-- Put your script code here that shall run every 5 minutes
	-- Below is an example using nested tables commandarray and a random delay
	-- commandArray[#commandArray + 1]={['My Device']='Off AFTER '..math.random(10,50) }
end

local function runEvery10min()
	-- Put your script code here that shall run every 10 minutes
end

local function runEvery30min()
	-- Put your script code here that shall run every 30 minutes
end

local function runEvery60min()
	-- Put your script code here that shall run every 60 minutes
end

local m = os.date('%M')
if (m % 5 == 0) then
	runEvery5min()
end
if (m % 10 == 0) then
	runEvery10min()
end
if (m % 30 == 0) then
	runEvery30min()
end
if (m % 60 == 0) then
	runEvery60min()
end

return commandArray
But if you have functions or variables that you want to define in one single place and then call from multiple Lua scripts it makes sense to put them in a module like this:

First create the commonly used script file, the "module". In this example we call it myFunctions.lua
Put it in your Lua scripts folder.

Code: Select all

-----------------------------------------------------------------------------
--	myFunctions.lua: A module with various functions aimed for Domoticz

local mf = {}  -- Public namespace

mf.HELLO = "Hello world" -- Just an example

function mf.blinkLight(light, times)
	times = times or 2
	local cmd1 = 'Off'
	local cmd2 = 'On'
	local pause = 0
	if (otherdevices[light] == 'Off') then
		cmd1 = 'On'
		cmd2 = 'Off'
	end	
	for i = 1, times do
		commandArray[#commandArray + 1]={[light]=cmd1..' AFTER '..pause }
		pause = pause + 3
		commandArray[#commandArray + 1]={[light]=cmd2..' AFTER '..pause }
		pause = pause + 3
	end
end

return mf
Then, in your ordinary device-script or time-script you can use the functions (or variables) like this:

Code: Select all

if (devicechanged["My Button"]) then
	local mf = require("scripts/lua/myFunctions")
	print(mf.HELLO)
	mf.blinkLight("My Living Room Light")
end
ONLY IF YOU ARE NOT ON A RASPBERRY PI
Note: The require statement local mf = require("scripts/lua/myFunctions") will probably only work on Raspberry Pi. If You are running Domoticz on a different distribution you must help Lua to find the path of your Lua scripts folder.
In that case put this line before the line with the require statement

Code: Select all

package.path = "/usr/local/domoticz/scripts/lua/?.lua;"..package.path

You should of course replace /usr/local/domoticz/scripts/lua/ with whatever the actual lua script name folder path is on your installation.

Re: Run time scripts at different intervals than every minut

Posted: Saturday 21 November 2015 19:27
by ceedebee
Thnx for your explanation, it is for both purposes: organization and reuse of code

Re: Run time scripts at different intervals than every minut

Posted: Sunday 22 November 2015 15:09
by NietGiftig
But if Your reason for that is only to make your time-script more organized You can do something like this instead:
Thanks for this write-up, useful for starters like me

Re: Run time scripts at different intervals than every minute

Posted: Wednesday 04 January 2017 15:39
by Derik
@ Bakseedaa

Thanks for this option..
Need this for my moonphase script. that runs to often so i was killing my api...


Do you have perhaps great scripts that you are running with this option?

Re: Run time scripts at different intervals than every minute

Posted: Wednesday 04 January 2017 16:14
by Toulon7559
Not new (already available here to control periodic, low-frequent upload of data to meteo-sites etc.) and perhaps an open door, but the following lines are a similar solution if you organise repeating time in minutes relative to t=0 minutes at the full hour.
- Interval is a local variable which you can set to your needs, defining the interval-time
- Offset is also a local variable, which defines the delay relative to the time defined by Interval
You can adjust for each desired Scriptloop by setting a dedicated set of Interval and Offset.

Code: Select all

-- Current date as date.year, date.month, date.day, date.hour, date.min, date.sec
date = os.date("*t")
-- Scriptloop1
if (date.min % Interval == Offset) then
     <script/instructions>
end

Re: Run time scripts at different intervals than every minute

Posted: Thursday 05 January 2017 10:32
by Derik
mmm something strange....
Until last night works great:
ScreenShot187.jpg
ScreenShot187.jpg (189.66 KiB) Viewed 16279 times
Only @ this moment....
ScreenShot188.jpg
ScreenShot188.jpg (72.26 KiB) Viewed 16279 times
No script running.
Is there something that i can do?

Re: Run time scripts at different intervals than every minute

Posted: Tuesday 04 July 2017 12:32
by Pjedr
Try also using the nohup (no hang up) function and & at the end of your executions to start it in a new process.
Then the lua scripts immidiatly continues, while the executions kan still go on, like pinging every few seconds every minute.
So the time script does basically nothing else then lunching external tools\scripts.

Code: Select all

commandArray={} LogLvl=uservariables['Nivo Lua Script Logging']
if LogLvl >= 3  then print('module_ping_ipdevices') end
local f=io.popen('/var/ramdrive/scripts/RunFromRamDisk.sh') local l=f:read("*a") f:close()
if l=='yes' then sRunDir='/var/ramdrive' else sRunDir='/opt/domoticz-extra' end
sScriptsDir=sRunDir..'/scripts' --print('sScriptsDir='..sScriptsDir)
--/var/ramdrive/Ping.sh benodigd met 3 parameters: <ip-adres> <status On\Off> <idx-nummer>
if LogLvl >= 4  then print('module_ping_lgg4_phone') end
os.execute('nohup '..sScriptsDir..'/Ping.sh 192.168.192.123 '..otherdevices['Ping LG G4 Android Telefoan']..' 932 2>/dev/null &')
..............<I ping 22 devices every few seconds every minute here with options IP, devname, devid for switching via jsonurl>..........
return commandArray

Re: Run time scripts at different intervals than every minute

Posted: Tuesday 04 July 2017 12:36
by Pjedr
In case you are curriouse to my Ping.sh I use from the lua script:

Code: Select all

#!/bin/bash
sDomoticzServer="192.168.192.234:8080"; #ping -q -c1 -W 1
ping -c3 -w5 $1 > /dev/null; if  [ $? -eq 0 ]; then
 echo Node with IP: $1 is up.
 if [ "$2" == "On" ]; then echo Node with IP: $1 is nog steeds up.;
 else
  echo Node with IP: $1 is up gegaan.
  echo "Versturen van statuswijziging naar Domoticz server via json"
  echo curl -s -i -m 5 -H "Accept: application/json" "http://$sDomoticzServer/json.htm?type=command&param=switchlight&idx=$3&switchcmd=On"
  strCurl=`nice -n 10 curl -s -i -m 5 -H "Accept: application/json" "http://$sDomoticzServer/json.htm?type=command&param=switchlight&idx=$3&switchcmd=On"`
 fi
else
 echo Node with IP: $1 is down.
 if [ "$2" == "On" ]; then
  echo Node with IP: $1 is down gegaan.
  echo "Versturen van statuswijziging naar Domoticz server via json"
  echo curl -s -i -m 5 -H "Accept: application/json" "http://$sDomoticzServer/json.htm?type=command&param=switchlight&idx=$3&switchcmd=Off"
  strCurl=`nice -n 10 curl -s -i -m 5 -H "Accept: application/json" "http://$sDomoticzServer/json.htm?type=command&param=switchlight&idx=$3&switchcmd=Off"`
 else echo Node with IP: $1 is nog steeds down.;
 fi
fi