UNPKG

smart-nodes

Version:

Controls light, shutters and more. Includes common used logic and statistic nodes to control your home.

169 lines (132 loc) 5.51 kB
module.exports = function (RED) { "use strict"; function HeatingCurveNode(config) { const node = this; RED.nodes.createNode(node, config); // ################### // # Class constants # // ################### // ####################### // # Global help objects # // ####################### const smart_context = require("../persistence.js")(RED); const helper = require("../smart_helper.js"); // ##################### // # persistent values # // ##################### var node_settings = helper.cloneObject({ room_setpoint: config.room_setpoint, flow_min: config.flow_min, flow_max: config.flow_max, temperature_outside: 10, last_flow_temperature: null, config_change_date: config.config_change_date, }, smart_context.get(node.id, config.config_change_date)); // ################## // # Dynamic config # // ################## let slope = parseFloat(config.slope); let offset = parseFloat(config.offset); // ################## // # Runtime values # // ################## // ############### // # Node events # // ############### node.on("input", function (msg) { handleTopic(msg); sendResult(); setStatus(); smart_context.set(node.id, node_settings); }); node.on("close", function () { }); // ##################### // # Private functions # // ##################### // This is the main function which handles all topics that was received. let handleTopic = msg => { let real_topic = helper.getTopicName(msg.topic); switch (real_topic) { case "debug": helper.nodeDebug(node, { node_settings, slope, offset, }); break; case "room_setpoint": let new_setpoint = parseFloat(msg.payload); if (isNaN(new_setpoint) && !isFinite(new_setpoint)) { // helper.warn(this, "Invalid payload: " + msg.payload); return; } node_settings.room_setpoint = new_setpoint; break; case "temperature_outside": let new_temp = parseFloat(msg.payload); if (isNaN(new_temp) && !isFinite(new_temp)) { // helper.warn(this, "Invalid payload: " + msg.payload); return; } node_settings.temperature_outside = new_temp; break; case "flow_min": let new_flow_min = parseFloat(msg.payload); if (isNaN(new_flow_min) && !isFinite(new_flow_min)) { // helper.warn(this, "Invalid payload: " + msg.payload); return; } node_settings.flow_min = new_flow_min; break; case "flow_max": let new_flow_max = parseFloat(msg.payload); if (isNaN(new_flow_max) && !isFinite(new_flow_max)) { // helper.warn(this, "Invalid payload: " + msg.payload); return; } node_settings.flow_max = new_flow_max; break; default: node.error("Invalid topic: " + real_topic); return; } } let sendResult = () => { // Formula used was found here: // https://community.viessmann.de/t5/Gas/Mathematische-Formel-fuer-Vorlauftemperatur-aus-den-vier/td-p/68843 let dar = node_settings.temperature_outside - node_settings.room_setpoint; node_settings.last_flow_temperature = node_settings.room_setpoint + offset - slope * dar * (1.4347 + 0.021 * dar + 247.9 * Math.pow(10, -6) * Math.pow(dar, 2)); // console.log({ // set: node_settings.room_setpoint, // offset, // slope, // dar, // flow: node_settings.last_flow_temperature // }); // Check borders node_settings.last_flow_temperature = Math.min(Math.max(node_settings.last_flow_temperature, node_settings.flow_min), node_settings.flow_max); smart_context.set(node.id, node_settings); node.send({ payload: node_settings.last_flow_temperature }); } let setStatus = () => { node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Out: " + node_settings.temperature_outside?.toFixed(1) + "°C, Flow: " + node_settings.last_flow_temperature?.toFixed(1) + "°C" }); } if (node_settings.last_flow_temperature !== null) setTimeout(sendResult, 10000); setStatus(); } RED.nodes.registerType("smart_heating-curve", HeatingCurveNode); }