gas usage classification, how to ? (SOLVED, incl CODE)

For heating/cooling related questions in Domoticz

Moderator: leecollings

Post Reply
willemd
Posts: 650
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

gas usage classification, how to ? (SOLVED, incl CODE)

Post by willemd »

I have P1 meter gas data and Opentherm Gateway data.
I want to classify my gas usage into categories:
1) gas used for hot water. This is gas used during a period where only the "hot water active" switch went on/off.
2) gas used for heating. This is gas used during a period where only the "central heating active" switch went on/off.
3) gas used for cooking. This is gas used during a period where neither the "hot water active" nor the "central heating active" switch went on/off, but still some gas was used.
4) gas used for multiple use, i.e. mixed or unclear. This is gas used where both switches went on/off. Here I still want to apply a split by estimating the gas usage for hot water using the minutes the hot water was on (and a flow rate per minute from the past) and then classify the rest has heating gas.

The heating gas usage will subsequently be used in gas per degree day calculations.

The approach I have in mind:
  • Every time the gas usage is updated and the increase is greater than zero:
  • Cycle through the two switch changes and calculate the seconds each switch has been on.
  • Then use the outcome for above classification and update 4 gas devices accordingly.
What is the best/easiest way to program this in dzvents? How can I cycle through the switch status changes specifically?

Or does someone have a totally different but valid approach to get a classification?
Last edited by willemd on Saturday 19 November 2022 19:43, edited 1 time in total.
User avatar
waltervl
Posts: 5859
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: gas usage classification, how to ?

Post by waltervl »

This is not possible as P1 meter is sending the gas consumption 1x per hour. So you do not know what the intended usage was in the last hour. if you have a modulating heater you do not know how much gas is used for heating or warm water even if you know the time the heater was switched on for each mode.
Perhaps your heater/thermostat knows it? My NefitEasy thermostat knows if it uses gas for heating or warm water. I do not send it to Domoticz (do not even know it is possible).

Perhaps the Opentherm gateway knows gas usage for each usage?
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
willemd
Posts: 650
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: gas usage classification, how to ?

Post by willemd »

waltervl wrote: Tuesday 30 August 2022 10:26 This is not possible as P1 meter is sending the gas consumption 1x per hour. So you do not know what the intended usage was in the last hour. if you have a modulating heater you do not know how much gas is used for heating or warm water even if you know the time the heater was switched on for each mode.
Perhaps your heater/thermostat knows it? My NefitEasy thermostat knows if it uses gas for heating or warm water. I do not send it to Domoticz (do not even know it is possible).

Perhaps the Opentherm gateway knows gas usage for each usage?
I realise the use of cooking gas might pollute the data and also when both switches were active during the past hour I can only make a theoretical calculation, but otherwise it should be possible, since:
1) when only the hot water switch was changed, then the gas was for hot water and possibly also cooking, but not for heating
2) when only the heating switch was changed, then the gas was for heating and possibly also cooking, but not for hot water
3) when neither hot water nor heating was used, then the gas was for cooking

When both switches were changed it become muddy, but I know the time the hot water was active and I can estimate the average gas usage per second for hot water from past experience, so I can make an estimate for the rest.

The approach I am planning on now is as follows:
1) every time the hot water switch changes to off, the seconds it was active will be calculated and this value will be put in a dummy counter device. Also if the hour has passed this update will be done (so if the switch is on while the hour changes, the calculation will be as-if it is switched off and on at the hour)
2) the same for heater switch
3) when the gas value increases with a non-zero value (max only once every hour), then the seconds of each dummy counter device will be checked and the classification will be determined. Dummy gas usage devices will be updated accordingly as result, so during the day I can see the different types of gas usage. The dummy counter devices mentioned in 1) and 2) will be reset to zero.
4) at the end of the day the heating gas usage will be used in the degree day calculation.
willemd
Posts: 650
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: gas usage classification, how to ?

Post by willemd »

For anyone trying to do the same, below is my script to classify my GAS usage into 3 different categories, i.e. hot-water-gas, cooking-gas and central-heating-gas. The central-heating-gas is then used in the gas-per-degreeday calculation.

Extensive comments and a lot of logging commands are still part of the script, because I wanted to see how everything was tracked/processed and then handle special situations.

Note the script so far has only been tested outside of the heating season.

Code: Select all

Code removed because it contained some bugs. See below for updated and corrected version.

Last edited by willemd on Tuesday 04 October 2022 18:19, edited 2 times in total.
jake
Posts: 744
Joined: Saturday 30 May 2015 22:40
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Contact:

Re: gas usage classification, how to ?

Post by jake »

I run the same split of gas usage since 2017, with the same limitation of the once/hour update of the P1-gas meter.

As an alternative, here my script (I have no gas for cooking):

Code: Select all

-- Title: GasUsageSplit.lua
-- Date: 01-11-2017
-- Script To measure energy usage (natural gas) for DHW usage (Shower, mainly) by combining OTGW information with P1 gas meter information

local LOG_LEVEL = domoticz.LOG_INFO -- Script default log level. You may change this.
-- domoticz.LOG_INFO, domoticz.LOG_DEBUG, domoticz.LOG_ERROR or domoticz.LOG_FORCE

