Page 1 of 7
dzVents 1.0 released
Posted: Thursday 26 May 2016 15:47
by dannybloe
Hi folks,
Today I thought it was about time to make a 1.0 release of
dzVents. It has all the features that I wanted for a 1.0 release and some people successfully tested the dev branch so
here we go.
For those of you who don't know what it is or
if you are just starting to discover Lua scripting for Domoticz, here is an excerpt from the readme:
dzVents (|diː ziː vɛnts| short for Domoticz Easy Events) brings Lua scripting in Domoticz to a whole new level. Writing scripts for Domoticz has never been so easy. Not only can you define triggers more easily, and have full control over timer-based scripts with extensive scheduling support, dzVents presents you with an easy to use API to all necessary information in Domoticz. No longer do you have to combine all kinds of information given to you by Domoticzs in many different data tables. You don't have to construct complex commandArrays anymore. dzVents encapsulates all the Domoticz peculiarities regarding controlling and querying your devices. And on top of that, script performance has increased a lot if you have many scripts because Domoticz will fetch all device information only once for all your device scripts and timer scripts.
Please take some time to read the installation instructions. It's not difficult (and has some changes regarding the settings for those of you who already have settings). I have spent quite some time to document everything but of course it is still possible that some things aren't clear. Just let me know and I'll fix or explain it and don't forget to look at the examples.
And... it is software so there's no guarantee there are no bugs but when there are, please report issues in the
GitHub tracker. I'll respond quickly and usually fix problems right away.
For those of you who already used a previous version, these are the latest changes (from the history file):
[1.0][1.0-beta2]
- Deprecated setNew(). Use add() instead. You can now add multiple values at once in a script by calling multiple add()s in succession.
- Fixed printing device logs when a value was boolean or nil
- Fixed WActual/total/today for energy devices.
- Added updateSetPoint method on devices for dummy thermostat devices and EvoHome setpoint devices
- Added couple of helper properties on Time object. See README.
- Renamed the file dzVents_settings.lua to dzVents_settings_example.lua so you don't overwrite your settings when you copy over a new version of dzVents to your system.
[1.0-beta1]
- Added data persistence for scripts between script runs (see readme for more info)
- Added a time-line based data type for you scripts with historical information and many statistical functions for retreiving information like average, minumum, maximum, delta, data smoothing (averaging values over neighbours) etc. See readme for more information.
- Added SMS method to the domoticz object.
- Added toggleSwitch() method to devices that support it.
- Added more switch states that control device.bState (e.g. on == true, open == true 'all on' == true)
- Added secondsAgo to the lastUpdate attribute
- Added tests (test code coverage is above 96%!)
- Refactored code significantly.
- Made sure differently formulated but equal triggers in one script only execute the script only once (like MySensor and MySensor_Temperature).
- Added trigger info as a third parameter (Lua table) that is passed to the execute method of a script containing information about what exactly triggered the script (type = EVENT_TYPE_TIMER/EVENT_TYPE_DEVICE, trigger=<timer rule>). See readme.
- Added Lua time properties to domoticz.time property with all information about the current time (hours, minutes, seconds, etc.)
- Added option to return false in a forEach iteratee function which will abort the forEach loop.
- All devices not delivered by Domoticz to the event scripts are now added to domoticz.devices using the http data that is fetched every 30 minutes (by default).
- Added scenes and groups collections to the domoticz object
- Added Quick Reference Guide.
Enjoy and please send me feedback!
Re: dzVents 1.0 released
Posted: Thursday 26 May 2016 16:54
by Mediacj
Wow there is much new functionality since the last time I played with it!
Thank you for the development and sharing it!
Re: dzVents 1.0 released
Posted: Saturday 28 May 2016 19:44
by remb0
congratz.. very nice work!
Re: dzVents 1.0 released
Posted: Sunday 29 May 2016 20:48
by jkimmel
I would like to convert the script of
http://www.domoticz.com/forum/viewtopic ... tor#p72942
for dzVents.
Please help if possible with comments.
Re: dzVents 1.0 released
Posted: Sunday 29 May 2016 21:19
by woody4165
Hi
don't know if I'm doing something wrong, I'm having some problem with historic data
This is my script
Code: Select all
return {
active = true,
on = {
['timer'] = {
'every minute'
}
},
data = {
errori = { history = true, maxItems = 10 }
},
execute = function(domoticz)
url_esp = domoticz.variables[ip'].value
ping_success=os.execute('ping -r -q -c3 -W 1 '..url_esp)
if ping_success then
domoticz.devices['ip'].switchOn()
else
domoticz.data.errori.add(url_esp)
for i=1,10 do
local item = domoticz.data.errori.get(i)
if item.time.minutesAgo ~= nil then
message="elemento "..i.." = "..item.time.minutesAgo.." minuti fa"
print(message)
else
return
end
i=i+1
end
if item.time.minutesAgo < 5 then
print("ESP Irrigazione ping fail"..url_esp)
domoticz.devices['ip'].switchOff()
end
end
end
}
I get only historic data for element 1 and 2 and even if have the
domoticz.data.errori.add(url_esp) everytime ping go wrong, and I modified the ip so it always goes wrong, I get only two elements.
The information I need is
item.time.minutesAgo and the first element contains always 0 when printed, the second contains an incremental value every minute.
But what for the other 8 elements?
Do you see something wrong in my script?
Thanks
Re: dzVents 1.0 released
Posted: Monday 30 May 2016 9:20
by dannybloe
woody4165 wrote:Hi
don't know if I'm doing something wrong, I'm having some problem with historic data
This is my script
Code: Select all
return {
active = true,
on = {
['timer'] = {
'every minute'
}
},
data = {
errori = { history = true, maxItems = 10 }
},
execute = function(domoticz)
url_esp = domoticz.variables[ip'].value
ping_success=os.execute('ping -r -q -c3 -W 1 '..url_esp)
if ping_success then
domoticz.devices['ip'].switchOn()
else
domoticz.data.errori.add(url_esp)
for i=1,10 do
local item = domoticz.data.errori.get(i)
if item.time.minutesAgo ~= nil then
message="elemento "..i.." = "..item.time.minutesAgo.." minuti fa"
print(message)
else
return
end
i=i+1
end
if item.time.minutesAgo < 5 then
print("ESP Irrigazione ping fail"..url_esp)
domoticz.devices['ip'].switchOff()
end
end
end
}
I get only historic data for element 1 and 2 and even if have the
domoticz.data.errori.add(url_esp) everytime ping go wrong, and I modified the ip so it always goes wrong, I get only two elements.
The information I need is
item.time.minutesAgo and the first element contains always 0 when printed, the second contains an incremental value every minute.
But what for the other 8 elements?
Do you see something wrong in my script?
Thanks
First of all, I think you shouldn't be touching the control variable inside the for-loop (i=i+1) since that may lead in unpredictable results. Seconds, item.time.minutesAgo should never be nil. If that's the case then I suspect a bug in my code. Third, it is possible that there aren't 10 items yet in the store. Especially if you just start the script then there are no historical values. So it is better to do this:
Code: Select all
domoticz.data['errori'].forEach(function(item, index)
print(item, item.time.minutesAgo, index)
end)
See
data iterators in the documentation.
Can you try this and let me know what you see in the logs? Another thing you can check is the 'side-car file' where the data is stored. See
here for how to do this.
Oh and another tip: you can use domoticz.data['errori'].reset(). That clears the historical data. This may be useful as soon as you
do get a ping response. That way you only store errors UNTIL a response is received. Then you only have to count the number of items in the store:
Code: Select all
....
if ping_success then
domoticz.data['errori'].reset()
else
domoticz.data['errori'].add('oops')
end
if (domoticz.data['errori'].size >5) then
print('5 consecutive pings have failed')
end
In this example you basically count the errors until you receive a good ping.
Re: dzVents 1.0 released
Posted: Monday 30 May 2016 9:27
by dannybloe
I'll see if I can give a shot at it tonight or so (it always take some time to absorb the problem).
Re: dzVents 1.0 released
Posted: Monday 30 May 2016 20:52
by dannybloe
Hi jkimmel,
I think this could be very easy. I wouldn't do that string cutting stuff as in the original code but just use a simple lookup table. It makes the code easier to read imho:
Code: Select all
-- create a simple lookup table that links
-- a master device (on your remote) to a slave device (a true light switch)
-- note that the prefix 'master_' is arbitrary.
local masterSlave = {
master_A = 'switchA',
master_B = 'switchB',
master_C = 'switchC'
}
return {
active = true,
on = {
'master_*' -- all devices starting with master_* will trigger this script
},
execute = function(domoticz, masterSwitch)
-- get the slave device using the lookup table above
local slaveSwitch = domoticz.devices[masterSlave[masterSwitch.name]]
if (masterSwitch.state == 'On') then
slaveSwitch.switchOn()
else
slaveSwitch.switchOff()
end
end
}
Another option, if you don't want to use prefixes for your remote switches is doing this:
Code: Select all
local masterSlave = {
masterA = 'switchA',
someOtherMaster = 'switchB',
anotherMaster = 'switchC'
}
return {
active = true,
on = {
-- just name all your remote devices here that will trigger this script
'masterA',
'someOtherMaster',
'anotherMaster'
},
execute = function(domoticz, masterSwitch)
-- get the slave device using the lookup table above
local slaveSwitch = domoticz.devices[masterSlave[masterSwitch.name]]
if (masterSwitch.state == 'On') then
slaveSwitch.switchOn()
else
slaveSwitch.switchOff()
end
end
}
Re: dzVents 1.0 released
Posted: Monday 30 May 2016 21:34
by woody4165
Thanks dannybloe
The forEach is working fine, for sure my loop was doing something wrong to get that strange values.
Now I have to find a way to check not only how many item number but also if the item.minutesAgo is more than x minutes.
Re: dzVents 1.0 released
Posted: Monday 30 May 2016 21:38
by Atmosphere
APPLAUSE!!!!
This is the greatest addon to Domoticz for a long time.... It makes LUA scripting soo much easier!
Thank you for all your hard work Danny!
Examples i've created today:
-- Script for controlling the light sensitivity of my Foscam IP cam (FW8904)
-- Snapshots are now controlled by the lux amount setting the right conditions for the perfect picture, no over/underlight anymore!
-- replace <ipaddress>, <user> and <pass> with your own
return {
active = true,
on = { ['timer'] = 'every 10 minutes'},
execute = function(domoticz)
local VoordeurLuxSensor = domoticz.devices['Deur - Achter - Licht Sensor']
if VoordeurLuxSensor.lux >= 750 then
domoticz.log('Camera in Outdoor Mode', domoticz.LOG_INFO)
domoticz.openURL('http://<ipaddress>:80/camera_control.cgi?param=3&value=2&user=<user>&pwd=<pass>')
end
if (VoordeurLuxSensor.lux >= 500 and VoordeurLuxSensor.lux < 750) then
domoticz.openURL('http://<ipaddress>:80/camera_control.cgi?param=1&value=64¶m=3&value=1&user=<user>&pwd=<pass>')
domoticz.log('Camera in Inside Light Mode', domoticz.LOG_INFO)
end
if (VoordeurLuxSensor.lux >= 250 and VoordeurLuxSensor.lux < 500) then
domoticz.openURL('http://<ipaddress>:80/camera_control.cgi?param=1&value=80¶m=3&value=1&user=<user>&pwd=<pass>')
domoticz.log('Camera in Inside Dusk Mode', domoticz.LOG_INFO)
end
if (VoordeurLuxSensor.lux < 250) then
domoticz.openURL('http://<ipaddress>:80/camera_control.cgi?param=1&value=96¶m=3&value=1&user=<user>&pwd=<pass>')
domoticz.log('Camera in Inside Night Mode', domoticz.LOG_INFO)
end
end
}
-- Automatic switchoff for my lights
return {
active = true,
on = {
['timer'] = 'every minute',
},
execute = function(domoticz)
local trapgat = domoticz.devices['Dimmer Trapgat']
local gang = domoticz.devices['Dimmer Gang']
if (trapgat.state == 'On' and trapgat.lastUpdate.minutesAgo > 15) then
local traphw = trapgat.hardwareId
if traphw == 4 then
trapgat.switchOff()
end
end
if (gang.state == 'On' and gang.lastUpdate.minutesAgo > 15) then
local ganghw = gang.hardwareId
if ganghw == 4 then
gang.switchOff()
end
end
end
}
Still looking for a way to set my Thermostat (OpenthermGW) setpoint.
I know it can be done with a json command (json.htm?type=command¶m=udevice&idx=69&nvalue=0&svalue=$newpoint) but the .updatesetPoint parameter of dzVents doesn't work and gives me an error (Setting setpoint not supported for this device.) Hope we can get it to work...
Also I wondered how i could check if a (zwave-) device was turned off by the physical switch before sending a command to it (as tried above, with hardwareID)
Once again! Thanks for the great job done!
Atmos
Re: dzVents 1.0 released
Posted: Monday 30 May 2016 21:48
by woody4165
Just done this, but it seems not to work
Code: Select all
if (domoticz.data['errori'].size > 1) then
local item = domoticz.data.errori.get(1)
if item.time.minutesAgo > 20 then
print("resetto dati storici errore ping. sono passati "..item.time.minutesAgo)
domoticz.data['errori'].reset()
end
end
I get the print, so reset should be done, but on the next script run domoticz.data.errori.get(1) gets an higher value, and I'm sure that there was no domoticz.data.errori.add(url_esp)
Re: dzVents 1.0 released
Posted: Monday 30 May 2016 23:10
by dannybloe
woody4165 wrote:Just done this, but it seems not to work
Code: Select all
if (domoticz.data['errori'].size > 1) then
local item = domoticz.data.errori.get(1)
if item.time.minutesAgo > 20 then
print("resetto dati storici errore ping. sono passati "..item.time.minutesAgo)
domoticz.data['errori'].reset()
end
end
I get the print, so reset should be done, but on the next script run domoticz.data.errori.get(1) gets an higher value, and I'm sure that there was no domoticz.data.errori.add(url_esp)
Could you paste the entire script? And could you check the data file for the script. You should be able to read what is stored for errori in there (it's in the storage folder and called __data_<scriptname>.lua. Could be a bug of course.
PS: just for better readability you could use .getLatest() instead of get(1). Just a matter of taste...
Re: dzVents 1.0 released
Posted: Monday 30 May 2016 23:15
by dannybloe
/me takes a bow. Glad you like it.
Atmosphere wrote:
Still looking for a way to set my Thermostat (OpenthermGW) setpoint.
I know it can be done with a json command but the .updatesetPoint parameter of dzVents doesn't work and gives me an error (Setting setpoint not supported for this device.) Hope we can get it to work...
Could you show me the actual json command? It shouldn't be too hard to add support for it.
Atmosphere wrote:
Also I wondered how i could check if a (zwave-) device was turned off by the physical switch before sending a command to it (as tried above, with hardwareID)
Not sure what you mean here. Could you elaborate a bit?
PS: pasting code is better readable using the [ code ] tag instead of the [ quote ] tag
Keeps the indenting
Re: dzVents 1.0 released
Posted: Monday 30 May 2016 23:37
by Atmosphere
dannybloe wrote:
Could you show me the actual json command? It shouldn't be too hard to add support for it.
Sure, here is the command: json.htm?type=command¶m=udevice&idx=69&nvalue=0&svalue=$newpoint
(http://domoticz_ip_address:8080/json.htm?type=command¶m=udevice&idx=69&nvalue=0&svalue=$newpoint)
Where IDX is the well known, and svalue (now $newpoint) the new setpoint (type, nvalue and udevice don't change)
dannybloe wrote:
Atmosphere wrote:
Also I wondered how i could check if a (zwave-) device was turned off by the physical switch before sending a command to it (as tried above, with hardwareID)
Not sure what you mean here. Could you elaborate a bit?
I have a Domitech Lightbulb (zwave). You can switch it off using domoticz or by the (physical) wall switch. If switched by the wall switch domoticz (or better my AEOTEC Zstick V2) doesn't see it anymore (as it is not online). I would like to check if it is online before i test it or send commands to it.
dannybloe wrote:
PS: pasting code is better readable using the [ code ] tag instead of the [ quote ] tag
Keeps the indenting
Thanx for the tip!
Keep up the good work.... I'll be following!
Re: dzVents 1.0 released
Posted: Tuesday 31 May 2016 6:41
by woody4165
dannybloe wrote:
Could you paste the entire script? And could you check the data file for the script. You should be able to read what is stored for errori in there (it's in the storage folder and called __data_<scriptname>.lua. Could be a bug of course.
PS: just for better readability you could use .getLatest() instead of get(1). Just a matter of taste...
This is my entire script, I modified the .get(1) with .getLatest(), but the reset doesn't seem to work for me.
Code: Select all
return {
active = true,
on = {
['timer'] = {
'every minute'
}
},
data = {
errori = { history = true, maxItems = 5 }
},
execute = function(domoticz)
url_esp = domoticz.variables['esp_irrig_ip'].value
--print("esp_irrig_ip = "..url_esp)
ping_success=os.execute('ping -r -q -c3 -W 1 '..url_esp)
-- print("ultimo errore ping "..item.time.minutesAgo)
if ping_success then
-- print("ESP Irrigazione ping success")
domoticz.devices['CheckIpEsp'].switchOn()
if (domoticz.data['errori'].size > 1) then
local item = domoticz.data.errori.getLatest()
if item.time.minutesAgo > 20 then
print("resetto dati storici errore ping. sono passati "..item.time.minutesAgo.." - item "..domoticz.data['errori'].size)
domoticz.data['errori'].reset()
end
end
else
domoticz.data.errori.add(url_esp)
domoticz.data['errori'].forEach(function(item, index)
print("nok", item, item.time.minutesAgo, index)
end)
print("ESP Irrigazione ping fail"..url_esp)
domoticz.devices['CheckIpEsp'].switchOff()
message="ESP Irrigazione non raggiungibile. IP "..url_esp
os.execute('curl --data chat_id=xxxxxxxxx --data-urlencode "text='..message..'" "https://api.telegram.org/xxxxxxxxxx/sendMessage"')
end
end
}
And this is what I found in the log:
Code: Select all
LUA: resetto dati storici errore ping. sono passati 564 - item 5
And every minute the big number become bigger
Really don't understand what I'm doing wrong
Re: dzVents 1.0 released
Posted: Tuesday 31 May 2016 7:55
by dannybloe
woody4165 wrote:dannybloe wrote:
Could you paste the entire script? And could you check the data file for the script. You should be able to read what is stored for errori in there (it's in the storage folder and called __data_<scriptname>.lua. Could be a bug of course.
PS: just for better readability you could use .getLatest() instead of get(1). Just a matter of taste...
This is my entire script, I modified the .get(1) with .getLatest(), but the reset doesn't seem to work for me.
Code: Select all
return {
active = true,
on = {
['timer'] = {
'every minute'
}
},
data = {
errori = { history = true, maxItems = 5 }
},
execute = function(domoticz)
url_esp = domoticz.variables['esp_irrig_ip'].value
--print("esp_irrig_ip = "..url_esp)
ping_success=os.execute('ping -r -q -c3 -W 1 '..url_esp)
-- print("ultimo errore ping "..item.time.minutesAgo)
if ping_success then
-- print("ESP Irrigazione ping success")
domoticz.devices['CheckIpEsp'].switchOn()
if (domoticz.data['errori'].size > 1) then
local item = domoticz.data.errori.getLatest()
if item.time.minutesAgo > 20 then
print("resetto dati storici errore ping. sono passati "..item.time.minutesAgo.." - item "..domoticz.data['errori'].size)
domoticz.data['errori'].reset()
end
end
else
domoticz.data.errori.add(url_esp)
domoticz.data['errori'].forEach(function(item, index)
print("nok", item, item.time.minutesAgo, index)
end)
print("ESP Irrigazione ping fail"..url_esp)
domoticz.devices['CheckIpEsp'].switchOff()
message="ESP Irrigazione non raggiungibile. IP "..url_esp
os.execute('curl --data chat_id=xxxxxxxxx --data-urlencode "text='..message..'" "https://api.telegram.org/xxxxxxxxxx/sendMessage"')
end
end
}
And this is what I found in the log:
Code: Select all
LUA: resetto dati storici errore ping. sono passati 564 - item 5
And every minute the big number become bigger
Really don't understand what I'm doing wrong
Can you also look into the data file for your script? You can find that file in the subfolder called 'storage' and is named like __data_<scriptname>.lua.
That file holds the persistent data for your script and should have a table named errori in there. It should be empty after the reset() is called.
Re: dzVents 1.0 released
Posted: Tuesday 31 May 2016 8:03
by woody4165
here it is
Code: Select all
["data"] = "192.168.1.103";
["time"] = "2016-05-30 16:06:03";
};
[5] = {
["data"] = "192.168.1.103";
["time"] = "2016-05-30 16:04:03";
};
};
}
and every time ping is ok, it should reset it, and i'm not getting ping error
Re: dzVents 1.0 released
Posted: Tuesday 31 May 2016 8:38
by dannybloe
Ah, ok, I'll look into it. Seems like reset() isn't working as expected
Re: dzVents 1.0 released
Posted: Tuesday 31 May 2016 11:53
by woody4165
dannybloe wrote:Ah, ok, I'll look into it. Seems like reset() isn't working as expected
Thanks!!
Re: dzVents 1.0 released
Posted: Tuesday 31 May 2016 12:29
by dhanjel
Looks really nice! Have to try it out tonight.
You can access historical data to? (Have not had time to read the entire documentation yet).
For monitoring when the dishwasher is done, I need to check if the power consumption has dropped to 3.3W and stayed there for at least 3 min.
Doable in an easy way?