Hi folks,
Today I tagged the dev branch of
dzVents which should be the
1.0 beta 1. I think it is feature complete (duh
) enough for a 1.0 release. Of course it is still beta so please test.
I am excited to announce a couple of really cool (if I may say) new features. Taken from the history.txt:
- 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.
So to me the most interesting part is the persistent variables stuff. You can now define variables in your scripts that hold their value between script runs. Simply define them in your script file like this:
Code: Select all
return {
active = true,
on = {
'MySwitch'
},
data = {
counter = {initial=0}
},
execute = function(domoticz, switch)
if (domoticz.data.counter = 5) then
domoticz.notify('The switch was pressed 5 times!')
domoticz.data.counter = 0 -- reset the counter
else
domoticz.data.counter = domoticz.data.counter + 1
end
end
}
In this simple example I defined a persistent counter.
You can even create global variables like this. Simply create a script file called global_data.lua and place next to your other script files. Defining globals is quite similar:
Code: Select all
return {
data = {
peopleAtHome = { initial = false },
heatingProgramActive = { initial = false }
}
}
And then accessing them in your script goes like this (don't mind the usefulness of this script though
):
Code: Select all
return {
active = true,
on = {
'WindowSensor'
},
execute = function(domoticz, windowSensor)
if (domoticz.globalData.heatingProgramActive and windowSensor.state == 'Open') then
domoticz.notify("Hey don't open the window when the heating is on!")
end
end
}
But what is even more interesting are the persistent variables defined with the type
history=true flag!
These variables have a time-line based internal history of previous values. You can put whatever you like in there and it acts as a FIFO queue (first in first out). So the historical set is limited in size (for performance reasons of course, fully configurable by you, see the specs). But it allows you to do really cool things like inspecting how fast a temperature rose or what the previous maximum humidity was in the past and
a lot lot more:
Code: Select all
return {
active = true,
on = {
'MyTempSensor' -- the trigger
},
data = {
temperatures = { history = true, maxHours = 12 } -- only log values younger than 24 hours
},
execute = function(domoticz, sensor)
-- add new data
domoticz.data.temperatures.setNew(sensor.temperature)
-- average
local average = domoticz.data.temperatures.avg()
-- maximum value in the past hour:
local max = domoticz.data.temperatures.maxSince('01:00:00')
end
}
Here is a list functions you can call on these variables:
- avg( [fromIdx], [toIdx], [default] )
- avgSince( timeAgo, default )
- delta( fromIdx, toIdx, [smoothRange], [default] )
- deltaSince( timeAgo, [smoothRange], [default] )
- get( [idx] )
- getAtTime( timeAgo )
- filter(function)
- find(function)
- forEach(function)
- getLatest( )
- getOldest( )
- localMin( [smoothRange], default )
- localMax([smoothRange], default)
- max( [fromIdx], [toIdx] )
- maxSince( timeAgo )
- min( [fromIdx], [toIdx] )
- minSince( timeAgo )
- setNew(data)
- size
- subset( [fromIdx], [toIdx] )
- subsetSince( [timeAgo] )
- reduce(function, initial)
- reset( )
- smoothItem(itemIdx, [smoothRange])
- sum( [fromIdx], [toIdx] )
- sumSince( timeAgo )
Yes, you are correct: it can even do
data-smoothing which may be useful for calculating deltas or comparing data.
- smoothing.png (34.39 KiB) Viewed 4341 times
(The red line is the raw data with spikes, the other lines with smoothRange=1 and 2).
And of course you don't have to put just numbers is such a variable. It can be anything but then of course some of these functions are irrelevant.
So... please take some time to read the doc and hopefully there's something in there that makes scripting even easier that it was before. At least it may reduce the amount of coding that you have to do to.
Oh, small note. These historical variables are in no way suitable for full data logging of your entire domoticz environment. Only create these variables when you need them for your scripts and keep them as small as possible. I suspect that the
reset() method is some interesting method that can be called in many situations when historical values are not needed anymore (maybe as soon as the heater is turned on). If you store a year worth of data from a sensor that logs every 10 seconds then I can assure you that your scripts will not run
. The data is stored in files (one for each script) in a subfolder inside your script folder.
See how it works.
Oh and I still have to write some examples that use these features. And please let me know if you have some cool (not too complex) implementations or applications using these variables. I have made the historical stuff quite generic hoping it will trigger the creativity of you as script writer but of course I can only think of my own situations. So I'm curious what use it may be for you (or not perhaps).
And if you think something is still missing let me know as well or make a pull request yourself (the code is quite readable I believe).
Cheers,
Danny