Now,
here’s the entire setup for Node-Red, based on a 3-way mixer with temperature adaptation to have the oven water inlet to be always above 55°C to prevent soot.
For the ease of calculation, all variables were converted to global ones plus, sensors were set to display core values in HASSio:
`
> [{"id":"49ac2d3a2c8cd6dc","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"],"x":34,"y":699,"w":1352,"h":262},{"id":"f7101a878906ff13","type":"poll-state","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","name":"Pump-State","server":"61c89149.6b842","version":3,"exposeAsEntityConfig":"","updateInterval":"10","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":740,"wires":[["f548f031284cf8e4"]]},{"id":"f548f031284cf8e4","type":"function","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","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":740,"wires":[[]]},{"id":"8d68417fa0d402de","type":"function","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","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":920,"y":860,"wires":[["49e1e0eaae5987a5"]]},{"id":"08ae38f779cf334d","type":"poll-state","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","name":"Ofen Einspeisung","server":"61c89149.6b842","version":3,"exposeAsEntityConfig":"","updateInterval":"10","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":800,"wires":[["5d35d585a01c8fbd"]]},{"id":"99819d57d53cae5d","type":"poll-state","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","name":"Speicher Vorlauf","server":"61c89149.6b842","version":3,"exposeAsEntityConfig":"","updateInterval":"10","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":860,"wires":[["0f4bc48f32920fa2"]]},{"id":"5d35d585a01c8fbd","type":"function","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","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":800,"wires":[[]]},{"id":"0f4bc48f32920fa2","type":"function","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","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":860,"wires":[[]]},{"id":"30a68a60b4b5a624","type":"inject","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"10","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":670,"y":840,"wires":[["8d68417fa0d402de","7e35282b10bace08"]]},{"id":"fdc068a15fd7aeac","type":"poll-state","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","name":"Ofen Vorlauf","server":"61c89149.6b842","version":3,"exposeAsEntityConfig":"","updateInterval":"10","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":920,"wires":[["49c447c109d24801"]]},{"id":"49c447c109d24801","type":"function","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","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":920,"wires":[[]]},{"id":"7e35282b10bace08","type":"function","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","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":940,"y":800,"wires":[["87559157a30aa38d"]]},{"id":"87559157a30aa38d","type":"ha-sensor","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","name":"sensor.heatTransferRatio","entityConfig":"e5aa6fef707c2d73","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1230,"y":800,"wires":[[]]},{"id":"49e1e0eaae5987a5","type":"ha-sensor","z":"e3f30e09f01c979f","g":"49ac2d3a2c8cd6dc","name":"sensor.OvenPowerTransfer","entityConfig":"ce391c35b6eb8d0d","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1240,"y":860,"wires":[[]]},{"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}]
`