return {
	active = true,                  -- set to true to activate this script
	on = {
		devices = {
		'Gas',
		'DHW_active',
		'CH_active'
		},
		timer = {
		'at 0:01'
		},
	},
	data = {
		GasUsage = {initial=nil},		--Newly created variable to store last boiler mode (idle, DHW gas or CH gas). Necessary because
						--gas meter is updated after the DHW/CH active switch is off and it is not known anymore for
						--which gas meter the gas consumption is.
		GasPrevious = {initial=nil},
	},
	logging = {
		level = domoticz.LOG_ERROR, --domoticz.LOG_INFO, domoticz.LOG_MODULE_EXEC_INFO, domoticz.LOG_DEBUG or domoticz.LOG_ERROR
		marker = "gas splitting"
			},
	
execute = function(domoticz)
	local gasTotal = domoticz.devices('Gas')		--Name of P1 gas meter device
	local DHW_energy_start = 'DHW_energy_start' 		--Newly created variable to store previous gas meter value
	local DHW_active = domoticz.devices('DHW_active') 	--OTGW virtual switch for boiler Domestic Hot Water 'On/Off'
	local CH_active = domoticz.devices('CH_active') 	--OTGW virtual switch for boiler Central Heating 'On/Off'
	local DHW_gas = 'DHW Gas'				--Name of newly created virtual Gas meter device for DHW
	local CH_gas = 'CH Gas'		 			--Name of newly created virtual Gas meter device for CH
	local gas_consumption					--Amount of gas used between latest gas meter update and the previous one
	local gasmeter						--The new gas meter value
	
	if domoticz.data.GasPrevious == nil then
		domoticz.data.GasPrevious = gasTotal.counter
	end
	if domoticz.data.GasUsage == nil then
		domoticz.data.GasUsage = DHW_gas
	end
	
	--Update to which virtual gasmeter the next gasmeter update value should go
	if DHW_active.state == 'On' then
		domoticz.data.GasUsage = DHW_gas
	elseif CH_active.state == 'On' then
		domoticz.data.GasUsage = CH_gas
	end
	
	if gasTotal.changed then
		--Calculate gas consumption by subtracting the stored previous gas meter value from the new (updated) gas meter value
		gas_consumption = gasTotal.counter - domoticz.data.GasPrevious
		domoticz.log('gasconumption = ' .. gas_consumption .. ' = gastotal counter - previous: '.. gasTotal.counter .. ' - ' .. domoticz.data.GasPrevious)
		if gas_consumption >= 0 then
			--domoticz.log ('Gas consumption = '..gasTotal.counter.." - "..domoticz.data.GasPrevious.." = "..gas_consumption..'m3')
			domoticz.data.GasPrevious = gasTotal.counter
			--multiply counter value by 1000 to match the units (dm3) for .updateGas and avoid decimals
			if domoticz.data.GasUsage == DHW_gas then
				domoticz.log('gas usage is DHW gas')
				gasmeter = domoticz.devices(DHW_gas).counter*1000 + domoticz.utils.round(gas_consumption*1000, 0)
				domoticz.log('gasmeter = ' .. gasmeter .. ' = DHW gascounterx1000  + gasconsumption = ' ..  domoticz.devices(DHW_gas).counter*1000 + domoticz.utils.round(gas_consumption*1000, 0))
				domoticz.devices(DHW_gas).updateGas(gasmeter)
				domoticz.devices(CH_gas).updateGas(domoticz.devices(CH_gas).counter*1000)
				domoticz.log('update CH gas met eigen waarde ' .. (domoticz.devices(CH_gas).counter*1000))
			elseif domoticz.data.GasUsage == CH_gas then
				domoticz.log('gas usage is CH gas')
				gasmeter = domoticz.devices(CH_gas).counter*1000 + domoticz.utils.round(gas_consumption*1000, 0)
				domoticz.log('gasmeter = ' .. gasmeter .. ' = CH gascounterx1000  + gasconsumption = ' ..  domoticz.devices(CH_gas).counter*1000 + domoticz.utils.round(gas_consumption*1000, 0))
				domoticz.devices(CH_gas).updateGas(gasmeter)
				domoticz.devices(DHW_gas).updateGas(domoticz.devices(DHW_gas).counter*1000)
				domoticz.log('update DHW gas met eigen waarde ' .. (domoticz.devices(DHW_gas).counter*1000))
			end
		end
	end
	
	--Update to which virtual gasmeter the next gasmeter update value should go
	if DHW_active.state == 'On' then
		domoticz.data.GasUsage = DHW_gas
	elseif CH_active.state == 'On' then
		domoticz.data.GasUsage = CH_gas
	end
	
	--Keep the gasmeters 'alive' when there is no gas usage for a longer time
	if domoticz.devices(DHW_gas).lastUpdate.hoursAgo > 23 then
		--multiply counter value by 1000 to match the units (dm3) for .updateCounter and avoid decimals
		domoticz.devices(DHW_gas).updateGas ((domoticz.devices(DHW_gas).counter)*1000)
	end
	if domoticz.devices(CH_gas).lastUpdate.hoursAgo > 23 then
		--multiply counter value by 1000 to match the units (dm3) for .updateCounter and avoid decimals
		domoticz.devices(CH_gas).updateGas ((domoticz.devices(CH_gas).counter)*1000)
	end
	
end
}
willemd
Posts: 650
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: gas usage classification, how to ?

Post by willemd »

jake wrote: Wednesday 14 September 2022 15:20 I run the same split of gas usage since 2017, with the same limitation of the once/hour update of the P1-gas meter.

As an alternative, here my script (I have no gas for cooking):
Thanks, Jake,

The absence of cooking gas makes it easier and more accurate.

However ...

You are assigning the total hourly GAS consumption to the category determined by whatever was switched ON last in the hour, right?
So if you have heating on for 50 minutes, then switch it off and then you switch on hot water for 5 minutes, the total hourly GAS consumption will be classified as hot water? My script is still trying to split the total based on the average GAS flow rate measured in the past for hot water (avg only updated if used > 180 seconds which is shower mainly). The rest will then be classified as heating-gas. I am not measuring just whether hot water or heating was switched on but also how long it was switched on during an hour.

Also, your script does not take into account the period between xx:00 and xx:04 (can be sometimes 03 or 02). Those are the minutes between the change of the hour and the new value of the GAS P1 meter coming in. I found that the GAS P1 meter splits consumption exactly at the hour, even though the value is imported only a few minutes later. So the GAS used during those minutes will only be reported after the next hour switchover.

Not sure whether it makes a big different in the heating season, I will still have to find out, but I tried to be as accurate as possible.
willemd
Posts: 650
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: gas usage classification, how to ?

Post by willemd »

Jake,

I am wondering why you don't have trouble related to the bug reported here: https://github.com/domoticz/domoticz/issues/5334
I would expect also in your case a reset of the counter value for the virtual GAS devices after midnight ? You don't see that happening?
See also viewtopic.php?t=39056

Are you prepared to run the simple test as proposed in the 5th post in the github thread, i.e. create a new virtual GAS device and run the simple script as shown in that post, i.e. the script that increments the gas device every minute? And see what happens after midnight?
jake
Posts: 744
Joined: Saturday 30 May 2015 22:40
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Contact:

Re: gas usage classification, how to ?

Post by jake »

willemd wrote: Wednesday 14 September 2022 20:19
jake wrote: Wednesday 14 September 2022 15:20 I run the same split of gas usage since 2017, with the same limitation of the once/hour update of the P1-gas meter.

As an alternative, here my script (I have no gas for cooking):
Thanks, Jake,

The absence of cooking gas makes it easier and more accurate.

However ...

You are assigning the total hourly GAS consumption to the category determined by whatever was switched ON last in the hour, right?
So if you have heating on for 50 minutes, then switch it off and then you switch on hot water for 5 minutes, the total hourly GAS consumption will be classified as hot water? My script is still trying to split the total based on the average GAS flow rate measured in the past for hot water (avg only updated if used > 180 seconds which is shower mainly). The rest will then be classified as heating-gas. I am not measuring just whether hot water or heating was switched on but also how long it was switched on during an hour.

Also, your script does not take into account the period between xx:00 and xx:04 (can be sometimes 03 or 02). Those are the minutes between the change of the hour and the new value of the GAS P1 meter coming in. I found that the GAS P1 meter splits consumption exactly at the hour, even though the value is imported only a few minutes later. So the GAS used during those minutes will only be reported after the next hour switchover.

Not sure whether it makes a big different in the heating season, I will still have to find out, but I tried to be as accurate as possible.
You're absolutely right that my split is a little rough and it might be interesting (for accuracy sake) to improve on this. However, in my case we use heating gas mostly during the night and sometimes during the day. We use a wood stove during most times that we are awake and at home. So, the not water comsumption will be quite accurate.

Have you taken into account that during heating the gas-usage per minute might be a lot less than during hot water usage? My thermostat shows a level 1 for heating and level 5 for hot water.
jake
Posts: 744
Joined: Saturday 30 May 2015 22:40
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Contact:

Re: gas usage classification, how to ?

Post by jake »

willemd wrote: Wednesday 14 September 2022 20:44 Jake,

I am wondering why you don't have trouble related to the bug reported here: https://github.com/domoticz/domoticz/issues/5334
I would expect also in your case a reset of the counter value for the virtual GAS devices after midnight ? You don't see that happening?
See also viewtopic.php?t=39056

Are you prepared to run the simple test as proposed in the 5th post in the github thread, i.e. create a new virtual GAS device and run the simple script as shown in that post, i.e. the script that increments the gas device every minute? And see what happens after midnight?
Nope, I don't see your error happening, but joined your test nonetheless.

The gas counter had a weird start for the first 3-4 minutes, but seems to add-up nicely now:
Spoiler: show
2022-09-16 20:52:00.305 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 20:52:00.305 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 20:52:00.325 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 0.0
2022-09-16 20:52:00.325 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 0.0
2022-09-16 20:52:00.326 Status: dzVents: Info: GAS device counter test: GAS device now updated to 1.0
2022-09-16 20:52:00.326 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 20:53:00.289 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 20:53:00.289 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 20:53:00.311 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 0.0
2022-09-16 20:53:00.311 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 0.0
2022-09-16 20:53:00.311 Status: dzVents: Info: GAS device counter test: GAS device now updated to 1.0
2022-09-16 20:53:00.312 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 20:54:00.376 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 20:54:00.376 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 20:54:00.398 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 0.0
2022-09-16 20:54:00.398 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 0.0
2022-09-16 20:54:00.398 Status: dzVents: Info: GAS device counter test: GAS device now updated to 1.0
2022-09-16 20:54:00.399 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 20:55:00.335 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 20:55:00.335 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 20:55:00.358 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 0.0
2022-09-16 20:55:00.358 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 0.0
2022-09-16 20:55:00.358 Status: dzVents: Info: GAS device counter test: GAS device now updated to 1.0
2022-09-16 20:55:00.358 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 20:56:00.349 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 20:56:00.349 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 20:56:00.373 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 0.0
2022-09-16 20:56:00.373 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 0.0
2022-09-16 20:56:00.373 Status: dzVents: Info: GAS device counter test: GAS device now updated to 1.0
2022-09-16 20:56:00.374 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 20:57:00.372 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 20:57:00.372 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 20:57:00.393 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 1.0
2022-09-16 20:57:00.393 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 0.0
2022-09-16 20:57:00.393 Status: dzVents: Info: GAS device counter test: GAS device now updated to 2.0
2022-09-16 20:57:00.394 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 20:58:00.379 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 20:58:00.379 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 20:58:00.409 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 2.0
2022-09-16 20:58:00.409 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 1.0
2022-09-16 20:58:00.410 Status: dzVents: Info: GAS device counter test: GAS device now updated to 3.0
2022-09-16 20:58:00.410 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 20:59:00.402 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 20:59:00.402 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 20:59:00.424 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 3.0
2022-09-16 20:59:00.424 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 2.0
2022-09-16 20:59:00.424 Status: dzVents: Info: GAS device counter test: GAS device now updated to 4.0
2022-09-16 20:59:00.424 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 21:00:00.534 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 21:00:00.534 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 21:00:00.558 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 4.0
2022-09-16 21:00:00.559 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 3.0
2022-09-16 21:00:00.559 Status: dzVents: Info: GAS device counter test: GAS device now updated to 5.0
2022-09-16 21:00:00.559 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 21:01:00.445 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 21:01:00.445 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 21:01:00.465 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 5.0
2022-09-16 21:01:00.465 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 4.0
2022-09-16 21:01:00.465 Status: dzVents: Info: GAS device counter test: GAS device now updated to 6.0
2022-09-16 21:01:00.465 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 21:02:00.463 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 21:02:00.463 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 21:02:00.485 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 6.0
2022-09-16 21:02:00.485 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 5.0
2022-09-16 21:02:00.485 Status: dzVents: Info: GAS device counter test: GAS device now updated to 7.0
2022-09-16 21:02:00.485 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 21:03:00.470 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 21:03:00.470 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 21:03:00.490 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 7.0
2022-09-16 21:03:00.490 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 6.0
2022-09-16 21:03:00.490 Status: dzVents: Info: GAS device counter test: GAS device now updated to 8.0
2022-09-16 21:03:00.490 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
2022-09-16 21:04:00.494 Status: dzVents: Info: GAS device counter test: ------ Start external script: gasmetertest.lua:, trigger: "every minute"
2022-09-16 21:04:00.495 Status: dzVents: Info: GAS device counter test: Timer event was triggered by every minute
2022-09-16 21:04:00.516 Status: dzVents: Info: GAS device counter test: Current counter value for GAS device is 8.0
2022-09-16 21:04:00.517 Status: dzVents: Info: GAS device counter test: Current counterToday value for GAS device is 7.0
2022-09-16 21:04:00.517 Status: dzVents: Info: GAS device counter test: GAS device now updated to 9.0
2022-09-16 21:04:00.517 Status: dzVents: Info: GAS device counter test: ------ Finished gasmetertest.lua
willemd
Posts: 650
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: gas usage classification, how to ?

Post by willemd »

Have you taken into account that during heating the gas-usage per minute might be a lot less than during hot water usage? My thermostat shows a level 1 for heating and level 5 for hot water.
I don't have experience with heating usage yet. All I know is that my boiler switches off heating when there is a demand for hot water. As far as I know I can only see the switch state. I don't know off any level that indicates the gas-usage. Is that modulation % ? My boiler does not provide that data field.
willemd
Posts: 650
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: gas usage classification, how to ?

Post by willemd »

Here is an updated version of my gas classification script, with some error corrections and with the degreeday calculations removed.
Some initial testing also with central heating has been done now.

Code: Select all

--[[
This scrips classifies gas usage every hour into 3 different categories

This script first tracks the seconds during each hour that the hot water or central heating has been active.
If either hot water or central heating was active across the hour boundary then the seconds are split into before- and after-the-hour values,
because the P1 meter provides gas usage exactly before- and after-the-hour, even though the actual value of the previous hour is only
received a few minutes after the hour (between 02 and 04 minutes after the hour).
When the gas usage is received, the gas usage is split into the right categories using the known usage seconds of the past hour.
Any events between the hour and the gas usage update are tracked for the new hour.

Previous version of this script also included degreeday calculations, but these have now been removed because it did not work well. This is now in a separate script.

Known limitations:
- cooking gas is not measured separately so will also be included in heating or hot water gas, unless both were not active
- if both hot water and central heating were active, a theoretical split is made based on past known gas flow rate for hot water
(and this avg flow rate is updated if hot water usage has been longer than 3 minutes)
- gas value is known approx. 4 minutes after the hour from the P1 meter, it is the value for the previous hour. This requires some special handling.
- opentherm gateway updates the switch states only every 30 seconds.
- the script is especially made for a version 4 Smart Meter that provides a new gas value only once per hour

Note the script can be triggered in very quick succession if two switches are update almost simultaneously by the Opentherm Gateway
No problem has been observed as result of this.

The script has not been extensively tested during the heating season yet. Only 3 days so far ....

Note: don't use virtual GAS devices to track the types of gas usage. Use virtual COUNTER devices instead and update those manually (with edit device) to type GAS with divider 1000 once created.
This is because resets of GAS counters (not only counterToday but also counter) have been observed after midnight, (update 04/10/2022 : this problem seems to be solved in latest beta version)
 ]]--
 
local idxGasP1=2                 -- idx of P1 meter Gas usage
local idxCentralHeatingActive=50 -- idx of CH-enabled from Opentherm Gateway (because CH-active is actually CH-pump-active and therefore not the one to use)
local idxHotWaterActive=57       -- idx of HW-active from Opentherm Gateway
local idxFlame=58                -- idx of Flame On from Opentherm Gateway (used for small corrections when hot water usage is only a few seconds)

local idxCentralHeatingGas=87    -- 3 virtual devices for tracking type of GAS usage
local idxCookingGas=88
local idxHotWaterGas=89 

local idxAvgGasFlowRateHW=81     -- average hot water flow rate

return {
	on = {
		devices = {
			idxHotWaterActive, 			-- hw switch
			idxCentralHeatingActive,    -- ch switch
			idxGasP1                    -- GAS P1 update
		},
		timer = {
		    'every hour'  -- to split the seconds into past and future hour for any devices active at xx:00
		},    
	},
	data = {
	        -- persistent variables, values kept from one script run to the other, also after system reset
	        -- two variables for tracking how many seconds either hot water or central heating was switched ON during the hour
            hotwaterseconds = { initial = 0 },
            centralheatingseconds = { initial = 0 },
            -- a variable to check not only an update but an actual increase of the gas meter
            previousgascounter = { initial = 0 },
            -- variables to help splitting total seconds into before and after the hour boundary
            previoushourhotwaterseconds = { initial = 0 },
            newhourhotwaterseconds = { initial = 0 },
            previoushourcentralheatingseconds = { initial = 0 },
            newhourcentralheatingseconds = { initial = 0 },
            previoushourprocessed = { initial = 'True' },
            firstgasupdateoftheday = { initial = 'False' }
    },        
	logging = {
		level = domoticz.LOG_INFO,
		marker = 'gas usage classification',
	},
	execute = function(domoticz, item)

	    if item.isDevice then  -- triggered by one of the devices, not the timer
    	    if item.idx==idxHotWaterActive then  -- hot water switched on/off
    	        if item.state == 'On' then
    		        domoticz.log('Hot Water was switched On', domoticz.LOG_INFO)
    		        -- on rare occasions Flame On is detected shortly before Hot Water is On
    		        if (domoticz.devices(idxFlame).state=='On' and domoticz.devices(idxCentralHeatingActive).state=="Off") then
    		            domoticz.log('Should add extra ' .. domoticz.devices(idxFlame).lastUpdate.secondsAgo .. 'hot water seconds because of earlier flame activation', domoticz.LOG_INFO) 
    		            if domoticz.data.previoushourprocessed == 'True' then 
    		                domoticz.log('Adding seconds to current hr', domoticz.LOG_INFO)
    		                domoticz.data.hotwaterseconds = domoticz.data.hotwaterseconds + domoticz.devices(idxFlame).lastUpdate.secondsAgo
    		            else
    		                domoticz.log('Saving seconds for next hr', domoticz.LOG_INFO)
    		                domoticz.data.newhourhotwaterseconds = domoticz.data.newhourhotwaterseconds + domoticz.devices(idxFlame).lastUpdate.secondsAgo
    		            end    
    		        end
    		    else
    		        domoticz.log('Hot Water was switched Off', domoticz.LOG_INFO)
    		        domoticz.log('previoushourprocessed' .. domoticz.data.previoushourprocessed )
    		        if domoticz.data.previoushourprocessed == 'True' then 
    		            domoticz.log('Adding seconds to current hr', domoticz.LOG_INFO)
    		            domoticz.data.hotwaterseconds = domoticz.data.hotwaterseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourhotwaterseconds
    		        else
    		            domoticz.log('Saving seconds for next hr', domoticz.LOG_INFO)
    		            domoticz.data.newhourhotwaterseconds = domoticz.data.newhourhotwaterseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourhotwaterseconds
    		        end       
    		        domoticz.log('Current time hot water ' .. item.lastUpdate.secondsAgo - domoticz.data.previoushourhotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		        domoticz.log('Total time hot water ' .. domoticz.data.hotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		        domoticz.data.previoushourhotwaterseconds = 0
    		    end  
    		end    
    	    if item.idx==idxCentralHeatingActive then
    	        if item.state == 'On' then
    		        domoticz.log('Central Heating was switched On', domoticz.LOG_INFO)
    		    else
    		        domoticz.log('Central Heating was switched Off', domoticz.LOG_INFO)
        		    if domoticz.data.previoushourprocessed == 'True' then 	
        		        domoticz.log('Adding seconds to current hr', domoticz.LOG_INFO)
        		        domoticz.data.centralheatingseconds = domoticz.data.centralheatingseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourcentralheatingseconds
        		    else      
        		        domoticz.log('Saving seconds for next hr', domoticz.LOG_INFO)
    		            domoticz.data.newhourcentralheatingseconds = domoticz.data.newhourcentralheatingseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourcentralheatingseconds
    		        end    		        
    		        domoticz.log('Current time central heating ' .. item.lastUpdate.secondsAgo - domoticz.data.previoushourcentralheatingseconds.. ' seconds', domoticz.LOG_INFO)
    		        domoticz.log('Total time central heating ' .. domoticz.data.centralheatingseconds .. ' seconds', domoticz.LOG_INFO)
    		        domoticz.data.previoushourcentralheatingseconds = 0
    		    end     
    		end    
    		if item.idx==idxGasP1 then
    	        local currentGas = domoticz.devices(idxGasP1).counter
    	        local increasegas = 0
    	        local currentValue=0
    	    
    		    domoticz.log('Device ' .. item.name .. ' was updated', domoticz.LOG_INFO)
    		    domoticz.log('hotwaterseconds ' .. domoticz.data.hotwaterseconds .. ' ', domoticz.LOG_INFO)
    		    domoticz.log('previous hr hotwaterseconds ' .. domoticz.data.previoushourhotwaterseconds .. ' ', domoticz.LOG_INFO)
    		    domoticz.log('centralheatingseconds ' .. domoticz.data.centralheatingseconds .. ' ', domoticz.LOG_INFO)
    		    domoticz.log('previous hr centralheatingseconds ' .. domoticz.data.previoushourcentralheatingseconds .. ' ', domoticz.LOG_INFO)
    		    
    		    domoticz.log('Hot Water Gas counter value ' .. domoticz.devices(idxHotWaterGas).counter .. ' ', domoticz.LOG_INFO)
        		domoticz.log('Hot Water Gas counterToday value ' .. domoticz.devices(idxHotWaterGas).counterToday .. ' ', domoticz.LOG_INFO)
        		domoticz.log('Central Heating Gas counter ' .. domoticz.devices(idxCentralHeatingGas).counter .. ' ', domoticz.LOG_INFO)
        		domoticz.log('Cooking Gas counter ' .. domoticz.devices(idxCookingGas).counter .. ' ', domoticz.LOG_INFO)

        		--if domoticz.devices(idxHotWaterGas).counter==0 then
        		--    domoticz.notify('Error: hot water gas counter was reset to zero',domoticz.PRIORITY_NORMAL)
        		--end    

    		    if currentGas>domoticz.data.previousgascounter then -- not only an update but a real increase. This occurs max every hour, approx 4 minutes past the hour
    		        -- The increase is the real increase of the previous hour. The P1 meter does a real split exactly at the hour.
    		        increasegas = domoticz.utils.round(currentGas - domoticz.data.previousgascounter,3)
    		        domoticz.log('Current value of Device ' .. item.name .. currentGas .. 'm3', domoticz.LOG_INFO)
    		        domoticz.log('Previousgascounter ' .. domoticz.data.previousgascounter .. 'm3', domoticz.LOG_INFO)
    		        domoticz.log('Value of Device ' .. item.name .. ' has increased by ' .. increasegas .. 'm3', domoticz.LOG_INFO)
    		        if domoticz.data.hotwaterseconds>0 and domoticz.data.centralheatingseconds==0 then
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of hot water (+ possibly cooking) usage', domoticz.LOG_INFO)
                        currentValue=domoticz.devices(idxHotWaterGas).counter
                        domoticz.devices(idxHotWaterGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
                        -- also update the avg gas flow rate for hot water, provided minimum 3 minute flow
                        -- apply factor 1000 for accuracy/decimals
                        if domoticz.data.hotwaterseconds>=180 then
                            local flowrate=increasegas/domoticz.data.hotwaterseconds*1000
                            local pastflowrate=domoticz.devices(idxAvgGasFlowRateHW).sensorValue
                            if flowrate<=1.5 * pastflowrate then -- ignore too high value, as result of inclusion of cooking gas
                                domoticz.devices(idxAvgGasFlowRateHW).updateCustomSensor(domoticz.utils.round((pastflowrate*9+flowrate)/10,3))  -- new value weights only 10% on the total average
                                domoticz.log('flow rate past hour ' .. flowrate .. ' ', domoticz.LOG_INFO)
                                domoticz.log('flow rate pas avg ' .. pastflowrate .. ' ', domoticz.LOG_INFO)
                            end
                        end    
    		        elseif domoticz.data.hotwaterseconds==0 and domoticz.data.centralheatingseconds>0 then
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of central heating (+ possibly cooking) usage', domoticz.LOG_INFO)
    		            
    		            currentValue=domoticz.devices(idxCentralHeatingGas).counter
                        domoticz.devices(idxCentralHeatingGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
    		        elseif domoticz.data.hotwaterseconds==0 and domoticz.data.centralheatingseconds==0 then   
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of cooking usage', domoticz.LOG_INFO)
    		            currentValue=domoticz.devices(idxCookingGas).counter
                        domoticz.devices(idxCookingGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
    		        elseif domoticz.data.hotwaterseconds>0 and domoticz.data.centralheatingseconds>0 then 
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of combined usage', domoticz.LOG_INFO)
    		            -- make a theoretical split between hot water and central heating, ignore possible cooking usage
    		            -- local hotwatergasestimate = domoticz.data.hotwaterseconds * 0.02/60 -- if not good avg calculation is available then 0.02 m3 per minute was a good average based on past observations
    		            local hotwatergasestimate = domoticz.devices(idxAvgGasFlowRateHW).sensorValue * domoticz.data.hotwaterseconds -- assume now a good avg is available, so use it.
    		            if hotwatergasestimate> increasegas then
    		                hotwatergasestimate=increasegas
    		                increasegas = 0
    		            else
    		                increasegas = increasegas - hotwatergasestimate
    		            end
    		            currentValue=domoticz.devices(idxCentralHeatingGas).counter
                        domoticz.devices(idxCentralHeatingGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
                        currentValue=domoticz.devices(idxHotWaterGas).counter
                        domoticz.devices(idxHotWaterGas).updateCounter(hotwatergasestimate*1000+currentValue*1000)  -- update value must be in dm3
    		        end   
    		        domoticz.data.hotwaterseconds=domoticz.data.newhourhotwaterseconds
    		        domoticz.data.centralheatingseconds=domoticz.data.newhourcentralheatingseconds
    		        domoticz.data.newhourhotwaterseconds=0
    		        domoticz.data.newhourcentralheatingseconds=0 
    		        domoticz.data.previousgascounter=currentGas
    		        domoticz.data.previoushourprocessed='True'
                else
    		        domoticz.log('Value of Device ' .. item.name .. ' has stayed the same', domoticz.LOG_INFO)
    		    end
    		end    
    	else -- triggered by the timer, not one of the devices    
    		-- the hourly timer is used to split the seconds for any switches than are ON across the hour limit
    		if domoticz.devices(idxHotWaterActive).state == 'On' then
    		    -- calculate as-if switched off/on at the hour
    		    domoticz.log('As-if Hot Water was switched Off', domoticz.LOG_INFO)
    		    domoticz.data.previoushourhotwaterseconds=domoticz.devices(idxHotWaterActive).lastUpdate.secondsAgo
    		    -- the above value is kept for later correction when the OFF switch occurs and then reset
    		    domoticz.data.hotwaterseconds = domoticz.data.hotwaterseconds + domoticz.data.previoushourhotwaterseconds
    		    domoticz.log('Extra before-hour hot water ' .. domoticz.data.previoushourhotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		    domoticz.log('Total time hot water ' .. domoticz.data.hotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		end
    		if domoticz.devices(idxCentralHeatingActive).state == 'On' then
    		    -- calculate as-if switched off/on at the hour
    		    domoticz.log('As-if Central Heating was switched Off', domoticz.LOG_INFO)
    		    domoticz.data.previoushourcentralheatingseconds=domoticz.devices(idxCentralHeatingActive).lastUpdate.secondsAgo
    		    -- the above value is kept for later correction when the OFF switch occurs and then reset
    		    domoticz.data.centralheatingseconds = domoticz.data.centralheatingseconds + domoticz.data.previoushourcentralheatingseconds
    		    domoticz.log('Extra before-hour central heating ' .. domoticz.data.previoushourcentralheatingseconds .. ' seconds', domoticz.LOG_INFO)
    		    domoticz.log('Total time central heating ' .. domoticz.data.centralheatingseconds .. ' seconds', domoticz.LOG_INFO)
    		end
    		-- previoushourprocessed is used to ensure the value of hotwaterseconds is kept until the gas increase of the previous hour has been processed
    		if domoticz.data.hotwaterseconds==0 and domoticz.data.centralheatingseconds==0 then
    		    domoticz.data.previoushourprocessed='True'
    		else
    		    if domoticz.data.previoushourprocessed=='True' then  -- only carry forward the hotwaterseconds one single hour, not more.
    		        domoticz.data.previoushourprocessed='False'
    		    else
    		        domoticz.data.previoushourprocessed='True'
    		    end      
    		end  

    		if domoticz.time.hour==0 then
    		    -- below updates were added because of a domoticz bug, which is apparently solved in latest beta as per 04/10/2022
    		    local currentcountervalue=0
    		    currentcountervalue=domoticz.devices(idxCentralHeatingGas).counter
    		    domoticz.log('Updating CH counter to existing value ' .. currentcountervalue .. ' ', domoticz.LOG_INFO)
    		    domoticz.devices(idxCentralHeatingGas).updateCounter(currentcountervalue*1000) -- update with 0 increase to prevent loosing real updates later
    		    currentcountervalue=domoticz.devices(idxHotWaterGas).counter
    		    domoticz.log('Updating HW counter to existing value ' .. currentcountervalue .. ' ', domoticz.LOG_INFO)
    		    domoticz.devices(idxHotWaterGas).updateCounter(currentcountervalue*1000) -- update with 0 increase to prevent loosing real updates later
    		    currentcountervalue=domoticz.devices(idxCookingGas).counter
    		    domoticz.log('Updating C counter to existing value ' .. currentcountervalue .. ' ', domoticz.LOG_INFO)
    		    domoticz.devices(idxCookingGas).updateCounter(currentcountervalue*1000) -- update with 0 increase to prevent loosing real updates later
    		end    
		end    
	end
}

willemd
Posts: 650
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: gas usage classification, how to ?

Post by willemd »

A further update with error correction on line 174. A factor 1000 needed to be added to get a correct split between central heating and hot water gas usage in case of combined usage within the same hour. As result of this error everything was classified as hot water gas in the previous version (in the case of combined usage, i.e. both switches going on/off within the same hour)

Code: Select all

--[[
This script classifies gas usage every hour into 3 different categories

This script first tracks the seconds during each hour that the hot water or central heating has been active.
If either hot water or central heating was active across the hour boundary then the seconds are split into before- and after-the-hour values,
because the P1 meter provides gas usage exactly before- and after-the-hour, even though the actual value of the previous hour is only
received a few minutes after the hour (between 02 and 04 minutes after the hour).
When the gas usage is received, the gas usage is split into the right categories using the known usage seconds of the past hour.
Any events between the hour and the gas usage update are tracked for the new hour.

Previous version of this script also included degreeday calculations, but these have now been removed because it did not work well. This is now in a separate script.

Known limitations:
- cooking gas is not measured separately so will also be included in heating or hot water gas, unless both were not active
- if both hot water and central heating were active, a theoretical split is made based on past known gas flow rate for hot water
(and this avg flow rate is updated if hot water usage has been longer than 3 minutes)
- gas value is known approx. 4 minutes after the hour from the P1 meter, it is the value for the previous hour. This requires some special handling.
- opentherm gateway updates the switch states only every 30 seconds.
- the script is especially made for a version 4 Smart Meter that provides a new gas value only once per hour

Note the script can be triggered in very quick succession if two switches are update almost simultaneously by the Opentherm Gateway
No problem has been observed as result of this.

The script has not been extensively tested during the heating season yet. Only 3 days so far ....

Note: don't use virtual GAS devices to track the types of gas usage. Use virtual COUNTER devices instead and update those manually (with edit device) to type GAS with divider 1000 once created.
This is because resets of GAS counters (not only counterToday but also counter) have been observed after midnight, (update 04/10/2022 : this problem seems to be solved in latest beta version)
 ]]--
 
local idxGasP1=2                 -- idx of P1 meter Gas usage
local idxCentralHeatingActive=50 -- idx of CH-enabled from Opentherm Gateway (because CH-active is actually CH-pump-active and therefore not the one to use)
local idxHotWaterActive=57       -- idx of HW-active from Opentherm Gateway
local idxFlame=58                -- idx of Flame On from Opentherm Gateway (used for small corrections when hot water usage is only a few seconds)

local idxCentralHeatingGas=87    -- 3 virtual devices for tracking type of GAS usage
local idxCookingGas=88
local idxHotWaterGas=89 

local idxAvgGasFlowRateHW=81     -- average hot water flow rate

return {
	on = {
		devices = {
			idxHotWaterActive, 			-- hw switch
			idxCentralHeatingActive,    -- ch switch
			idxGasP1                    -- GAS P1 update
		},
		timer = {
		    'every hour'  -- to split the seconds into past and future hour for any devices active at xx:00
		},    
	},
	data = {
	        -- persistent variables, values kept from one script run to the other, also after system reset
	        -- two variables for tracking how many seconds either hot water or central heating was switched ON during the hour
            hotwaterseconds = { initial = 0 },
            centralheatingseconds = { initial = 0 },
            -- a variable to check not only an update but an actual increase of the gas meter
            previousgascounter = { initial = 0 },
            -- variables to help splitting total seconds into before and after the hour boundary
            previoushourhotwaterseconds = { initial = 0 },
            newhourhotwaterseconds = { initial = 0 },
            previoushourcentralheatingseconds = { initial = 0 },
            newhourcentralheatingseconds = { initial = 0 },
            previoushourprocessed = { initial = 'True' },
            firstgasupdateoftheday = { initial = 'False' }
    },        
	logging = {
		level = domoticz.LOG_INFO,
		marker = 'gas usage classification',
	},
	execute = function(domoticz, item)

	    if item.isDevice then  -- triggered by one of the devices, not the timer
    	    if item.idx==idxHotWaterActive then  -- hot water switched on/off
    	        if item.state == 'On' then
    		        domoticz.log('Hot Water was switched On', domoticz.LOG_INFO)
    		        -- on rare occasions Flame On is detected shortly before Hot Water is On
    		        if (domoticz.devices(idxFlame).state=='On' and domoticz.devices(idxCentralHeatingActive).state=="Off") then
    		            domoticz.log('Should add extra ' .. domoticz.devices(idxFlame).lastUpdate.secondsAgo .. 'hot water seconds because of earlier flame activation', domoticz.LOG_INFO) 
    		            if domoticz.data.previoushourprocessed == 'True' then 
    		                domoticz.log('Adding seconds to current hr', domoticz.LOG_INFO)
    		                domoticz.data.hotwaterseconds = domoticz.data.hotwaterseconds + domoticz.devices(idxFlame).lastUpdate.secondsAgo
    		            else
    		                domoticz.log('Saving seconds for next hr', domoticz.LOG_INFO)
    		                domoticz.data.newhourhotwaterseconds = domoticz.data.newhourhotwaterseconds + domoticz.devices(idxFlame).lastUpdate.secondsAgo
    		            end    
    		        end
    		    else
    		        domoticz.log('Hot Water was switched Off', domoticz.LOG_INFO)
    		        domoticz.log('previoushourprocessed' .. domoticz.data.previoushourprocessed )
    		        if domoticz.data.previoushourprocessed == 'True' then 
    		            domoticz.log('Adding seconds to current hr', domoticz.LOG_INFO)
    		            domoticz.data.hotwaterseconds = domoticz.data.hotwaterseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourhotwaterseconds
    		        else
    		            domoticz.log('Saving seconds for next hr', domoticz.LOG_INFO)
    		            domoticz.data.newhourhotwaterseconds = domoticz.data.newhourhotwaterseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourhotwaterseconds
    		        end       
    		        domoticz.log('Current time hot water ' .. item.lastUpdate.secondsAgo - domoticz.data.previoushourhotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		        domoticz.log('Total time hot water ' .. domoticz.data.hotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		        domoticz.data.previoushourhotwaterseconds = 0
    		    end  
    		end    
    	    if item.idx==idxCentralHeatingActive then
    	        if item.state == 'On' then
    		        domoticz.log('Central Heating was switched On', domoticz.LOG_INFO)
    		    else
    		        domoticz.log('Central Heating was switched Off', domoticz.LOG_INFO)
        		    if domoticz.data.previoushourprocessed == 'True' then 	
        		        domoticz.log('Adding seconds to current hr', domoticz.LOG_INFO)
        		        domoticz.data.centralheatingseconds = domoticz.data.centralheatingseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourcentralheatingseconds
        		    else      
        		        domoticz.log('Saving seconds for next hr', domoticz.LOG_INFO)
    		            domoticz.data.newhourcentralheatingseconds = domoticz.data.newhourcentralheatingseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourcentralheatingseconds
    		        end    		        
    		        domoticz.log('Current time central heating ' .. item.lastUpdate.secondsAgo - domoticz.data.previoushourcentralheatingseconds.. ' seconds', domoticz.LOG_INFO)
    		        domoticz.log('Total time central heating ' .. domoticz.data.centralheatingseconds .. ' seconds', domoticz.LOG_INFO)
    		        domoticz.data.previoushourcentralheatingseconds = 0
    		    end     
    		end    
    		if item.idx==idxGasP1 then
    	        local currentGas = domoticz.devices(idxGasP1).counter
    	        local increasegas = 0
    	        local currentValue=0
    	    
    		    domoticz.log('Device ' .. item.name .. ' was updated', domoticz.LOG_INFO)
    		    domoticz.log('hotwaterseconds ' .. domoticz.data.hotwaterseconds .. ' ', domoticz.LOG_INFO)
    		    domoticz.log('previous hr hotwaterseconds ' .. domoticz.data.previoushourhotwaterseconds .. ' ', domoticz.LOG_INFO)
    		    domoticz.log('centralheatingseconds ' .. domoticz.data.centralheatingseconds .. ' ', domoticz.LOG_INFO)
    		    domoticz.log('previous hr centralheatingseconds ' .. domoticz.data.previoushourcentralheatingseconds .. ' ', domoticz.LOG_INFO)
    		    
    		    domoticz.log('Hot Water Gas counter value ' .. domoticz.devices(idxHotWaterGas).counter .. ' ', domoticz.LOG_INFO)
        		domoticz.log('Hot Water Gas counterToday value ' .. domoticz.devices(idxHotWaterGas).counterToday .. ' ', domoticz.LOG_INFO)
        		domoticz.log('Central Heating Gas counter ' .. domoticz.devices(idxCentralHeatingGas).counter .. ' ', domoticz.LOG_INFO)
        		domoticz.log('Cooking Gas counter ' .. domoticz.devices(idxCookingGas).counter .. ' ', domoticz.LOG_INFO)

        		--if domoticz.devices(idxHotWaterGas).counter==0 then
        		--    domoticz.notify('Error: hot water gas counter was reset to zero',domoticz.PRIORITY_NORMAL)
        		--end    

    		    if currentGas>domoticz.data.previousgascounter then -- not only an update but a real increase. This occurs max every hour, approx 4 minutes past the hour
    		        -- The increase is the real increase of the previous hour. The P1 meter does a real split exactly at the hour.
    		        increasegas = domoticz.utils.round(currentGas - domoticz.data.previousgascounter,3)
    		        domoticz.log('Current value of Device ' .. item.name .. currentGas .. 'm3', domoticz.LOG_INFO)
    		        domoticz.log('Previousgascounter ' .. domoticz.data.previousgascounter .. 'm3', domoticz.LOG_INFO)
    		        domoticz.log('Value of Device ' .. item.name .. ' has increased by ' .. increasegas .. 'm3', domoticz.LOG_INFO)
    		        if domoticz.data.hotwaterseconds>0 and domoticz.data.centralheatingseconds==0 then
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of hot water (+ possibly cooking) usage', domoticz.LOG_INFO)
                        currentValue=domoticz.devices(idxHotWaterGas).counter
                        domoticz.devices(idxHotWaterGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
                        -- also update the avg gas flow rate for hot water, provided minimum 3 minute flow
                        -- apply factor 1000 for accuracy/decimals
                        if domoticz.data.hotwaterseconds>=180 then
                            local flowrate=increasegas/domoticz.data.hotwaterseconds*1000
                            local pastflowrate=domoticz.devices(idxAvgGasFlowRateHW).sensorValue
                            if flowrate<=1.5 * pastflowrate then -- ignore too high value, as result of inclusion of cooking gas
                                domoticz.devices(idxAvgGasFlowRateHW).updateCustomSensor(domoticz.utils.round((pastflowrate*9+flowrate)/10,3))  -- new value weights only 10% on the total average
                                domoticz.log('flow rate past hour ' .. flowrate .. ' ', domoticz.LOG_INFO)
                                domoticz.log('flow rate pas avg ' .. pastflowrate .. ' ', domoticz.LOG_INFO)
                            end
                        end    
    		        elseif domoticz.data.hotwaterseconds==0 and domoticz.data.centralheatingseconds>0 then
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of central heating (+ possibly cooking) usage', domoticz.LOG_INFO)
    		            
    		            currentValue=domoticz.devices(idxCentralHeatingGas).counter
                        domoticz.devices(idxCentralHeatingGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
    		        elseif domoticz.data.hotwaterseconds==0 and domoticz.data.centralheatingseconds==0 then   
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of cooking usage', domoticz.LOG_INFO)
    		            currentValue=domoticz.devices(idxCookingGas).counter
                        domoticz.devices(idxCookingGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
    		        elseif domoticz.data.hotwaterseconds>0 and domoticz.data.centralheatingseconds>0 then 
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of combined usage', domoticz.LOG_INFO)
    		            -- make a theoretical split between hot water and central heating, ignore possible cooking usage
    		            -- local hotwatergasestimate = domoticz.data.hotwaterseconds * 0.02/60 -- if not good avg calculation is available then 0.02 m3 per minute was a good average based on past observations
    		            local hotwatergasestimate = domoticz.devices(idxAvgGasFlowRateHW).sensorValue * domoticz.data.hotwaterseconds / 1000 -- assume now a good avg is available, so use it.
    		            if hotwatergasestimate> increasegas then
    		                hotwatergasestimate=increasegas
    		                increasegas = 0
    		            else
    		                increasegas = increasegas - hotwatergasestimate
    		            end
    		            currentValue=domoticz.devices(idxCentralHeatingGas).counter
                        domoticz.devices(idxCentralHeatingGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
                        currentValue=domoticz.devices(idxHotWaterGas).counter
                        domoticz.devices(idxHotWaterGas).updateCounter(hotwatergasestimate*1000+currentValue*1000)  -- update value must be in dm3
    		        end   
    		        domoticz.data.hotwaterseconds=domoticz.data.newhourhotwaterseconds
    		        domoticz.data.centralheatingseconds=domoticz.data.newhourcentralheatingseconds
    		        domoticz.data.newhourhotwaterseconds=0
    		        domoticz.data.newhourcentralheatingseconds=0 
    		        domoticz.data.previousgascounter=currentGas
    		        domoticz.data.previoushourprocessed='True'
                else
    		        domoticz.log('Value of Device ' .. item.name .. ' has stayed the same', domoticz.LOG_INFO)
    		    end
    		end    
    	else -- triggered by the timer, not one of the devices    
    		-- the hourly timer is used to split the seconds for any switches than are ON across the hour limit
    		if domoticz.devices(idxHotWaterActive).state == 'On' then
    		    -- calculate as-if switched off/on at the hour
    		    domoticz.log('As-if Hot Water was switched Off', domoticz.LOG_INFO)
    		    domoticz.data.previoushourhotwaterseconds=domoticz.devices(idxHotWaterActive).lastUpdate.secondsAgo
    		    -- the above value is kept for later correction when the OFF switch occurs and then reset
    		    domoticz.data.hotwaterseconds = domoticz.data.hotwaterseconds + domoticz.data.previoushourhotwaterseconds
    		    domoticz.log('Extra before-hour hot water ' .. domoticz.data.previoushourhotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		    domoticz.log('Total time hot water ' .. domoticz.data.hotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		end
    		if domoticz.devices(idxCentralHeatingActive).state == 'On' then
    		    -- calculate as-if switched off/on at the hour
    		    domoticz.log('As-if Central Heating was switched Off', domoticz.LOG_INFO)
    		    domoticz.data.previoushourcentralheatingseconds=domoticz.devices(idxCentralHeatingActive).lastUpdate.secondsAgo
    		    -- the above value is kept for later correction when the OFF switch occurs and then reset
    		    domoticz.data.centralheatingseconds = domoticz.data.centralheatingseconds + domoticz.data.previoushourcentralheatingseconds
    		    domoticz.log('Extra before-hour central heating ' .. domoticz.data.previoushourcentralheatingseconds .. ' seconds', domoticz.LOG_INFO)
    		    domoticz.log('Total time central heating ' .. domoticz.data.centralheatingseconds .. ' seconds', domoticz.LOG_INFO)
    		end
    		-- previoushourprocessed is used to ensure the value of hotwaterseconds is kept until the gas increase of the previous hour has been processed
    		if domoticz.data.hotwaterseconds==0 and domoticz.data.centralheatingseconds==0 then
    		    domoticz.data.previoushourprocessed='True'
    		else
    		    if domoticz.data.previoushourprocessed=='True' then  -- only carry forward the hotwaterseconds one single hour, not more.
    		        domoticz.data.previoushourprocessed='False'
    		    else
    		        domoticz.data.previoushourprocessed='True'
    		    end      
    		end  

    		if domoticz.time.hour==0 then
    		    -- below updates were added because of a domoticz bug, which is apparently solved in latest beta as per 04/10/2022
    		    local currentcountervalue=0
    		    currentcountervalue=domoticz.devices(idxCentralHeatingGas).counter
    		    domoticz.log('Updating CH counter to existing value ' .. currentcountervalue .. ' ', domoticz.LOG_INFO)
    		    domoticz.devices(idxCentralHeatingGas).updateCounter(currentcountervalue*1000) -- update with 0 increase to prevent loosing real updates later
    		    currentcountervalue=domoticz.devices(idxHotWaterGas).counter
    		    domoticz.log('Updating HW counter to existing value ' .. currentcountervalue .. ' ', domoticz.LOG_INFO)
    		    domoticz.devices(idxHotWaterGas).updateCounter(currentcountervalue*1000) -- update with 0 increase to prevent loosing real updates later
    		    currentcountervalue=domoticz.devices(idxCookingGas).counter
    		    domoticz.log('Updating C counter to existing value ' .. currentcountervalue .. ' ', domoticz.LOG_INFO)
    		    domoticz.devices(idxCookingGas).updateCounter(currentcountervalue*1000) -- update with 0 increase to prevent loosing real updates later
    		end    
		end    
	end
}
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest