Page 1 of 1
Getting the defined maxItems value for historical variables
Posted: Thursday 23 March 2017 16:08
by BakSeeDaa
Considering the following declaration:
Code: Select all
data = {
lightLevel = { history = true, maxItems = 20 }
},
Is there a way for me to find out the value for maxItems inside the script?
Code: Select all
lightLevelData = domoticz.data['lightLevel']
for i = 1, (lightLevelData.size == 0 and XXXXXXXXXXXXXXXXXXXX or 1) do
lightLevelData.add((TEST_MODE_LIGHT_READING == 0
and domoticz.devices[LIGHT_SENSOR].lux or TEST_MODE_LIGHT_READING))
end
What should XXXXXXXXXXXXXXXXXXXX be?
Thanks!
Re: Getting the defined maxItems value for historical variables [Solved]
Posted: Friday 24 March 2017 8:32
by dannybloe
This is really an interesting piece of code

. First of all I am trying to understand what the for loop is actually for. For what I see here you want to either add 20 (maxItems) lux values to the variable if the variable has no historical data or add 1 new item? Interesting... why do you want to do that?
But to answer your question. It's actually much easier than you think. First of all, it is important that you understand variable scoping. See
Scope tutorial. So what you could do is:
Code: Select all
local maxItems = 20 --this var is available in the entire module scope
return {
active = true,
on = {},
data = {
lightLevel = { history = true, maxItems = maxItems }
},
execute = function()
for i = 1, (lightLevelData.size == 0 and maxItems or 1) do
end
end
}
Hope that helps.
Re: Getting the defined maxItems value for historical variables
Posted: Friday 24 March 2017 8:54
by BakSeeDaa
dannybloe wrote:This is really an interesting piece of code

. First of all I am trying to understand what the for loop is actually for. For what I see here you want to either add 20 (maxItems) lux values to the variable if the variable has no historical data or add 1 new item? Interesting... why do you want to do that?
But to answer your question. It's actually much easier than you think. First of all, it is important that you understand variable scoping. See
Scope tutorial. So what you could do is:
Code: Select all
local maxItems = 20 --this var is available in the entire module scope
return {
active = true,
on = {},
data = {
lightLevel = { history = true, maxItems = maxItems }
},
execute = function()
for i = 1, (lightLevelData.size == 0 and maxItems or 1) do
end
end
}
Hope that helps.
Thanks @dannybloe
I actually used a similar solution before. I guess I just wanted to save that single code line declaring local maxItems. Like if there was a property or something that I could use. Something in style with lightLevel.maxItems, it would look cleaner

But Your solution works fine, no question about that.
dannybloe wrote:Interesting... why do you want to do that?
Further down in the script I'd like to work with a subset of datapoints. E.g.
subset( [fromIdx], [toIdx] ) to compare lightlevels over some time to be able to get a trend rather than a lightlevel fluctuation
I'd like to thank You for Your kind help and for the beautiful piece of code that dzVents is. I feel I still want to buy you a crate of beers (or whatever your drink of choice is) ...

Re: Getting the defined maxItems value for historical variables
Posted: Friday 24 March 2017 8:55
by dannybloe
Ok, cool..
Re: Getting the defined maxItems value for historical variables
Posted: Friday 24 March 2017 10:23
by BakSeeDaa
dannybloe wrote:Ok, cool..
dzVents provide some nice statistical functions and data smoothing.
My script stores a fixed number of light readings. Using them, I'd like to determine
the trend over a period of time, that is, if the light levels are rising or if they are declining. If the light level is below a certain point and the trend is declining, I will assume that the "day state" is "Dawn". As opposite, If the light level is above a certain point and the trend is rising I will assume that the "day state" is "Dusk". It would probably be more adequate to calculate a moving average to smooth out short-term fluctuations and highlight longer-term trends. I'm not sure how to do that though.
Just in case You or someone else have ideas how this should be done, I include the embryo of my script below.
Code: Select all
--[[
lightingMood.lua by BakSeeDaa
Version 0.0.1
--]]
local LIGHT_SENSOR = 'South-southwest Light Level'
local LIGHT_LEVEL_DARK = 60 -- At this level and below, outdoor illumination is lit and shades are closed
local LIGHT_LEVEL_BRIGHT = 860 -- No illumination needed above this value
local TEST_MODE_LIGHT_READING = 0 -- Set to a value between 1 and 55000. Set to 0 to disable test mode
-- Shady is between LIGHT_LEVEL_DARK and LIGHT_LEVEL_BRIGHT
local LIGHTLEVEL_READINGS = 20
return {
active = true,
on = {
LIGHT_SENSOR,
['timer'] = 'every minute'
},
data = {
lightLevel = { history = true, maxItems = LIGHTLEVEL_READINGS }
},
execute = function(domoticz, windDevice, triggerInfo)
local LOG_LEVEL = domoticz.LOG_INFO -- Script default log level. You may change this.
if (triggerInfo.type == domoticz.EVENT_TYPE_TIMER) then
-- Timer event occurred
-- Store the current light level value in the persistant data
lightLevelData = domoticz.data['lightLevel']
for i = 1, (lightLevelData.size == 0 and LIGHTLEVEL_READINGS or 1) do
lightLevelData.add((TEST_MODE_LIGHT_READING == 0
and domoticz.devices[LIGHT_SENSOR].lux or TEST_MODE_LIGHT_READING))
end
--domoticz.log('The latest stored light level: '..lightLevelData.getLatest().data, LOG_LEVEL)
local avg1 = lightLevelData.avg(1, lightLevelData.size/2)
local avg2 = lightLevelData.avg(lightLevelData.size/2+1, lightLevelData.size)
domoticz.log('I would like to believe that the light level trend is '..(avg1 >= avg2 and 'declining' or 'rising')..'. avg1: '.. avg1..'. avg2: '.. avg2, LOG_LEVEL)
else
-- Device event occurred
end
end
}
Re: Getting the defined maxItems value for historical variables
Posted: Sunday 02 April 2017 7:29
by gerard76
A moving average is just an average over time. So the average at time T, T+1, T+2, etc. It's used to define stock trends a lot.
So, in your case you could take avg(1, 5) (last 5 readings) and avg(2,6) (5 readings at T-1) and compare them. The problem is in the definition of 'trend'. If you take too short a period (I took 5 for example), you could trigger a local maximum, if you take it too long the script will be too sluggish to be useful.
To solve the slugginess you could look at exponential moving averages where the last readings are counted heavier, but it's still buffered over time. I have some Ruby code here
https://github.com/gerard-leijdekkers/s ... ck_math.rb where I used those. Exponential moving average is calculated on top of the previous exponential moving average so it's a recursive function. It starts of with a regular average and then adds the next measurement with double weight.
Re: Getting the defined maxItems value for historical variables
Posted: Sunday 02 April 2017 9:04
by BakSeeDaa
Thanks @gerard76
I will have a look at it.
Re: Getting the defined maxItems value for historical variables
Posted: Tuesday 04 April 2017 7:59
by dannybloe
gerard76 wrote:A moving average is just an average over time. So the average at time T, T+1, T+2, etc. It's used to define stock trends a lot.
So, in your case you could take avg(1, 5) (last 5 readings) and avg(2,6) (5 readings at T-1) and compare them. The problem is in the definition of 'trend'. If you take too short a period (I took 5 for example), you could trigger a local maximum, if you take it too long the script will be too sluggish to be useful.
To solve the slugginess you could look at exponential moving averages where the last readings are counted heavier, but it's still buffered over time. I have some Ruby code here
https://github.com/gerard-leijdekkers/s ... ck_math.rb where I used those. Exponential moving average is calculated on top of the previous exponential moving average so it's a recursive function. It starts of with a regular average and then adds the next measurement with double weight.
May be nice to add to dzVents statistical functions.