On = {devices ={'XX'}, timer = {'at ....'},} (solved)

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

Moderator: leecollings

Post Reply
Tukker
Posts: 674
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

On = {devices ={'XX'}, timer = {'at ....'},} (solved)

Post by Tukker »

I have this script to find out the mean temperature (gemiddelde temperatuur)

Code: Select all

return {
    active = true,
    on = 
	{
	    timer = {'at 07:00-23:00'},
	    devices = {'KNMI Wind'},
	},

    logging = {
        level = domoticz.LOG_DEBUG,
        marker = 'buitentemperatuur gemiddeld',
    },

	data = {
		temperatures = { history = true, maxHours = 24 },
	},
	
    execute = function(domoticz, sensor)
		-- add new data
		domoticz.data.temperatures.add(sensor.temperature)

		-- average
		local average = domoticz.data.temperatures.avg()
        domoticz.log('average temperature ' .. average, domoticz.LOG_INFO)
        domoticz.devices('Gem buitentemp').updateTemperature(average)
        -- domoticz.log('average temperature ' .. average, domoticz.LOG_INFO)
		
		-- maximum value in the past 24 hours:
		local max = domoticz.data.temperatures.maxSince('24:00:00')
		domoticz.devices('Max buitentemp').updateTemperature(max)
		-- domoticz.log('maximum temperature ' .. max, domoticz.LOG_INFO)
	    
	    -- minimum value in the past 24 hours:
		local min = domoticz.data.temperatures.minSince('24:00:00')
		domoticz.devices('Min buitentemp').updateTemperature(min)
		-- domoticz.log('minimum temperature ' .. max, domoticz.LOG_INFO)
    end
} 
So far, so good and it works like a charm.
I'd like the script to execute between 7 in the morning and 23 in the evening.
So I added this:

Code: Select all

timer = {'at 07:00-23:00'},
The beginning of the code now is like:

Code: Select all

return {
    active = true,
    on = 
	{
	    timer = {'at 07:00-23:00'},
	    devices = {'KNMI Wind'},
	},
The addition of the timer = statement is punished with the following error message:

Code: Select all

2023-12-22 22:37:00.203 Status: dzVents: Info: buitentemperatuur gemiddeld: ------ Start internal script: Buitentemp gemiddeld:, trigger: "at 07:00-23:00"
2023-12-22 22:37:00.209 Status: dzVents: Info: buitentemperatuur gemiddeld: ------ Finished Buitentemp gemiddeld
2023-12-22 22:37:00.209 Error: dzVents: Error: (3.1.8) buitentemperatuur gemiddeld: Item data is not a number type. Type is nil
2023-12-22 22:37:00.209 Error: dzVents: Error: (3.1.8) buitentemperatuur gemiddeld: An error occurred when calling event handler Buitentemp gemiddeld
2023-12-22 22:37:00.209 Error: dzVents: Error: (3.1.8) buitentemperatuur gemiddeld: /home/hein/domoticz/dzVents/runtime/HistoricalStorage.lua:282: attempt to perform arithmetic on a nil value (local 'acc')
I do understand that it executes every minute due to the 'at 07:00-23:00' statement.
That is the reason the function gets no data from 'KNMI Wind'
Last edited by Tukker on Saturday 23 December 2023 18:59, edited 5 times in total.
Bugs bug me.
willemd
Posts: 793
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.3
Location: The Netherlands
Contact:

Re: What is happening here?

Post by willemd »

I think you have to define a custom event to achieve what you want.
https://www.domoticz.com/wiki/DzVents:_ ... _scripting

But you are anyway not calculating an average temperature, because as far as I can see you are not taking into account how long each temperature lasted. Even though each value in history has a timestamp, the documentation is not mentioning that it is taking the timestamp into account when calculating an average. Probably it is just the simple average of all values without looking at timestamps. You could of course check the timestamp and do the proper calculation yourself.

Edit: if your devcie is updated by regular polling (so not only when it changes) then your average calculation is correct. But then you also don't need the device trigger or custom event in your script. Just run your script at the same interval between 07:00 and 23:00.

What I am doing is the following:
1) at each update of the buienradar temp (even if it does not change), I add the temperature to a total (on a device) and I also increase a counter device (=number of temperatures)
2) at the end of the day I divide the total by the counter (you could also do this during the day).
This is also much less resource intensive than logging 24 hours of changes.
Last edited by willemd on Saturday 23 December 2023 9:22, edited 3 times in total.
roblom
Posts: 408
Joined: Wednesday 26 February 2014 15:28
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: the Netherlands
Contact:

Re: What is happening here?

Post by roblom »

I'm not sure a trigger on time AND a timerange is possible so I would say put the timerange in an if statement within the script.
Tukker
Posts: 674
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: What is happening here?

Post by Tukker »

willemd wrote: Friday 22 December 2023 23:11 Edit: if your devcie is updated by regular polling (so not only when it changes) then your average calculation is correct. But then you also don't need the device trigger or custom event in your script. Just run your script at the same interval between 07:00 and 23:00.
Thanks for your input @willemd
I found a simple way to execute the code at the predefined time interval.
I looked in the Wiki and there it was not documented in a way I can handle it.

So here is the os.date('%H:%M') trick.

Code: Select all

