Getting the defined maxItems value for historical variables  [Solved]

Easy to use, 100% Lua-based event scripting framework.

Moderator: leecollings

Post Reply
BakSeeDaa
Posts: 485
Joined: Thursday 17 September 2015 10:13
Target OS: Raspberry Pi / ODroid
Domoticz version:

Getting the defined maxItems value for historical variables

Post 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!
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Getting the defined maxItems value for historical variables  [Solved]

Post 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.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
BakSeeDaa
Posts: 485
Joined: Thursday 17 September 2015 10:13
Target OS: Raspberry Pi / ODroid
Domoticz version:

Re: Getting the defined maxItems value for historical variables

Post 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 :lol: 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) ... :lol: :lol: :lol:
Last edited by BakSeeDaa on Friday 24 March 2017 8:56, edited 1 time in total.
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Getting the defined maxItems value for historical variables

Post by dannybloe »

Ok, cool..
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
BakSeeDaa
Posts: 485
Joined: Thursday 17 September 2015 10:13
Target OS: Raspberry Pi / ODroid
Domoticz version:

Re: Getting the defined maxItems value for historical variables

Post 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
}
gerard76
Posts: 53
Joined: Wednesday 22 March 2017 9:13
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.8153
Contact:

Re: Getting the defined maxItems value for historical variables

Post 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.
BakSeeDaa
Posts: 485
Joined: Thursday 17 September 2015 10:13
Target OS: Raspberry Pi / ODroid
Domoticz version:

Re: Getting the defined maxItems value for historical variables

Post by BakSeeDaa »

Thanks @gerard76

I will have a look at it.
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Getting the defined maxItems value for historical variables

Post 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.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest