Average Temp from multiple sensors

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

Moderator: leecollings

Wob76
Posts: 110
Joined: Wednesday 19 April 2017 6:31
Target OS: Linux
Domoticz version:
Contact:

Average Temp from multiple sensors

Post by Wob76 »

Hi All,

After some advice, I created a script yesterday to pull the data from all my sensors, I have 5 in various rooms, and populate a dummy sensor called "Inside Temp". So I have a single temp of to show the current average inside temps. I have averaged this out over the last 30mins.

I am using Xiaomi Temp\Humidity sensors, and I am averaging both values, I created a data set with history of Temp and Humidity, and whenever I see an update to one of the temp devices it is added to the data set. I use a single device to pull "Humidity Status" from, as I can't average a string.

The issue I am seeing is that sometimes I see the temp devices update twice within microseconds of each other.

Code: Select all

2017-08-24 10:55:11.232 (Home Gateway) Temp (Master Bed Temp)
2017-08-24 10:55:11.239 (Home Gateway) Humidity (Master Bed Humidity)
2017-08-24 10:55:15.900 (Home Gateway) Temp (Living Room Temp)
2017-08-24 10:55:15.902 (Home Gateway) Humidity (Living Room Humidity)
2017-08-24 10:55:15.904 (Home Gateway) Temp (Living Room Temp)
2017-08-24 10:55:15.905 (Home Gateway) Humidity (Living Room Humidity)
This isn't a HUGE issue, but it does skew the results a little when that zone is particularly warm or cool.
chart.jpeg
chart.jpeg (85.07 KiB) Viewed 5189 times
So, is there a way I can avoid the double triggering of my event when a device triggers multiple times like above? Or does anyone have a better solution to calculating the averages? or maybe a way to smooth out the result?

My script.

Code: Select all

