Page 2 of 2

Re: Some LUA magic: one script to rule them all..

Posted: Tuesday 23 February 2016 18:33
by Sicco28
Could it be you forgot to include the event_helpers.lua script in the latest: script-v0.9.2.zip ?

... the initial version 0.9 is returning an error:
Error: EventSystem: in /home/domoticz/scripts/lua/script_time_main.lua: /home/domoticz/scripts/lua/event_helpers.lua:162: bad argument #1 to 'pairs' (table expected, got nil)

Re: Some LUA magic: one script to rule them all..

Posted: Tuesday 23 February 2016 18:43
by dannybloe
Crap.. ur are right..

Re: Some LUA magic: one script to rule them all..

Posted: Tuesday 23 February 2016 19:30
by Sicco28
Yup, that worked, thanks! I will continue to implement and test.


Sent from my iPhone using Tapatalk

Re: Some LUA magic: one script to rule them all..

Posted: Tuesday 23 February 2016 20:32
by JustME125
I see something that will eat up a lot of the quality time with the misses [GRINNING FACE WITH SMILING EYES]. Going to give it a try soon. Expect some silly questions as I am no programmer ;)

Verstuurd vanaf mijn HTC One_M8 met Tapatalk

Re: Some LUA magic: one script to rule them all..

Posted: Wednesday 24 February 2016 12:10
by dannybloe
I found a bug that prevented execution of the scripts as soon as one script was set to be inactive. Fixed that one.

Also added something extra: the device scripts not only receive the value but also the name and the index of the device triggering the script. This again saves you some code and is handy if you have multiple triggers/devices triggering one script:

Code: Select all

return {
	active = true,
	on = {
		47, -- ventilator
		46 -- lighting
	},
	execute = function(value, deviceName, deviceIndex)
		local commandArray = {}

		if (deviceIndex == 47 and value == 'On') then
			-- ventilator was turned on
		end
		
		if (deviceIndex == 46 and value == 'Off') then
			-- lights were turned off
		end

		return commandArray
	end
}

Re: Some LUA magic: one script to rule them all..

Posted: Wednesday 24 February 2016 19:23
by simonrg
dannybloe wrote:Also added something extra: the device scripts not only receive the value but also the name and the index of the device triggering the script. This again saves you some code and is handy if you have multiple triggers/devices triggering one script:
New simpler approach is looking interesting :D

A lot of my devices change their idx whenever I need to replace the batteries, so I try to work solely with names and look up idx, made a lot easier with otherdevices_idx table.

All your examples seem to give the idx rather than the name of the device, I assume I could just give the name of the device.

Re: Some LUA magic: one script to rule them all..

Posted: Wednesday 24 February 2016 19:35
by dannybloe
I didn't know you'd get new indexes. But yes, you can use the name as the trigger. As you can see in example.lua.

Re: Some LUA magic: one script to rule them all..

Posted: Wednesday 24 February 2016 21:50
by Toni
I added the 'otherdevices_idx[]' a while ago, as some of the commands absolutely require the IDX, and there was no way to get it in Lua.

Like, updating the state of a multiselector device so that it also fires a new event on the selector:

Code: Select all

commandArray['OpenURL'] = 'http://127.0.0.1:8080/json.htm?type=command&param=udevice&idx=' .. otherdevices_idx['name of your multiselector'] .. '&svalue=10'

Re: Some LUA magic: one script to rule them all..

Posted: Thursday 25 February 2016 19:18
by Sicco28
@Toni, slightly off-topic, but you can actually use this in LUA:

commandArray[<random order>]={ ['UpdateDevice']='<idx>|0|' .. <integer value> }

e.g. commandArray[1]={ ['UpdateDevice']='171|0|' .. lightLevel }

@Danny, the version 0.9.3 seems to run stable for over a day now :) Good stuff!

Re: Some LUA magic: one script to rule them all..

Posted: Friday 26 February 2016 10:39
by dannybloe
Thanks @Sicco28.
I'm still playing with the idea to have some more control over the timer events. Right now it fires every minute but I've noticed that people would like to have some larger intervals like every 5 minutes or maybe every hour. Now I think that can easily be done by this system as well so, and I am thinking out loud, something like this:

Code: Select all

	on = {
		-- pick one
		['timer'] = 'every minute',       -- minutes: xx:00, xx:01, xx:02, ..., xx:59
		['timer'] = 'every other minute', -- minutes: xx:00, xx:02, xx:04, ..., xx:58
		['timer'] = 'every 5 minutes',    -- minutes: xx:00, xx:05, xx:10, ..., xx:55
		['timer'] = 'every 10 minutes',   -- minutes: xx:00, xx:10, xx:20, ..., xx:50
		['timer'] = 'every 15 minutes',   -- minutes: xx:00, xx:15, xx:30, xx:45
		['timer'] = 'every 20 minutes',   -- minutes: xx:00, xx:20, xx:40
		['timer'] = 'every 30 minutes',   -- minutes: xx:00, xx:30
		['timer'] = 'every 60 minutes',   -- minutes: xx:00
		['timer'] = 'every hour',         -- minutes: 00:00, 01:00, ..., 23:00  (24x per 24hrs)
		['timer'] = 'every 2 hours',      -- minutes: 00:00, 02:00, ..., 22:00  (12x per 24hrs)
		['timer'] = 'every 3 hours',      -- minutes: 00:00, 03:00, ..., 21:00  (8x per 24hrs)
		['timer'] = 'every 4 hours',      -- minutes: 00:00, 04:00, ..., 20:00  (6x per 24hrs)
		['timer'] = 'every 6 hours',      -- minutes: 00:00, 06:00, 12:00, 18:00 (4x per 24hrs)
		['timer'] = 'every 12 hours',     -- minutes: 00:00, 12:00, (2x per 24hrs)
		['timer'] = 'every 24 hours',     -- minutes: 00:00, (1x per 24hrs),
		['timer'] = 'at 13:45',
		['timer'] = {'at 13:45', 'at 18:37'},
	}
I think that is not so hard to do and it gives you a lot more flexibility and you don't have to write the horrible Lua code for dealing with times.
Now the only issue we might have here is that the timer events are called every minute by Domoticz at 00 seconds. But of course there is no guarantee that if you have a trigger set 'at 13:45' and for some reason Domoticz skips the event at 13:45, you miss that trigger. But of course that's not a problem I guess.

Re: Some LUA magic: one script to rule them all..

Posted: Friday 26 February 2016 13:54
by dannybloe
Ok, so, I just implemented configurable timer triggers. You now have a lot more control over your timed scripts and define timer schedules. This is an excerpt from the readme:

timer options

There are several options for time triggers. First, as you perhaps know, Domoticz event system only calls timer events every minute. So the smallest interval you can use for timer triggers is... you guessed it... one minute. But to prevent you from coding all kinds of timer functions, you can have all kinds of timer triggers that can all be combined for your convenience (all times are in 24hr format!):

Code: Select all

on = {
    'timer'                           -- the simplest form, causes the script to be called every minute
    ['timer'] = 'every minute',       -- same as above: every minute
    ['timer'] = 'every other minute', -- minutes: xx:00, xx:02, xx:04, ..., xx:58
    
    ['timer'] = 'every <xx> minutes', -- starting from xx:00 triggers every xx minutes (0 > xx < 60)

    ['timer'] = 'every hour',         -- 00:00, 01:00, ..., 23:00  (24x per 24hrs)
    ['timer'] = 'every other hour',   -- 00:00, 02:00, ..., 22:00  (12x per 24hrs)
    ['timer'] = 'every <xx> hours',   -- starting from 00:00, triggers every xx hours (0 > xx < 24)
    
    ['timer'] = 'at 13:45',           -- specific time
    ['timer'] = 'at *:45',            -- every 45th minute in the hour
    ['timer'] = 'at 15:*',            -- every minute between 15:00 and 16:00
    
    -- and last but not least, you can create a table with multiples:
    ['timer'] = {'at 13:45', 'at 18:37', 'every 3 minutes'},

},
One important note: if Domoticz for whatever reason skips a beat (skips a timer event) then you may miss the trigger! So you may have to build in some fail-safe checks or some redundancy if you have critical time-based stuff to control.

So, isn't that nice? :lol:

Just an example of a script:

Code: Select all

return {
	active = true,
	on = {
		['timer'] = {'at 8:00', 'at 18:00'}
	},

	execute = function()
		local commandArray = {}
		commandArray['Heater'] = 'On'
		return commandArray
	end
}
So what's next?
How about something like this?:

Code: Select all

	on = {
		['timer'] = {'at 8:00 on {'We', 'Tu, 'Fr', 'Sat'} }, -- day markers
		['timer'] = {'at 8:00-9:00 },  -- time range
		['timer'] = 'sunset',
		['timer'] = {'at ~8:00'},  -- around 8
	},
I know Domoticz has all kinds of schedule support through the GUI but some things may be easier to program or people just don't like GUIs ;-)

But that's for another day...(my vacation is almost over)

Re: Some LUA magic: one script to rule them all..

Posted: Friday 26 February 2016 14:50
by NietGiftig
Thanks!
I don't comprehend it all at the moment, but that is because I have to master the basics of Lua
As always, the best way of learning is trying things out.

Re: Some LUA magic: one script to rule them all..

Posted: Friday 26 February 2016 15:01
by dannybloe
Ah what the heck... I couldn't help it... schedule galore!!:

I added the options to set time triggers for specific days and support for sunrise and sunset triggers:

Code: Select all

on = {
    ['timer'] = 'at 13:45 on mon,tue',     -- at 13:45 only on monday en tuesday (must be english!)
    ['timer'] = 'every hour on sat',       -- you guessed it correctly
    ['timer'] = 'at sunset',               -- uses sunset/sunrise info from Domoticz
    ['timer'] = 'at sunrise',
    ['timer'] = 'at sunset on sat,sun'
},
Time ranges and 'around <some time>' is more difficult and less trivial so I'm not going to add that. :mrgreen:

Re: Some LUA magic: one script to rule them all..

Posted: Friday 26 February 2016 17:47
by WebStar
When I try to use a function in the active variable, the function is script is always excecuted.

Code: Select all

return {
	active = function() return otherdevices['Thuis'] == 'On' end,                  -- set to true to activate this script,
								     --can also be a function returning either true or false
	on = {
		'Test',  -- see readme for more options and schedules
	},

	execute = function(value, deviceName, deviceIndex)
		local commandArray = {}

		print('Test function')
		print(otherdevices['Thuis'])

		return commandArray
	end
}
This is my function, but also when i write

Code: Select all

active = function() return false end,
The script is always excecuted, (I tried the code from version 0.9.5)
Do you know what i'm doing wrong?

Re: Some LUA magic: one script to rule them all..

Posted: Friday 26 February 2016 17:58
by dannybloe
Yup, I saw it. Fixed it in v0.9.6 (Some weird Lua logic)

Re: Some LUA magic: one script to rule them all..

Posted: Friday 26 February 2016 22:43
by dannybloe
I have moved the code to github and named it ezVents: https://github.com/dannybloe/ezVents. Feel free to contribute or comment.

Re: Some LUA magic: one script to rule them all..

Posted: Sunday 28 February 2016 0:08
by WebStar
Thank you for the quick fix :) I realy like the scripts/codes you created.

Only one other small thing, on github (and your zips) the folder is called 'script' but the configuration is looking for the folder 'scripts'.

Re: Some LUA magic: one script to rule them all..

Posted: Sunday 28 February 2016 0:18
by Sicco28
Maybe another 'feature' request: can we turn off/reduce the verbose logging per script? This setup generates a lot of device scripts (good thing :) ), but also generates a lot of log entries.

Re: Some LUA magic: one script to rule them all..

Posted: Tuesday 01 March 2016 23:39
by dannybloe
Sicco28 wrote:Maybe another 'feature' request: can we turn off/reduce the verbose logging per script? This setup generates a lot of device scripts (good thing :) ), but also generates a lot of log entries.
Ah, ok, good idea. Check out my post about dzVents (new name, lot's of new features).