return {
    active = true,
    on = 
	{
	    devices = {'KNMI Wind'},
	},

    logging = {
        level = domoticz.LOG_ERROR,  -- change to LOG_DEBUG to display results in the Log
        marker = 'buitentemperatuur gemiddeld',
    },

	data = {
		temperatures = { history = true, maxHours = 24 },
	},
	
    execute = function(domoticz, sensor)
	    -- add new data (collect information about temperature)
    	domoticz.data.temperatures.add(sensor.temperature)
    	
    	local current_time = os.date('%H:%M')
        if (current_time >= '07:00' and current_time <= '23:00') then
            domoticz.log('De huidige tijd is', domoticz.LOG_DEBUG)
	    domoticz.log(current_time, domoticz.LOG_DEBUG)
	        
	    -- average between 07:00 and 23:00
	    local average = domoticz.data.temperatures.avg()
            domoticz.devices('Gem buitentemp').updateTemperature(average)
            domoticz.log('average temperature ' .. average, domoticz.LOG_DEBUG)
	else
            domoticz.log('Just check', domoticz.LOG_DEBUG)
	end		
	-- maximum value in the past 24 hours:
    	local max = domoticz.data.temperatures.maxSince('00:00:11')
	domoticz.devices('Max outside temp').updateTemperature(max)
	domoticz.log('maximum temperature ' .. max, domoticz.LOG_DEBUG)
	    
    	 -- minimum value in the past 24 hours:
	local min = domoticz.data.temperatures.minSince('00:00:11')
	domoticz.devices('Minimum outside temp').updateTemperature(min)
    	domoticz.log('minimum temperature ' .. max, domoticz.LOG_DEBUG)
    end
} 

Avergae temperature is updated between 7 and 23 hours.

The reason for the time interval is for calculating weigthed degree days.
Our heating is working from 7 to 23 hour, we don't have floor heating.
By calculating the average temperature during the hours that the heating is on it will reflect the gas usage in weighted degree days.
Bugs bug me.
willemd
Posts: 793
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.3
Location: The Netherlands
Contact:

Re: On device AND on timer (solved)

Post by willemd »

You have the domoticz.data.temperatures.add(sensor.temperature) statement outside of the if condition, so it will still add temperatures during the full day. Even if you calculate the average only between 07:00 and 23:00 it will then still use all values. If you want to use only the values between 07:00 and 23:00 then you should bring the add stament within the if condition.

Normally there are a number of steps in calculating degree days:
1) first determine the average temperature
2) then determine the difference versus your threshold temperature (default is 18 degrees).
3) then apply the correction factor depending on the month
But of course you can create your own calculation if that is a more accurate representation of the temperature influence on your heating behaviour.

I am planning to do some regression analysis using a number of factors to see which factors combined are a good representation of my gas usage and then use that model for the future (temperature, sunshine intensity and angle, presence in the house for example)
Tukker
Posts: 674
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: On device AND on timer (solved)

Post by Tukker »

willemd wrote: Saturday 23 December 2023 16:22 You have the domoticz.data.temperatures.add(sensor.temperature) statement outside of the if condition, so it will still add temperatures during the full day. Even if you calculate the average only between 07:00 and 23:00 it will then still use all values. If you want to use only the values between 07:00 and 23:00 then you should bring the add stament within the if condition.
That's on purpose.
This part:

Code: Select all

-- add new data (collect information about temperature)
    	domoticz.data.temperatures.add(sensor.temperature)
is data collection.
What comes next is data processing. (I suppose)
I want the average temperature in a distinct time frame for gas consumption calculations and weighed degree days.
Max and min temp during the day is just the curiosity about max an min of the whole day.
That's the logic of the if .... else construction used.
Bugs bug me.
willemd
Posts: 793
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.3
Location: The Netherlands
Contact:

Re: On device AND on timer (solved)

Post by willemd »

HvdW wrote: Saturday 23 December 2023 19:34 I want the average temperature in a distinct time frame for gas consumption calculations and weighed degree days.
Do you want it displayed in that distinct time frame or do you want to have it calculated over that distinct time frame?

The comment in the code seems to suggest that you are expecting the average calculated over the period 07:00 to 23:00, but that is not what you are doing.

My point was that currently you are calculating the average over the period 00:00 to the current-time-of-day, not over 07:00 to the current-time-of-day.
Tukker
Posts: 674
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: On = {devices ={'XX'}, timer = {'at ....'},} (solved)

Post by Tukker »

Well.
Maybe we misunderstand.
At 21:10 I have set the time from 07:00 to 21:00
On device.jpg
On device.jpg (83.21 KiB) Viewed 1614 times
As you can see at 21:19 Weather and Max and Min temperature have updated and Gemiddelde temperatuur (Average temperature) did not.
The log file tells me that the if has been skipped and it got trapped in the else.
The log sais: 'Just check'
Max and Min have been calculated, Average has not been calculated.

EDIT:
Of course the easy way is to do it on timer (every 10 minutes or so) instead of on device. It just the challenge of doing it this way.
Last edited by Tukker on Saturday 23 December 2023 21:54, edited 1 time in total.
Bugs bug me.
willemd
Posts: 793
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.3
Location: The Netherlands
Contact:

Re: On = {devices ={'XX'}, timer = {'at ....'},} (solved)

Post by willemd »

Correct, makes sense, but if you look at the average that is calculated and displayed at 07:05 you will see it is not the average over the period 07:00 to 07:05 but the average over 00:00 to 07:05.
Tukker
Posts: 674
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: On = {devices ={'XX'}, timer = {'at ....'},} (solved)

Post by Tukker »

willemd wrote: Saturday 23 December 2023 21:43 Correct, makes sense, but if you look at the average that is calculated and displayed at 07:05 you will see it is not the average over the period 07:00 to 07:05 but the average over 00:00 to 07:05.
Finally I get your point.
I'll use this one with other timing of course to check.

Code: Select all

-- get average for the past 30 minutes:
local avg = myVar.avgSince('00:30:00')
Bugs bug me.
Post Reply