local OUTPUT_DEVICE = "Inside Temp" -- The Device to write the averages to
local STATUS_DEVICE = "Living Room Temp" -- Device to pull humidity status from (as we can't average a string)

local LOGGING = false

return {
    active = true,
    on = {
        devices = {
            "Living Room Temp",
            "Master Bed Temp",
            "Kids Room Temp",
            "Guest Room Temp",
            "Study Temp",
        },
    },
    data = {
        temperatures = { history = true, maxHours = 12 },
        humiditys = { history = true, maxHours = 12 }
    },
    logging = {
    level = domoticz.LOG_ERROR,
    marker = "Tempz"
    },

    execute = function(domoticz, sensor)
        -- define output devices
        local output = domoticz.devices(OUTPUT_DEVICE)
        
        -- add new data
        domoticz.data.temperatures.add(sensor.temperature)
        domoticz.data.humiditys.add(sensor.humidity)
    
        -- half hour average
        local temp_average = domoticz.helpers.round(domoticz.data.temperatures.avgSince('00:30:00'), 1)
        local humid_average = domoticz.data.humiditys.avgSince('00:30:00')
        local humid_status = domoticz.devices(STATUS_DEVICE).humidityStatus
        
        -- Convert status to dzVentz format
        if (humid_status == "Comfortable") then
            humid_out = "1"
        elseif (humid_status == "Dry") then
            humid_out = "2"
        elseif (humid_status == "Wet") then
            humid_out = "3"
        else
            humid_out = "0"
        end
        
        local humid_status = domoticz.devices(STATUS_DEVICE).humidityStatus
        
        if LOGGING then domoticz.log("Half Hourly Averages - Temp: " .. temp_average .. ". Himidity: " .. humid_average .. ". Status: " .. humid_status .. " " .. humid_out) end
        
        output.updateTempHum(temp_average, humid_average, humid_out)
    end
}
Thanks,
Wob
mivo
Posts: 80
Joined: Friday 21 April 2017 8:58
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Czechia
Contact:

Re: Average Temp from multiple sensors

Post by mivo »

Hi,

do you try to trigger script by time, not devices ? Every 5 minutes for example. It can avoid unnecessary often calculation and updates
My toys:
Raspberry Pi 3 + UPS PIco HV3.0 A Stack
Minibian (Raspbian Jessie) + Domoticz beta
RFLink 433 Gateway, 1wire DS18B20 temp sensors (GPIO)
RaZberry module + 2x Comet Z-Wave + Z-wave socket
---
Plugins: WeMo Switch, UPS PIco HV3.0A on GitHub
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Average Temp from multiple sensors

Post by dannybloe »

And why would you log the temperatures for 12 hours? That gives you a lot of data that has to be loaded every time the script is called. Do you really need to average over 30 minutes? I guess you could significantly optimize here performance wise.
The double triggers are hard to come by. In the upcoming dzVents release you get microsecond resolution on the time-stamps in your historical data points so you could use that to store the last update and compare its time-stamp with your current temperature. On the other hand, if you expect samples to be at least minutes apart then you could just check if the lastUpdate is at least a couple of second older than the current time.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
User avatar
DewGew
Posts: 579
Joined: Thursday 21 April 2016 12:01
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.10618
Location: Sweden
Contact:

Re: Average Temp from multiple sensors

Post by DewGew »

I have a simple script that checks temps and update a virtual sensor every hour. My only issue is that in my logs the avarage temp shows in alot of decimals (eg. 22.123456758).

Code: Select all

--[[
-- Avarage Temp --
 
dzVenst script that calculate avarage temperature at a specific time and updates the virtul sensor "Avarage temp inside"

Titel: avarageTemp.lua
Framework: dzVents 2.2.X
Datum: 2017-05-23

 ]]

return {
        active = true,
    on = {
		timer = {
			'every hour'
		}
    },
    execute = function(domoticz)
	
		local avarageTemp = domoticz.devices('Medeltemperatur Inne')
		local tempSensorLivingroom = domoticz.devices('Inne Temp')
		local tempSensorHall = domoticz.devices('VP Inne Temperatur')
		-- local tempSensorKitchen = domoticz.devices('Temperatur Kök')
		
		local temperature = 0
        local avarage = 0
        local numbOfReadings  = 0

        if tempSensorLivingroom.lastUpdate.minutesAgo < 30) then
            temperature = temperature + tempSensorLivingroom.temperature
            numbOfReadings  = numbOfReadings  + 1
        end

        if tempSensorHall.lastUpdate.minutesAgo < 30) then
            temperature = temperature + tempSensorHall.temperature
            numbOfReadings  = numbOfReadings  + 1
        end
		--[[
		if tempSensorKitchen.lastUpdate.minutesAgo < 30) then
            temperature = temperature + tempSensorKitchen.temperature
            numbOfReadings  = numbOfReadings  + 1
        end
		]]

        avarage= 10*(temperature/numbOfReadings )/10
        domoticz.log('Medeltemperatur Inne är ' .. avarage, domoticz.LOG_INFO)
		domoticz.log('Antal mätvärden = ' .. numbOfReadings , domoticz.LOG_INFO)

        avarageTemp.updateTemperature(math.floor(10*(temperature/numbOfReadings ))/10)
    end
}
Raspberry Pi 3 | domoticz | Aeon Labs Z-Stick GEN5 | RFlink gateway
NanoPi NEO-air | REGO6XX interface | Machinon theme | Homebridge | Domoticz Google Assistant | ideAlarm
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Average Temp from multiple sensors

Post by dannybloe »

Yeah that's what I'm fighting with myself every time I use floats in Lua. Guess I'll have to read the Lua manual someday and learn about floating point precision. Maybe this link helps.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
Wob76
Posts: 110
Joined: Wednesday 19 April 2017 6:31
Target OS: Linux
Domoticz version:
Contact:

Re: Average Temp from multiple sensors

Post by Wob76 »

Hi Guys,

Thanks for the responses.

I did consider this at first, but my sensors update fairly randomly, and for the most part, less often than 5 mins, so the load is actually less calling it when a device updates. That and if I take all devices every 5 mins I am not really getting data from that "point in time" some sensors data would be older than others. If I go with that approach I would prob not bother keeping history at all, clear the history, poll all devices then average the result.

But as I mention this would be calling the script more often not less, see here, my current time is 15:58 and you can see here one device last updated at 15:10.. They are wireless low power devices so fairly low polling times.
Capture2.JPG
Capture2.JPG (90.33 KiB) Viewed 5166 times
Honestly I am very new to dzVents\Lau and I used an example I found in the wiki to build from, It was keeping the data that long so I thought it couldn't be to hard on the CPU, I average of 30 mins to try and capture data from as many sensors as I can, due to the slow polling above, but still have the temps relative enough. Open to suggestions to reduce both the history and the average time, but again I want to try and capture date from each sensor, I do an average function in another script that clears at the start and then just logs each sensor at its current state and runs an average, maybe I am just best to stick with that idea and run every 5 min?

I ran into the rounding issues earlier when sending out notification with temp, i fixed it by creating a rounding helper function.

Code: Select all

round = function(num, numDecimalPlaces)
            return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num))
        end
You can see it in use in my above script. It is rounding to 1 decimal in that example. Being new I pulled that from a Lua page somewhere.

Code: Select all

local temp_average = domoticz.helpers.round(domoticz.data.temperatures.avgSince('00:30:00'), 1)
Thanks,
Beau
Wob76
Posts: 110
Joined: Wednesday 19 April 2017 6:31
Target OS: Linux
Domoticz version:
Contact:

Re: Average Temp from multiple sensors

Post by Wob76 »

Just had a look, my script has been running for around 24 hours, and the data file is still quite small.

Code: Select all

-rwxrw-r-- 1 nobody users 15K Aug 24 16:15 __data_Temps.lua*
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Average Temp from multiple sensors

Post by dannybloe »

Well, this is certainly an interesting situation that certainly is solvable and I believe in an elegant way. This is really a nice challenge and a good way to learn about dzVents as well. I believe there are many solutions to this. Maybe it is just trying different things and see how they go. And if you don't see a performance hit then there's no problem (just check the logs and the timings).

So, having said that... one thing that comes to my mind is perhaps create a history stream for each sensor and limit it to let's say 10 minutes or less. At least the longest interval between sensor updates. Then fill the stream for each sensor every time a new reader comes in. Then maybe you can have a timer trigger let's say every 10 minutes or less that calculates the average for each of those streams and use that to calculate the overall average.

But again.. there are certainly more ways to this.. Nice problem! (And good to see people use the history-data support!)
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
Wob76
Posts: 110
Joined: Wednesday 19 April 2017 6:31
Target OS: Linux
Domoticz version:
Contact:

Re: Average Temp from multiple sensors

Post by Wob76 »

DewGew wrote: Thursday 24 August 2017 8:02 I have a simple script that checks temps and update a virtual sensor every hour. My only issue is that in my logs the avarage temp shows in alot of decimals (eg. 22.123456758).
Your solution looks simple enough, I like how you are limiting the sensors used to those updated within the last 30 mins, I will give it a try and see if it gives me a more accurate result.

Thanks dannybloe, I actually found the history-data easier to use than to try and keep track of how many datapoints I have used. DewGew's solution is simple enough, but I would prob just use history, clear it at the start of the script and then let it work out the average, this is how I did it in another script.

Code: Select all

            -- get temperature sensors average
            averages.reset()
            averages.add(zone0_temp)
            if (zone1_enable == "On") then averages.add(zone1_temp) end
            if (zone2_enable == "On") then averages.add(zone2_temp) end
            if (zone3_enable == "On") then averages.add(zone3_temp) end
            local temp_average = domoticz.helpers.round(averages.avg(), 2)
Just wondering, how often is too often for running scripts? I am trying to avoid running too many scripts, too often, I do have one running every minute for presence detection purposes, and another lua script for timing switches, most other are limited to actions. Load isn't an issue at the moment, but just wondering if I am worrying about nothing.

Thanks,
Wob
User avatar
Egregius
Posts: 2582
Joined: Thursday 09 April 2015 12:19
Target OS: Linux
Domoticz version: v2024.7
Location: Beitem, BE
Contact:

Re: Average Temp from multiple sensors

Post by Egregius »

Just wondering, what is your purpose of this average temperature?
Only similar I do is calculate the average home temperature each minute to create something of a pre fire alarm. When temperature in one room is more than 5° higher than another room I receive a high priority message.
User avatar
DewGew
Posts: 579
Joined: Thursday 21 April 2016 12:01
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.10618
Location: Sweden
Contact:

Re: Average Temp from multiple sensors

Post by DewGew »

Wob76 wrote: Thursday 24 August 2017 8:15
I ran into the rounding issues earlier when sending out notification with temp, i fixed it by creating a rounding helper function.

Code: Select all

round = function(num, numDecimalPlaces)
            return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num))
        end
You can see it in use in my above script. It is rounding to 1 decimal in that example. Being new I pulled that from a Lua page somewhere.

Code: Select all

local temp_average = domoticz.helpers.round(domoticz.data.temperatures.avgSince('00:30:00'), 1)
Thanks,
Beau
Great #Wob76. Just what I need. I will try this in my scripts.

// Pierre
Raspberry Pi 3 | domoticz | Aeon Labs Z-Stick GEN5 | RFlink gateway
NanoPi NEO-air | REGO6XX interface | Machinon theme | Homebridge | Domoticz Google Assistant | ideAlarm
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Average Temp from multiple sensors

Post by dannybloe »

I can't get that one to work. I tried this and that works nice (also with negatives):

Code: Select all

function round(x, n)
	n = math.pow(10, n or 0)
	x = x * n
	if x >= 0 then 
		x = math.floor(x + 0.5) 
	else 
		x = math.ceil(x - 0.5) 
	end
	return x / n
end
I'll add that to dzVents.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
User avatar
DewGew
Posts: 579
Joined: Thursday 21 April 2016 12:01
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.10618
Location: Sweden
Contact:

Re: Average Temp from multiple sensors

Post by DewGew »

dannybloe wrote: Thursday 24 August 2017 9:32 I can't get that one to work. I tried this and that works nice (also with negatives):
I got Wob76's code to work
Raspberry Pi 3 | domoticz | Aeon Labs Z-Stick GEN5 | RFlink gateway
NanoPi NEO-air | REGO6XX interface | Machinon theme | Homebridge | Domoticz Google Assistant | ideAlarm
Wob76
Posts: 110
Joined: Wednesday 19 April 2017 6:31
Target OS: Linux
Domoticz version:
Contact:

Re: Average Temp from multiple sensors

Post by Wob76 »

Odd dannybloe, def works here.
Wob76
Posts: 110
Joined: Wednesday 19 April 2017 6:31
Target OS: Linux
Domoticz version:
Contact:

Re: Average Temp from multiple sensors

Post by Wob76 »

Egregius wrote:Just wondering, what is your purpose of this average temperature?
Only similar I do is calculate the average home temperature each minute to create something of a pre fire alarm. When temperature in one room is more than 5° higher than another room I receive a high priority message.
At the moment it is only being used in the dashboard to see a guide to indoor temps. I do some internal averaging in another script for my Air Con, to average the currently active zones for temp triggers.

Future plan is to use internal and external averages to help control AC and maybe send notifications if it's worth just opening some doors/windows and turn the AC off.

I've only just started with Domoticz and automation, most of it is climate control as that's all I have control of at the moment. But it's addictive and growing fast :)

Sent from my SM-G935F using Tapatalk

Wob76
Posts: 110
Joined: Wednesday 19 April 2017 6:31
Target OS: Linux
Domoticz version:
Contact:

Re: Average Temp from multiple sensors

Post by Wob76 »

Thanks for the help so far, I made up a script based loosely on DewGew's Code, it only uses data at the instant it is run, and excludes and sensors that have stale data (older than 30 mins), this is then used to create an average that is sent to my dummy sensor. I found that pooling every hour was a little unreliable, and even at 30min I found I would still like more data points.

So I ended up having it activated by the input sensors again, as they still poll less than running it every 5-10 minutes, and I am grabbing a new data point when ever a input is updated.

I did have 1 instance where my sensor zeroed, so I added a IF to filter out when Temp and Humidity = 0.

Considering this approach should eliminate the double data points I was seeing from some points, the end result is VERY similar to my original, maybe even a little more spiky, I'll run both for a bit long to see how they compare. I have reduced my original script it only keep 2 hours data instead of 12, file is 4.5k now.

Yellow = New Script, Pink(ish) = Original
chart (1).jpeg
chart (1).jpeg (59.08 KiB) Viewed 5083 times
Wob76
Posts: 110
Joined: Wednesday 19 April 2017 6:31
Target OS: Linux
Domoticz version:
Contact:

Re: Average Temp from multiple sensors

Post by Wob76 »

Ran both sensors for a few days, results are very close, both have some unexpected peaks, but I have decided to stick with a modified version of DewGew's script.

Rather than using multiple if statements, is there a way to use a foreach to do each sensor in the variable?

And when I read the status from a temp sensor I am given it is strong form (eg "Comfortable") but the .updateTempHum will only accept a numerical value (0 to 3) so at the moment I need that if block to convert it, is it possible to read or update the values in the same format?

Thanks,
Wob

Code: Select all

-- Avarage Temp --
local OUTPUT_SENSOR = "Inside Temp" -- The Device to write the averages to

-- Input Sensors
local INPUT_SENSOR1 = "Living Room Temp"
local INPUT_SENSOR2 = "Master Bed Temp"
local INPUT_SENSOR3 = "Kids Room Temp"
local INPUT_SENSOR4 = "Guest Room Temp"
local INPUT_SENSOR5 = "Study Temp"

local LOGGING = false

return {
        active = true,
    on = {
--[[		timer = {
		'every 30 minutes'
		}, ]]
        devices = {
            INPUT_SENSOR1,
            INPUT_SENSOR2,
            INPUT_SENSOR3,
            INPUT_SENSOR4,
            INPUT_SENSOR5,
        },
    },
    data = {
        temps = { history = true, maxItems = 10 },
        humids = { history = true, maxItems = 10 },
    },
    logging = {
    level = domoticz.LOG_ERROR,
    marker = "Tempz"
    },

    execute = function(domoticz)
        -- define output sensor
        local output = domoticz.devices(OUTPUT_SENSOR)
        
        -- define output sensor
        local sensor1 = domoticz.devices(INPUT_SENSOR1)
        local sensor2 = domoticz.devices(INPUT_SENSOR2)
        local sensor3 = domoticz.devices(INPUT_SENSOR3)
        local sensor4 = domoticz.devices(INPUT_SENSOR4)
        local sensor5 = domoticz.devices(INPUT_SENSOR5)
        
        local temperatures = domoticz.data.temps
        local humiditys = domoticz.data.humids
        
        temperatures.reset()
        humiditys.reset()
        
        if (sensor1.lastUpdate.minutesAgo < 30) then
            temperatures.add(sensor1.temperature)
            humiditys.add(sensor1.humidity)
        end
        
        if (sensor2.lastUpdate.minutesAgo < 30) then
            temperatures.add(sensor2.temperature)
            humiditys.add(sensor2.humidity)
        end
        
        if (sensor3.lastUpdate.minutesAgo < 30) then
            temperatures.add(sensor3.temperature)
            humiditys.add(sensor3.humidity)
        end
        
        if (sensor4.lastUpdate.minutesAgo < 30) then
            temperatures.add(sensor4.temperature)
            humiditys.add(sensor4.humidity)
        end
        
        if (sensor5.lastUpdate.minutesAgo < 30) then
            temperatures.add(sensor5.temperature)
            humiditys.add(sensor5.humidity)
        end
        
        local temp_average = domoticz.helpers.round(temperatures.avg(), 1)
        local humid_average = humiditys.avg()
        
        -- Convert status to dzVentz format
        if (sensor1.humidityStatus == "Comfortable") then
            humid_out = "1"
        elseif (sensor1.humidityStatus == "Dry") then
            humid_out = "2"
        elseif (sensor1.humidityStatus == "Wet") then
            humid_out = "3"
        else
            humid_out = "0"
        end
        
        if LOGGING then domoticz.log("Temps are " .. sensor1.temperature .. " " .. sensor2.temperature .. " " .. sensor3.temperature .. " " .. sensor4.temperature .. " " .. sensor5.temperature) end
        if LOGGING then domoticz.log("Averages are " .. temp_average .. " " .. humid_average .. "% " .. humid_out) end
        
        if ( temp_average ~= 0 and humid_average ~= 0 ) then
            output.updateTempHum(temp_average, humid_average, humid_out)
        end
    end
}
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Average Temp from multiple sensors

Post by dannybloe »

Wob76 wrote: Tuesday 29 August 2017 4:13 Ran both sensors for a few days, results are very close, both have some unexpected peaks, but I have decided to stick with a modified version of DewGew's script.

Rather than using multiple if statements, is there a way to use a foreach to do each sensor in the variable?
s
Well yeah, you could do a domoticz.devices().filter(..).forEach() where in the filter you filter out only those who are in your list of sensors. Then in the forEach you do the processing of what's left of the filter.
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
Wob76
Posts: 110
Joined: Wednesday 19 April 2017 6:31
Target OS: Linux
Domoticz version:
Contact:

Re: Average Temp from multiple sensors

Post by Wob76 »

Hi Dannybloe,

Thanks again for the response, I don't currently have a easy way to filter, no common name, I think I'll just leave as is.

Can you answer the question regarding a command humidity status for the output and update?

Wob
dannybloe
Posts: 1355
Joined: Friday 29 August 2014 11:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Ermelo
Contact:

Re: Average Temp from multiple sensors

Post by dannybloe »

Wob76 wrote: Tuesday 29 August 2017 8:33 Hi Dannybloe,
Thanks again for the response, I don't currently have a easy way to filter, no common name, I think I'll just leave as is.
Of course you can:

Code: Select all

local sensor = {
	[INPUT_SENSOR1]=true, 
	[INPUT_SENSOR2]=true, ... 
}

domoticz.devices().filter( function(device)
	return (sensor[device.name] == true)
end).forEach( function(device)
	-- do your thing with the sensor
	temperatures.add(device.humidity)
end)
Creator dzVents - RPi3, loads of zwave devices, esp8266, evohome.
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest