Here’s the entire setup. You need three temperature sensors at the three-way mixing unit and tech data on the pump flow to get ratio, power and energy calculated.
I use the temperatures to calculate the ratios, based on Kirchhoff’s current law.
It all shows nicely up in the Energy panel under “Gas consumption”
[{"id":"5b9a39c4104bea1d","type":"group","z":"e3f30e09f01c979f","name":"Ofen Sensorgruppe","style":{"label":true,"stroke":"#ff0000","color":"#000000"},"nodes":["f7101a878906ff13","f548f031284cf8e4","8d68417fa0d402de","08ae38f779cf334d","99819d57d53cae5d","5d35d585a01c8fbd","0f4bc48f32920fa2","30a68a60b4b5a624","fdc068a15fd7aeac","49c447c109d24801","7e35282b10bace08","87559157a30aa38d","49e1e0eaae5987a5","868522eee1c1a024","fe61e2ce9210577b","a5eec25bae6c5767","7dafbfc0f5e2fa3f"],"x":34,"y":760,"w":1671,"h":281},{"id":"f7101a878906ff13","type":"poll-state","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Pump-State","server":"61c89149.6b842","version":3,"exposeAsEntityConfig":"","updateInterval":"2","updateIntervalType":"num","updateIntervalUnits":"seconds","outputInitially":false,"outputOnChanged":false,"entityId":"switch.shellypro4pm_0_5_3_e_switch_3","stateType":"habool","ifState":"","ifStateType":"str","ifStateOperator":"is","outputs":1,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":130,"y":801,"wires":[["f548f031284cf8e4"]]},{"id":"f548f031284cf8e4","type":"function","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Set.global PumpSwitch","func":"// Assuming msg.payload contains a boolean value\nvar boolValue = msg.payload; // Replace this with your boolean value\n\n// Convert boolean to 1 or 0 using a ternary operator\nvar PumpSwitch = boolValue ? 1 : 0;\n\n// Update the global variable with the new value\nglobal.set(\"PumpSwitch\", PumpSwitch);\n\n// Pass the updated value to the next node (optional)\nmsg.payload = global.get(\"PumpSwitch\");\n\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":390,"y":801,"wires":[[]]},{"id":"8d68417fa0d402de","type":"function","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Oven Power transfer","func":"// Access individual temperature and pump status from global variables\nvar temperatureOutput = global.get(\"temperatureOutput\") || 0;\nvar temperatureInput = global.get(\"temperatureInput\") || 0;\nvar heatTransferRatio = global.get(\"heatTransferRatio\") || 0;\nvar PumpSwitch = global.get(\"PumpSwitch\") || 0;\n\n// Calculate the Temperature difference output-input\nvar deltaTemperature = temperatureOutput - temperatureInput;\n\n// Pump flow rate in liters per minute (based on 1800 liters per hour)\nvar pumpFlowRateLitersPerMinute = 30;\n\n// Specific heat capacity of water in J/(kg·°C)\nvar specificHeatCapacityOfWater = 4186; // This is an approximate value, you may need to adjust it\n\n// Density of water in kg/L\nvar densityOfWater = 1; // This is an approximate value for room temperature\n\n// Calculate the mass of water in kg\nvar massOfWater = (heatTransferRatio / 100) * pumpFlowRateLitersPerMinute * densityOfWater;\n\n// Calculate the energy transferred in joules\nvar energyJoules = massOfWater * specificHeatCapacityOfWater * deltaTemperature;\n\n// Convert joules to watts\nvar powerWatts = energyJoules / 60; // Assuming 60 seconds in a minute\n\n// round the output to 3 decimals\npowerWatts = powerWatts.toFixed(0);\n\n// convert to number\npowerWatts = parseFloat(powerWatts);\n\n// multiply output with PumpSwitch Status\npowerWatts = powerWatts * PumpSwitch;\n\n// limit to only positive values including zero\npowerWatts = Math.max(0, powerWatts);\n\n// Set the result as the payload\nmsg.payload = powerWatts;\nmsg.topic = 'OvenPowerWatts';\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":939,"y":866,"wires":[["49e1e0eaae5987a5","868522eee1c1a024"]]},{"id":"08ae38f779cf334d","type":"poll-state","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Ofen Einspeisung","server":"61c89149.6b842","version":3,"exposeAsEntityConfig":"","updateInterval":"2","updateIntervalType":"num","updateIntervalUnits":"seconds","outputInitially":true,"outputOnChanged":false,"entityId":"sensor.shelly_uni_0_6_6_c_ladepumpe_temperature_1","stateType":"num","ifState":"","ifStateType":"str","ifStateOperator":"is","outputs":1,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":140,"y":861,"wires":[["5d35d585a01c8fbd"]]},{"id":"99819d57d53cae5d","type":"poll-state","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Speicher Vorlauf","server":"61c89149.6b842","version":3,"exposeAsEntityConfig":"","updateInterval":"2","updateIntervalType":"num","updateIntervalUnits":"seconds","outputInitially":true,"outputOnChanged":false,"entityId":"sensor.shelly_uni_0_6_6_c_ladepumpe_temperature_3","stateType":"num","ifState":"","ifStateType":"str","ifStateOperator":"is","outputs":1,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"},{"property":"parts","propertyType":"msg","value":"3","valueType":"num"}],"x":140,"y":921,"wires":[["0f4bc48f32920fa2"]]},{"id":"5d35d585a01c8fbd","type":"function","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Set.global temperatureOutput","func":"// Assuming msg.payload contains the sensor output\nvar sensorValue = msg.payload;\n\n// Update the global variable with the new value\nglobal.set(\"temperatureOutput\", sensorValue);\n\n// Pass the updated value to the next node (optional)\nmsg.payload = global.get(\"temperatureOutput\");\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":410,"y":861,"wires":[[]]},{"id":"0f4bc48f32920fa2","type":"function","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Set.global temperatureInput","func":"// Assuming msg.payload contains the sensor output\nvar sensorValue = msg.payload;\n\n// Update the global variable with the new value\nglobal.set(\"temperatureInput\", sensorValue);\n\n// Pass the updated value to the next node (optional)\nmsg.payload = global.get(\"temperatureInput\");\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":921,"wires":[[]]},{"id":"30a68a60b4b5a624","type":"inject","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"1-second Poll","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":680,"y":840,"wires":[["8d68417fa0d402de","7e35282b10bace08"]]},{"id":"fdc068a15fd7aeac","type":"poll-state","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Ofen Vorlauf","server":"61c89149.6b842","version":3,"exposeAsEntityConfig":"","updateInterval":"2","updateIntervalType":"num","updateIntervalUnits":"seconds","outputInitially":true,"outputOnChanged":false,"entityId":"sensor.shelly_uni_0_6_6_c_ladepumpe_temperature_2","stateType":"num","ifState":"","ifStateType":"str","ifStateOperator":"is","outputs":1,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"},{"property":"parts","propertyType":"msg","value":"2","valueType":"num"}],"x":130,"y":981,"wires":[["49c447c109d24801"]]},{"id":"49c447c109d24801","type":"function","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Set.global ovenInput","func":"// Assuming msg.payload contains the sensor output\nvar sensorValue = msg.payload;\n\n// Update the global variable with the new value\nglobal.set(\"ovenInput\", sensorValue);\n\n// Pass the updated value to the next node (optional)\nmsg.payload = global.get(\"ovenInput\");\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":981,"wires":[[]]},{"id":"7e35282b10bace08","type":"function","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Set.global heatTransferRatio","func":"// Assuming msg.payload contains the temperature sensor data\n// Access temperature values from global variables\nvar temperature1 = global.get(\"temperatureOutput\") || 0;\nvar temperature2 = global.get(\"ovenInput\") || 0;\nvar temperature3 = global.get(\"temperatureInput\") || 0;\nvar PumpSwitch = global.get(\"PumpSwitch\") || 0;\n\n// var temperature1 = msg.payload[\"sensor.shelly_uni_0_6_6_c_ladepumpe_temperature_1\"] || 0; // Temperature from sensor\n// var temperature2 = msg.payload[\"sensor.shelly_uni_0_6_6_c_ladepumpe_temperature_2\"] || 0;\n// var temperature3 = msg.payload[\"sensor.shelly_uni_0_6_6_c_ladepumpe_temperature_3\"] || 0;\n\n// Calculate the heat transfer ratio\nvar heatTransferRatio = 100 - ((temperature2 - temperature3) / (temperature1 - temperature3)) * 100;\n\n// Round the result to the nearest whole number\n// heatTransferRatio = Math.round(heatTransferRatio);\nheatTransferRatio = heatTransferRatio.toFixed(1);\n\n// Clamp the value between 0 and 100\nheatTransferRatio = Math.min(100, Math.max(0, heatTransferRatio));\n\n// Only set value when oven is burning\nheatTransferRatio = PumpSwitch * heatTransferRatio;\n\n// Set the heat transfer ratio as a global variable\nglobal.set(\"heatTransferRatio\", heatTransferRatio);\n\n// Set the heat transfer ratio as the payload\nmsg.payload = heatTransferRatio;\nmsg.topic = \"heatTransferRatio\"\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":959,"y":806,"wires":[["87559157a30aa38d"]]},{"id":"87559157a30aa38d","type":"ha-sensor","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"sensor.heatTransferRatio","entityConfig":"e5aa6fef707c2d73","version":0,"state":"payload","stateType":"msg","
attributes":[],"inputOverride":"allow","outputProperties":[],"x":1549,"y":805,"wires":[[]]},{"id":"49e1e0eaae5987a5","type":"ha-sensor","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"sensor.OvenPowerTransfer","entityConfig":"ce391c35b6eb8d0d","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1559,"y":865,"wires":[[]]},{"id":"868522eee1c1a024","type":"function","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Oven Energy","func":"// Hole die aktuelle Leistung aus der Nachricht\nvar leistung = msg.payload; // Leistung in Watt\nvar previousTimestamp = flow.get('previousTimestamp') || Date.now();\nvar previousEnergy = flow.get('energy') || 0; // Energiestand in Wattstunden\n\n// Berechne Zeitdifferenz in Sekunden\nvar currentTimestamp = Date.now();\nvar zeitdifferenz = (currentTimestamp - previousTimestamp) / 1000; // Zeit in Sekunden\n\n// Berechne die hinzugefügte Energie in Kilowattstunden\nvar energieZuwachs = (leistung * zeitdifferenz) / (3600 * 1000)\n\n// Kumulierte Energie berechnen (kWh, drei Nachkommastellen)\nvar kumulierteEnergie = previousEnergy + energieZuwachs;\nkumulierteEnergie = Math.round(kumulierteEnergie * 1000) / (1000); // Runden auf ganze Zahl\n\n// Speichere den aktuellen Zustand\nflow.set('previousTimestamp', currentTimestamp);\nflow.set('energy', kumulierteEnergie);\n\n// Gib die kumulierte Energie als Payload zurück\nmsg.payload = kumulierteEnergie;\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1247,"y":946,"wires":[["fe61e2ce9210577b"]]},{"id":"fe61e2ce9210577b","type":"ha-sensor","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"sensor.OvenEnergy","entityConfig":"04f3e315ab242e17","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1529,"y":945,"wires":[[]]},{"id":"a5eec25bae6c5767","type":"inject","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Midnight Reset","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"00 00 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":680,"y":1000,"wires":[["7dafbfc0f5e2fa3f"]]},{"id":"7dafbfc0f5e2fa3f","type":"function","z":"e3f30e09f01c979f","g":"5b9a39c4104bea1d","name":"Energy Daily Reset","func":"// Setzt die kumulierte Energie auf null\nflow.set('energy', 0);\n\n// Rückgabe der neuen Energie (0) als Payload\nmsg.payload = 0;\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1270,"y":1000,"wires":[["fe61e2ce9210577b"]]},{"id":"61c89149.6b842","type":"server","name":"Home Assistant","addon":true},{"id":"e5aa6fef707c2d73","type":"ha-entity-config","server":"61c89149.6b842","deviceConfig":"","name":"sensor.HeatTransferRatio","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"sensor.HeatTransferRatio"},{"property":"icon","value":"mdi:label-percent-outline"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"power_factor"},{"property":"unit_of_measurement","value":"%"},{"property":"state_class","value":"measurement"}],"resend":true,"debugEnabled":false},{"id":"ce391c35b6eb8d0d","type":"ha-entity-config","server":"61c89149.6b842","deviceConfig":"","name":"sensor.OvenPowerTransfer","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"sensor.OvenPowerTransfer"},{"property":"icon","value":"mdi:gas-burner"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"power"},{"property":"unit_of_measurement","value":"W"},{"property":"state_class","value":"measurement"}],"resend":false,"debugEnabled":false},{"id":"04f3e315ab242e17","type":"ha-entity-config","server":"61c89149.6b842","deviceConfig":"","name":"sensor.OvenEnergy","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"sensor.OvenEnergy"},{"property":"icon","value":"mdi:Campfire"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":"energy"},{"property":"unit_of_measurement","value":"kWh"},{"property":"state_class","value":"total_increasing"}],"resend":true,"debugEnabled":false}]