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
jkimmel wrote:I would like to convert the script of

http://www.domoticz.com/forum/viewtopic ... tor#p72942

for dzVents.

Please help if possible with comments.
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
jkimmel wrote:I would like to convert the script of

http://www.domoticz.com/forum/viewtopic ... tor#p72942

for dzVents.

Please help if possible with comments.
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!!!! :D :lol: :D :lol: 8-) 8-)

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&param=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&param=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&param=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&param=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
Atmosphere wrote:APPLAUSE!!!! :D :lol: :D :lol: 8-) 8-)

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!
/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&param=udevice&idx=69&nvalue=0&svalue=$newpoint
(http://domoticz_ip_address:8080/json.htm?type=command&param=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! :D


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?