Page 2 of 17
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Monday 07 March 2016 21:44
by commodore white
Hi. I thought I'd try something really simple, a script that simply reports when an event occurs. The script is:
Code: Select all
return {
on = {
"CPU"
},
active = true,
execute = function(domoticz, sensor)
-- print(sensor.name .. " triggered")
print(' CPU triggered')
end
}
However, even this results in errors being reported for no apparent reason, as follows:
Code: Select all
2016-03-07 16:58:44.479 LUA: Handling events for: "CPU", value: ""
2016-03-07 16:58:44.479 LUA: =====================================================
2016-03-07 16:58:44.480 LUA: >>> Handler: test
2016-03-07 16:58:44.480 LUA: >>> Device: CPU
2016-03-07 16:58:44.480 Error: EventSystem: /home/pi/domoticz/scripts/lua/event_helpers.lua:10: bad argument #1 to 'format' (number expected, got nil)
2016-03-07 16:58:54.832 (RFXCOM) Temp (envKitchen)
2016-03-07 16:58:55.393 (RFXCOM) Humidity (envKitchen)
2016-03-07 16:59:00.134 LUA: Phones: Peter's phone found 1h 32m ago
2016-03-07 16:59:00.135 LUA: Phones: Rita's phone lost 0h 0m ago
Note, I had made a slight alteration to the script to better understand what was going on, as follows:
Code: Select all
for eventIdx, eventHandler in pairs(events) do
print('=====================================================')
print('>>> Handler: ' .. eventHandler.name )
if (device) then
printf('>>> Device: %s', device.name)
printf('>>> Index : %d', device.id)
end
Unfortunately, I couldn't track down where device.id was populated.
Regards
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Thursday 10 March 2016 19:33
by dannybloe
simonrg wrote:The thing to do would be add this information to the device object in the table that dzVents creates. This would allow filtering in the spirit of dzVents.
To reduce the number of device dumps which are needed from Domoticz, it would make sense to have a standard timer script that runs every minute, which would do the json call and save the complete device object table to a file, which would be read in each time a script is executed to create the device object, with some items being updated from otherdevices / devicechanged tables to keep it current.
Today I experimented a bit with getting a full json dump of all (active) devices in order to get at least the battery status into dzVents. I used os.execute etc but I noticed that more often than not it brought Domoticz to a stand still with errors that scripts are taking longer than 10 seconds to complete etc. I even had to restart my Pi at one time. But yeah, it could be possible to have some script that fetches the json and incorporate that into the de device object. If I can come up with a way to get the json without killing Domoticz... Maybe detach the os.execute somehow and then in the next cycle see if there's a devices.json somewhere....
Once it's there then I can get all the values into the devices.
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Thursday 10 March 2016 19:37
by dannybloe
commodore white wrote:Hi. I thought I'd try something really simple, a script that simply reports when an event occurs. The script is:
However, even this results in errors being reported for no apparent reason, as follows:
Did you use the latest version from GitHub? I cannot find this line there that could cause the problem:
Code: Select all
event_helpers.lua:10: bad argument #1 to 'format'
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Thursday 10 March 2016 20:35
by Westcott
In Lua, get a JSON device dump, and decode it, like this for (light)switches.
It checks the description to see if devices in Plan 2 contain a MAC address.
Code: Select all
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
jsonurl = 'curl http://127.0.0.1:8080/json.htm?type=devices&filter=light&used=true&order=Name'
jsondata = assert(io.popen(jsonurl))
jsondevices = jsondata:read('*all')
jsondata:close()
data = json:decode(jsondevices)
devices = {}
for x, dd in pairs(data.result) do
if (dd.PlanID == '2') then
mac = string.match(dd.Description, "%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
if (mac ~= nil) then
devices[dd.Name] = mac
end
end
end
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Thursday 10 March 2016 21:29
by dannybloe
I managed to get the json stuff without crashing Domoticz.
Code: Select all
nohup curl 'http://xxx:yyy/json.htm?type=devices&displayhidden=1&filter=all&used=true' -s -o '/home/pi/domoticz/scripts/lua/devices.json' 2> /dev/null &
However, decoding the resultset for all devices takes way too long and I don't want to make loads of single requests to D.
Maybe a bash script can do some filtering and prepocessing but I don't want users having to do all kinds of linux wizardry in order to have some extra device attributes.. So.. any ideas?
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Thursday 10 March 2016 22:37
by simonrg
dannybloe wrote:However, decoding the resultset for all devices takes way too long and I don't want to make loads of single requests to D.
The quicker way to get the information is directly in Lua, using the socket/http/json libraries (on Raspberry Pi the libaries can be installed as
http://www.domoticz.com/wiki/Remote_Con ... _Libraries) - demo just prints all your devices in the log with their type and id.
Code: Select all
-- script_time_getdevicedata.lua
-- Load necessary Lua libraries
http = require "socket.http";
socket = require "socket";
https = require "ssl.https";
JSON = require "JSON";
commandArray = {}
DomoticzIP = "127.0.0.1"
DomoticzPort = "8080"
server_url = "http://"..DomoticzIP..":"..DomoticzPort
-- Retrieve all the device data
jresponse, status = http.request(server_url.."/json.htm?type=devices")
decoded_response = JSON:decode(jresponse)
i = 0
for k,record in pairs(decoded_response) do
print(k..' record '..type(record))
if type(record) == "table" then
for k, v in pairs(record) do
i = i + 1
k1 = k
v1 = v
-- Print out device and type for demonstration
print(v.Name..' has id '..v1.idx..' and is type '..v.Type)
end
else
print(record)
end
end
--print(v1.Name..' has id '..v1.idx..' and is type '..v1.Type)
print(i..' devices found')
return commandArray
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Thursday 10 March 2016 23:25
by commodore white
The way I've approached this in the past, as have others, is to prefix a devices's type ahead of its name. So, for instance, all my PIRs have names of the form pirXXXXX, eg, pirKitchen, pirHall. In regular LUA, all I'd need to do is have a device-script that triggered if the device that triggered it had "pir" as the first 3-characters of its name. c.f
Code: Select all
d=next(devicechanged)
if d:sub(1,3) == "pir" then whatever end
I could do something similar in DzVents by triggering using the "on = { "*" }" construct though this would sidestep some of the speed benefits that might be on offer. Perhaps DzVents could be extended to allow "on={"pir*"}" as a trivial (and selfish) example of wildcards.
Might be easier than trying to populate a devicetype table each minute on the off-chance someone has added or removed a device. Though even this will require DzVents to itterate through the otherdevices array. Sigh.
Peter
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Thursday 10 March 2016 23:41
by commodore white
Anyone tell me whats wrong with this:
Code: Select all
return {
on = { "*"},
active = true,
execute = function(domoticz, sensor)
print(sensor.name .. " triggered")
end
}
I keep getting this so I cant make any progress:
Code: Select all
LUA: /home/pi/domoticz/scripts/lua/scripts/test.lua:6: attempt to index local 'sensor' (a nil value)
2016-03-10 23:34:51.513 LUA: An error occured when calling event handler test
2016-03-10 23:34:51.513 LUA: .....................................................
2016-03-10 23:34:51.513 LUA: >>> Handler: test
2016-03-10 23:34:51.512 LUA: =====================================================
2016-03-10 23:34:51.512 LUA: Handling events for: "*", value: ""
2016-03-10 23:34:51.301 LUA: -----------------------------------------------------
2016-03-10 23:34:51.301 LUA: <<< Done
2016-03-10 23:34:51.300 LUA: .....................................................
2016-03-10 23:34:51.300
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Thursday 10 March 2016 23:45
by commodore white
Thanks for your JSON suggestions guys. I'll look through it all tomorrow.
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Friday 11 March 2016 1:04
by commodore white
dannybloe wrote:commodore white wrote:Hi. I thought I'd try something really simple, a script that simply reports when an event occurs. The script is:
However, even this results in errors being reported for no apparent reason, as follows:
Did you use the latest version from GitHub? I cannot find this line there that could cause the problem:
Code: Select all
event_helpers.lua:10: bad argument #1 to 'format'
Yes, using the latest but I tinkered with the helper program to track down why I wasn't getting the idx back for a sensor. Turns out I'm not getting much back from dzvents scripts as my most recent post shows.
I'd like to use this stuff and be a contributor lest it wither on the vine like several other fine ideas.
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Friday 11 March 2016 9:36
by thorbj
dannybloe wrote:Almost. Maybe it is a bit confusing in this domain of devices that can be on and off but the
on in the return object/module means something like: 'on a change execute blah' and not so much the state of a device. Get it?
So you should do it like this:
Code: Select all
return {
active = false, -- set to true to activate this script
on = {
'Low Lux',
'Chromecast',
'Overstyr',
'Nattmodus',
},
execute = function(domoticz, mySwitch)
if (mySwitch.state == 'On') then
domoticz.setScene('Stue PÅ dag', 'On')
end
end
}
So the 'on' key should be a list of devices that, when changed ('
on a change') will trigger the execute method. And in this example, when the execute method is called, mySwitch is the device that was actually changed. In this example I called it mySwitch but it can be any name that has a meaning to you. Could be just 'device' or 'changedDevice' or 'doorSensor' if the script is about door sensors that are changed.
So, just to make things clear: my advise is to have one script deal with only one kind of (related) event(s). So for instance, I have a couple of floating sensors in my roof gutters that switch on if the water level is too high (dirt blocking the pipes). All these sensors have a dummy switch in Domoticz and I have on script that deals with them:
Code: Select all
return {
on = {
250, 251, 252, 253 -- gutter sensors
},
active = true,
execute = function(domoticz, sensor)
if (sensor.state == 'On') then
domoticz.notify('Gutter is clogged', sensor.name, domoticz.PRIORITY_EMERGENCY)
else
print('Nothing to take care off, all clear again')
end
end
}
That's all there is in this script file (called gutter_sensors.lua).
Thanks! It's a bit clearer now
But what if I have some switches that I want to be triggered ONLY if other switches are off - and vice versa. Can this be done with this script?
In my case I have the switch "Overstyr" (means override). If this is off, I want the script to operate as normal based on given conditions for lux, time of day, movement, etc. But if the override-switch is on, I want the script to do nothing.
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Friday 11 March 2016 10:00
by simonrg
thorbj wrote:Thanks! It's a bit clearer now
But what if I have some switches that I want to be triggered ONLY if other switches are off - and vice versa. Can this be done with this script?
In my case I have the switch "Overstyr" (means override). If this is off, I want the script to operate as normal based on given conditions for lux, time of day, movement, etc. But if the override-switch is on, I want the script to do nothing.
Once your script has been triggered by a single device changing, then you decide whether your script carries out an action you can do any other test you want inside your function just like you do with normal scripts. You can either use the logic you are currently using with otherdevices etc. or you can convert to the objects from dzVents.
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Friday 11 March 2016 11:11
by commodore white
Something is fundamentally wrong with my installation of dzvents since this code, a modification Dannys' original, doesnt work.
Code: Select all
return {
on = {
-- 250, 251, 252, 253 -- gutter sensors
95 -- virtual switch to test this nonsence
},
active = true,
execute = function(domoticz, sensor)
if (sensor.state == 'On') then
domoticz.notify('Gutter is clogged', sensor.name, domoticz.PRIORITY_EMERGENCY)
else
print('Nothing to take care off, all clear again')
end
end
}
Whats wrong??
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Friday 11 March 2016 15:15
by commodore white
Changed the condition from an idx to a string and got this!
Code: Select all
Hardware Monitor: : Fetching data (System sensors)
2016-03-11 14:04:34.910 Squeezebox: : (Kitchen Player 1Gb) On
2016-03-11 14:04:27.383 (Virtual) Lighting 1 (DzVents)
2016-03-11 14:04:27.533 Error: EventSystem: : /home/pi/domoticz/scripts/lua/event_helpers.lua:60: attempt to concatenate field 'id' (a nil value)
2016-03-11 14:04:27.533 LUA: >>> Handler: test
2016-03-11 14:04:27.533 LUA: =====================================================
2016-03-11 14:04:27.532 LUA: Handling events for: "DzVents", value: "Off"
2016-03-11 14:04:21.603 (Virtual) Lighting 1 (DzVents)
2016-03-11 14:04:21.749 Error: EventSystem: : /home/pi/domoticz/scripts/lua/event_helpers.lua:60: attempt to concatenate field 'id' (a nil value)
2016-03-11 14:04:21.749 LUA: >>> Handler: test
2016-03-11 14:04:21.749 LUA: =====================================================
2016-03-11 14:04:21.748 LUA: Handling events for: "DzVents", value: "On"
2016-03-11 14:04:17.177
The thick plottens.
Interesting. I commented-out the offending line 60 and some measure of normality has returned. And my first indication that all of this wasn't completely broke.
Code: Select all
return {
on = {
-- 250, 251, 252, 253 -- gutter sensors
"DzVents" -- virtual switch to test this nonsence
},
active = true,
execute = function(domoticz, sensor)
if (sensor.state == 'On') then
domoticz.notify('Gutter is clogged', sensor.name, domoticz.PRIORITY_EMERGENCY)
else
print('Nothing to take care off, all clear again')
end
print(next(devicechanged) .. " did it")
end
}
However, something is still strange as, in an "Off-On" transition, the devicechanged correctly shows the culprit as DzVents, while an "On-Off" event, the devicechanged array seems to get a "*".
Code: Select all
2016-03-11 15:02:51.699 LUA: Handling events for: "DzVents", value: "Off"
2016-03-11 15:02:51.699 LUA: =====================================================
2016-03-11 15:02:51.699 LUA: >>> Handler: test
2016-03-11 15:02:51.700 LUA: .....................................................
2016-03-11 15:02:51.700 LUA: Nothing to take care off, all clear again
2016-03-11 15:02:51.700 LUA: * did it
2016-03-11 15:02:51.700 LUA: .....................................................
2016-03-11 15:02:51.701 LUA: <<< Done
2016-03-11 15:02:51.701 LUA: -----------------------------------------------------
2016-03-11 15:02:51.499 (Virtual) Lighting 1 (DzVents)
2016-03-11 15:02:54.385 LUA: Handling events for: "DzVents", value: "On"
2016-03-11 15:02:54.386 LUA: =====================================================
2016-03-11 15:02:54.386 LUA: >>> Handler: test
2016-03-11 15:02:54.386 LUA: .....................................................
2016-03-11 15:02:54.386 LUA: DzVents did it
2016-03-11 15:02:54.387 LUA: .....................................................
2016-03-11 15:02:54.387 LUA: <<< Done
2016-03-11 15:02:54.387 LUA: -----------------------------------------------------
2016-03-11 15:02:54.387 LUA: [1] = SendNotification: Gutter is clogged#DzVents#2
2016-03-11 15:02:54.387 LUA: =====================================================
2016-03-11 15:02:55.393 Notification sent (lms) => Success
2016-03-11 15:02:56.094 Notification sent (pushbullet) => Success
2016-03-11 15:02:56.095 EventSystem: Script event triggered: /home/pi/domoticz/scripts/lua/script_device_main.lua
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Friday 11 March 2016 18:39
by dannybloe
Wow.. I missed so many messages here. Guess I'm not subscribed to my own thread.. will read up soon.
In the mean time I have been working on a new release (not yet commited) and these are the release notes:
[0.9.8]
- Fixed a bug where a device can have underscores in its name.
- Added dimTo(percentage) method to control dimmers.
- Modified the switch-like commands to allow for timing options: .for_min(), .within_min(), after_sec() and after_min() methods to control delays and durations. Removed the options argument to the switch functions. E.g. device.switchOn().after_sec(10).for_min(30). See readme.
- Added device.switchSelector method on a device to set a selector switch.
- Added wild-card option for triggers. E.g. 'PIR_*'
- Added http request data from Domoticz to devices. Now you can check the battery level and switch type and more. Make sure to edit dzVents_settings.lua file first and check the readme for install instructions!!!
Just to let you peeps know. Soon in this theater...
version 0.9.8 released
Posted: Friday 11 March 2016 22:29
by dannybloe
Just commited and tagged a new version on github. I also added a setting to control the logging (log level). Don't forget to edit dzVents_settings.lua!
Btw, fetching extra device data from Domoticz like battery info only works on linux file systems. It requires bash, curl and sed and lots of pipes
.
@commodore white: can you please test this version and perhaps set the log level to debug?
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Friday 11 March 2016 22:33
by dannybloe
Westcott wrote:In Lua, get a JSON device dump, and decode it, like this for (light)switches.
It checks the description to see if devices in Plan 2 contain a MAC address.
Code: Select all
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
jsonurl = 'curl http://127.0.0.1:8080/json.htm?type=devices&filter=light&used=true&order=Name'
jsondata = assert(io.popen(jsonurl))
jsondevices = jsondata:read('*all')
jsondata:close()
data = json:decode(jsondevices)
devices = {}
for x, dd in pairs(data.result) do
if (dd.PlanID == '2') then
mac = string.match(dd.Description, "%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
if (mac ~= nil) then
devices[dd.Name] = mac
end
end
end
I tried some lua json decoders and encoders but they didn't like the long dumps coming from Domoticz. What decoder is this?
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Friday 11 March 2016 22:35
by commodore white
Looking forward to the update.
- Fixed a bug where a device can have underscores in its name.
Yeah. Stumbled into that bug pretty quick
- Added dimTo(percentage) method to control dimmers.
Makes sence. Also be nice to have ".duration(nnn)" to define how long the fade should take
- Modified the switch-like commands to allow for timing options: .for_min(), .within_min(), after_sec() and after_min() methods to control delays and durations. Removed the options argument to the switch functions. E.g. device.switchOn().after_sec(10).for_min(30).
Consistent approach is good
- Added device.switchSelector method on a device to set a selector switch.
No idea what this is but I bet its going to be handy
- Added wild-card option for triggers. E.g. 'PIR_*'
Wish I'd thought of that!
- Added http request data from Domoticz to devices. Now you can check the battery level and switch type and more.
Wonder if this will place a lower limit on the spec of cpu?
It'll be interesting to see how long it takes dzVents to gain traction. Might need a catchier name first though.
Peter
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Friday 11 March 2016 23:52
by Westcott
I tried some lua json decoders and encoders but they didn't like the long dumps coming from Domoticz. What decoder is this?
It's the JSON.lua utility as described somewhere in the Wiki, and is loaded into the Lua script by the call -
json = (loadfile "/home/pi/domoticz/scripts/lua/JSON.lua")()
The JSON call and decode takes less than 1 second.
Re: Introducing dzVents - Domoticz Lua file based event scripting made e-z!
Posted: Saturday 12 March 2016 0:19
by dakipro
dear sir this is brilliant!
As a developer myself (php though) I was looking at some way to organize the code and group functions, but this is exactly what I needed!
I managed to make "night motion lights" script that will turn on the lights on motion and then turn them off after ~2min. All that in basically 10 lines, wheres before it would be 30 with a bunch of if elses and parsing and things..
Code: Select all
on = {
39, -- index of the device - 39 book motion
['timer'] = 'every other minute', -- minutes: xx:00, xx:02, xx:04, ..., xx:58
},
execute = function(domoticz, mySwitch) -- see readme for what you get
if (domoticz.devices[39].state == 'On') then
domoticz.devices[36].switchOn()
end
if(domoticz.devices[39].minutesAgo>1) then
domoticz.devices[36].switchOff()
end
end
And what is really beautiful is that I can run both motion controlled ON event
and the timer controlled OFF event in the same script.
Regarding of which, do you have a comment about a better way to write my script? Maybe you can make a folder on github and collect some of the common examples there?
I also tried using the mySwitch.state in the first if, it works on sensor change but when script runs on timer it never reaches the second if, I guess it brakes because the mySwitch doesn't exist on timer calls.