Page 1 of 1

Sensor update triggers script

Posted: Monday 09 March 2020 18:25
by jkimmel
I'm running scripts to control my heating system.
My scripts start with

Code: Select all

return {
	on = {
		['timer'] = {
			'every 10 minutes',
		},
		devices = {
			TEMPERATURE_SENSOR,
			SETPOINT_DEVICE
		}
	},
So every time the sensor is updated the script will be triggered.
How to trigger the script only when the value of the sensor has changed?

Re: Sensor update triggers script

Posted: Monday 09 March 2020 20:35
by freijn
@Waaren H E L P me :-)

I am getting close but can't get to the working one..... :-(

Code: Select all

return {
            on =    {
                    devices = { 'TEMPERATURE_SENSOR', 
                              },
                    },

    data =  {
                TEMPERATURE_level = { initial = 0 }
            },

    logging =   {
                    level = domoticz.LOG_DEBUG,
                    marker = "Temp Value"
                },

    execute = function(dz, item)
        if item.name == 'TEMPERATURE_SENSOR' and item.value ~= dz.data.TEMPERATURE_level then
            dz.notify('Temp level changed','Temp changed!')
            dz.data.TEMPERATURE_level = item.value
        end
    end
}

Re: Sensor update triggers script

Posted: Monday 09 March 2020 21:23
by waaren
jkimmel wrote: Monday 09 March 2020 18:25 I'm running scripts to control my heating system.
How to trigger the script only when the value of the sensor has changed?
You will need to do some administration of the device-state in the script.

Code: Select all

local TEMPERATURE_SENSOR = 130
local SETPOINT_DEVICE = 131

return
{
    on = 
    {
        devices = 
        {
            TEMPERATURE_SENSOR,
            SETPOINT_DEVICE,
        },
    },

    logging =   
    {
        level = domoticz.LOG_DEBUG, -- set to LOG_ERROR when tested and OK
        marker = 'setSetpoint', 
    },

    data = 
    {
        myHistory = 
        { 
            initial = {},
        },
    },

    execute = function(dz, item)
        if dz.data.myHistory[item.name] ~= nil and dz.data.myHistory[item.name].nValue == item.nValue and dz.data.myHistory[item.name].sValue == item.sValue then
            dz.log('no action required',dz.LOG_DEBUG)
            return
        end
        dz.data.myHistory[item.name] = {}
        dz.data.myHistory[item.name].nValue = item.nValue 
        dz.data.myHistory[item.name].sValue = item.sValue
        
        -- Rest of script
        dz.log('Action required',dz.LOG_DEBUG)
    end
}

Re: Sensor update triggers script

Posted: Tuesday 10 March 2020 11:14
by jkimmel
I'm using dannybloe's script for heating control, merely by copy and paste and not always understanding how it may work.
Now thinking of reducing triggering the scripts and getting your response I looked again into my script.
Here is the sector which I think should already run the script to its end only if sensor value or setpoint changes.
It is about reducing writes on the sdcard.

Code: Select all

	if (triggerInfo.type == domoticz.EVENT_TYPE_DEVICE) then

			if (sensor.changed) then
				-- sensor just reported a new reading
				-- add it to the readings table

				if (current ~= 0 and current ~= nil) then
					temperatureReadings.add(current)
				else
					-- no need to be here, weird state detected
					domoticz.log('Strange sensor reading.. skiping', domoticz.LOG_ERROR)
					return
				end

			elseif (domoticz.devices(SETPOINT_DEVICE).changed) then
				-- a new setpoint was set
				if LOGGING then domoticz.log('Setpoint was set to ' .. device.state) end
			else
				-- no business here, bail out...
				return
			end
Do I miss something?

Re: Sensor update triggers script

Posted: Tuesday 10 March 2020 12:23
by waaren
jkimmel wrote: Tuesday 10 March 2020 11:14 I'm using dannybloe's script for heating control, merely by copy and paste and not always understanding how it may work.
Now thinking of reducing triggering the scripts and getting your response I looked again into my script.

Do I miss something?
The script you are using is from the early days of dzVents. If you share the complete script I can have a go of merging it with the example.
Also have a look at the wiki and search for changed. You will read under Device attributes:
changed: Boolean. True if the device was updated. Note: This does not necessarily means the device state or value changed.

Re: Sensor update triggers script

Posted: Tuesday 10 March 2020 15:50
by jkimmel
Thank you for your fast response. Here my complete script:
Spoiler: show

Code: Select all

-- assumptions:
-- the setpoint is set by a selector dummy device where the values are numeric temperatures
-- but you can easily change it to a setpoint device

local BOILER_DEVICE = 'FB 21 Heizkreis Salon' -- switch device
local SETPOINT_DEVICE = 'Solltemperatur Salon' -- selector dummy device
local TEMPERATURE_SENSOR = 'Salon Temperatur'
local CHANGE_DEVICE = 'Modus Waermepumpe' -- selector dummy device
local HYSTERESIS = 0.5 -- temp has to drop this value below setpoint before boiler is on again
local HEATPUMP_RETURN = 'WP Ruecklauf' -- controls dewpoint of walls
local SMOOTH_FACTOR = 3
local LOGGING = true

return {
	on = {
		['timer'] = {
			'every 10 minutes',
		},
		devices = {
			TEMPERATURE_SENSOR,
			SETPOINT_DEVICE
		}
	},
	data = {
		temperatureReadings = { history = true, maxItems = SMOOTH_FACTOR }
	},
	active = true,
	execute = function(domoticz, device, triggerInfo)

		local avgTemp
		local temperatureReadings = domoticz.data.temperatureReadings
		local sensor = domoticz.devices(TEMPERATURE_SENSOR)
		local current = sensor.temperature
		local boiler = domoticz.devices(BOILER_DEVICE)
		local setpoint = domoticz.devices(SETPOINT_DEVICE)

		-- first check if the sensor got a new reading or the setpoint was changed:
		if (triggerInfo.type == domoticz.EVENT_TYPE_DEVICE) then

			if (sensor.changed) then
				-- sensor just reported a new reading
				-- add it to the readings table

				if (current ~= 0 and current ~= nil) then
					temperatureReadings.add(current)
				else
					-- no need to be here, weird state detected
					domoticz.log('Strange sensor reading.. skiping', domoticz.LOG_ERROR)
					return
				end

			elseif (domoticz.devices(SETPOINT_DEVICE).changed) then
				-- a new setpoint was set
				if LOGGING then domoticz.log('Setpoint was set to ' .. device.state) end
			else
				-- no business here, bail out...
				return
			end
		end

		-- now determine what to do
		if (setpoint.state == nil or setpoint.state == 'Off') then
			boiler.switchOff()
			return -- we're done here
		end

		local setpointValue = tonumber(setpoint.state)

		-- determine at which temperature the boiler should be
		-- switched on
		local switchOnTemp = setpointValue - HYSTERESIS

		-- don't use the current reading but average it out over
		-- the past <SMOOTH_FACTOR> readings (data smoothing) to get rid of noise, wrong readings etc
		local avgTemp = temperatureReadings.avg(1, SMOOTH_FACTOR, current) -- fallback to current when history is empty

		if LOGGING then
			domoticz.log('Average: ' .. avgTemp, domoticz.LOG_INFO)
			domoticz.log('Setpoint: ' .. setpointValue, domoticz.LOG_INFO)
			domoticz.log('Current boiler state: ' .. boiler.state, domoticz.LOG_INFO)
			domoticz.log('Switch-on temperature: ' .. switchOnTemp, domoticz.LOG_INFO)
		end

		if (avgTemp >= setpointValue and boiler.state == 'On') then
			if LOGGING then domoticz.log('Target temperature reached, boiler off') end
			boiler.switchOff()
		end

		if (avgTemp < setpointValue and boiler.state == 'Off') then
			if (avgTemp < switchOnTemp) then
				if LOGGING then domoticz.log('Heating is required, boiler switched on') end
				boiler.switchOn()
			else
				if LOGGING then domoticz.log('Average temperature below setpoint but within hysteresis range, waiting for temperature to drop to ' .. switchOnTemp) end
			end
		end
	end
}

Re: Sensor update triggers script  [Solved]

Posted: Tuesday 10 March 2020 17:15
by waaren
jkimmel wrote: Tuesday 10 March 2020 15:50 Thank you for your fast response. Here my complete script:
This script relies on the new readings even if they are equal to the previous one. It does not make sense to ignore these reading. The smoothing and hysteresis will not work as designed if you do that.