[ { "id": "cf255672ab90a22f", "type": "tab", "label": "Battery heater", "disabled": false, "info": "", "env": [] }, { "id": "edd7c4cce6eb5861", "type": "victron-input-battery", "z": "cf255672ab90a22f", "service": "com.victronenergy.battery/512", "path": "/Dc/0/Temperature", "serviceObj": { "service": "com.victronenergy.battery/512", "name": "Cegasa battery" }, "pathObj": { "path": "/Dc/0/Temperature", "type": "float", "name": "Battery temperature (°C)" }, "name": "batt_temp", "onlyChanges": true, "roundValues": "0", "x": 80, "y": 200, "wires": [ [ "7e04d0fa828e9868" ] ] }, { "id": "e4786f6532b0e8d0", "type": "debug", "z": "cf255672ab90a22f", "name": "debug 1", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 740, "y": 40, "wires": [] }, { "id": "43f946d4d47ba3ec", "type": "victron-input-solarcharger", "z": "cf255672ab90a22f", "service": "com.victronenergy.solarcharger/273", "path": "/Yield/Power", "serviceObj": { "service": "com.victronenergy.solarcharger/273", "name": "SmartSolar MPPT VE.Can 250/100 rev2" }, "pathObj": { "path": "/Yield/Power", "type": "float", "name": "PV Power (W)" }, "name": "pv_power", "onlyChanges": true, "roundValues": "0", "x": 80, "y": 260, "wires": [ [ "7e04d0fa828e9868" ] ] }, { "id": "de555a35fee6404c", "type": "ui-switch", "z": "cf255672ab90a22f", "name": "heater_on", "label": "Calefacción", "group": "aa9cdf043b4ff6f3", "order": 1, "width": 0, "height": 0, "passthru": false, "decouple": false, "topic": "topic", "topicType": "msg", "style": "", "className": "", "layout": "row-spread", "clickableArea": "none", "onvalue": "true", "onvalueType": "bool", "onicon": "", "oncolor": "", "offvalue": "false", "offvalueType": "bool", "officon": "", "offcolor": "", "x": 940, "y": 160, "wires": [ [] ] }, { "id": "fb3c661bf8c01d98", "type": "shelly-gen2", "z": "cf255672ab90a22f", "hostname": "172.24.24.2", "description": "shelly", "mode": "callback", "verbose": false, "server": "04263f2d054cc2a1", "outputmode": "event", "uploadretryinterval": "5000", "pollinginterval": 5000, "pollstatus": false, "getstatusoncommand": false, "devicetype": "SNSW-001X16EU", "devicetypemustmatchexactly": false, "captureblutooth": false, "outputs": 1, "x": 490, "y": 520, "wires": [ [ "bd1f36a1d9afba8d" ] ] }, { "id": "7e04d0fa828e9868", "type": "delay", "z": "cf255672ab90a22f", "name": "", "pauseType": "timed", "timeout": "5", "timeoutUnits": "seconds", "rate": "1", "nbRateUnits": "5", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": true, "allowrate": false, "outputs": 1, "x": 310, "y": 160, "wires": [ [ "4f2f81e6c9c20a90" ] ] }, { "id": "8c3a3af1c81eaec6", "type": "victron-input-battery", "z": "cf255672ab90a22f", "service": "com.victronenergy.battery/512", "path": "/Dc/0/Power", "serviceObj": { "service": "com.victronenergy.battery/512", "name": "Cegasa battery" }, "pathObj": { "path": "/Dc/0/Power", "type": "float", "name": "Battery power (W)" }, "name": "batt_power", "onlyChanges": true, "roundValues": "0", "x": 80, "y": 140, "wires": [ [ "7e04d0fa828e9868" ] ] }, { "id": "bd1f36a1d9afba8d", "type": "function", "z": "cf255672ab90a22f", "name": "set_shelly_message", "func": "let name = msg.payload.name\nlet component = msg.payload.component\n\nif (name == \"temperature\"){\n msg.topic = component == \"temperature:100\" ? \"box_temp\" : \"room_temp\"\n msg.payload = msg.payload.info.tC\n}\nelse if (name == \"switch\"){\n msg.topic = \"relay\"\n msg.payload = msg.payload.info.state\n}\nelse {\n node.warn(\"Error parsing Shelly message\")\n node.warn(msg)\n return null\n}\n\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 280, "y": 360, "wires": [ [ "4f2f81e6c9c20a90", "0f85c811db6b90cb" ] ] }, { "id": "4f2f81e6c9c20a90", "type": "function", "z": "cf255672ab90a22f", "name": "heater_switch_manager", "func": "context.set(msg.topic, msg.payload)\n\nlet batt_temp = context.get(\"batt_temp\")\nlet batt_power = context.get(\"batt_power\")\nlet batt_soc = context.get(\"batt_soc\")\nlet box_temp = context.get(\"box_temp\")\nlet room_temp = context.get(\"room_temp\")\nlet pv_power = context.get(\"pv_power\")\nlet relay = context.get(\"relay\")\nlet force_heater = context.get(\"force_heater\")\n\nlet log = \"\"\nfor (const key of context.keys()) {\n log += key + \"=\" + context.get(key) + \" \"\n}\n//node.warn(log)\n\n// Si estamos iniciando y faltan datos apagar el radiador.\nif (batt_temp == undefined || batt_power == undefined || box_temp == undefined\n || room_temp == undefined || pv_power == undefined) {\n node.warn(\"INITIALIZING\")\n msg.payload = false\n return msg;\n}\n\n// Si la temperatura ambiente o de la batería es alta apagar el radiador.\nif (batt_temp > 20 || room_temp > 20) {\n msg.payload = false\n return msg;\n}\n\n// Si la temperatura del sarcofago es baja desmarcar que se ha llegado al límite.\nif (box_temp < 15) {\n context.set(\"box_temp_upper_limit_reached\", false)\n}\n// Si la temperatura del sarcofago es alta marcar que se ha llegado al límite.\nelse if (box_temp > 25) {\n context.set(\"box_temp_upper_limit_reached\", true)\n}\n\n// Si se ha llegado al límite superior de temperatura del sarcófago apagar el\n// radiador, hay que esperar a cruzar el límite inferior.\nif (context.get(\"box_temp_upper_limit_reached\")) {\n msg.payload = false\n return msg;\n}\n\n// Comprobar si se ha pedido explicitamente encender la calefacción.\nif (context.get(\"force_heater\")) {\n msg.payload = true\n return msg;\n}\n\n// Encender el radiador si la potencia de carga es alta teniendo en cuenta el SOC.\nif ((pv_power > 700 && batt_soc > 50) || (pv_power > 300 && batt_soc > 70) ||\n (pv_power > 200 && batt_soc > 90)) {\n msg.payload = true\n return msg;\n}\n\n// Encender el radiador si la potencia de carga está limitada por la temperatura\n// de la batería.\nif ((pv_power > 1200 && batt_temp < 8) || (pv_power > 2500 && batt_temp < 16)) {\n msg.payload = true\n return msg;\n}\n\n// Encender el radiador si la batería está fría y hay suficiente SOC.\nif ((batt_temp < 5 && batt_soc > 50) || (batt_temp < 6 && batt_soc > 60) ||\n (batt_temp < 8 && batt_soc > 70) || (batt_temp < 12 && batt_soc > 80) ||\n (batt_temp < 16 && batt_soc > 90)) {\n msg.payload = true\n return msg;\n}\n\n// En el resto de casos apagamos el radiador.\nmsg.payload = false\nreturn msg;\n", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 550, "y": 160, "wires": [ [ "cd1a8c477cfe992a", "e4786f6532b0e8d0" ] ] }, { "id": "5a77160b6a27db82", "type": "function", "z": "cf255672ab90a22f", "name": "switch_relay", "func": "let on = msg.payload\n\nmsg.payload = {\n method: \"Switch.Set\",\n parameters : {\n id : 0,\n on : on\n }\n};\nreturn msg;", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 970, "y": 380, "wires": [ [ "fb3c661bf8c01d98" ] ] }, { "id": "cd1a8c477cfe992a", "type": "rbe", "z": "cf255672ab90a22f", "name": "filter equal", "func": "rbe", "gap": "", "start": "", "inout": "out", "septopics": false, "property": "payload", "topi": "topic", "x": 770, "y": 160, "wires": [ [ "de555a35fee6404c", "5a77160b6a27db82", "2e458f61d504ee9b" ] ] }, { "id": "2e458f61d504ee9b", "type": "debug", "z": "cf255672ab90a22f", "name": "debug 2", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 940, "y": 100, "wires": [] }, { "id": "2c23d4c1a6fbb2c0", "type": "victron-input-battery", "z": "cf255672ab90a22f", "service": "com.victronenergy.battery/512", "path": "/Soc", "serviceObj": { "service": "com.victronenergy.battery/512", "name": "Cegasa battery" }, "pathObj": { "path": "/Soc", "type": "float", "name": "State of charge (%)" }, "name": "batt_soc", "onlyChanges": true, "roundValues": "0", "x": 80, "y": 80, "wires": [ [ "7e04d0fa828e9868" ] ] }, { "id": "0f85c811db6b90cb", "type": "switch", "z": "cf255672ab90a22f", "name": "", "property": "topic", "propertyType": "msg", "rules": [ { "t": "eq", "v": "box_temp", "vt": "str" }, { "t": "eq", "v": "room_temp", "vt": "str" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 530, "y": 360, "wires": [ [ "9593b9b734c4e4f9" ], [ "62d7f8dd71fa7b38" ] ] }, { "id": "9593b9b734c4e4f9", "type": "ui-text", "z": "cf255672ab90a22f", "group": "aa9cdf043b4ff6f3", "order": 3, "width": 0, "height": 0, "name": "box_temp", "label": "Sarcófago", "format": "{{msg.payload}}", "layout": "row-spread", "style": false, "font": "", "fontSize": 16, "color": "#717171", "wrapText": false, "className": "", "value": "payload", "valueType": "msg", "x": 680, "y": 340, "wires": [] }, { "id": "62d7f8dd71fa7b38", "type": "ui-text", "z": "cf255672ab90a22f", "group": "aa9cdf043b4ff6f3", "order": 4, "width": 0, "height": 0, "name": "room_text", "label": "Habitación", "format": "{{msg.payload}}", "layout": "row-spread", "style": false, "font": "", "fontSize": 16, "color": "#717171", "wrapText": false, "className": "", "value": "payload", "valueType": "msg", "x": 680, "y": 380, "wires": [] }, { "id": "91d7f7d3a52c6875", "type": "ui-switch", "z": "cf255672ab90a22f", "name": "force_heater", "label": "Forzar calefacción", "group": "aa9cdf043b4ff6f3", "order": 2, "width": 0, "height": 0, "passthru": false, "decouple": false, "topic": "force_heater", "topicType": "str", "style": "", "className": "", "layout": "row-spread", "clickableArea": "switch", "onvalue": "true", "onvalueType": "bool", "onicon": "", "oncolor": "", "offvalue": "false", "offvalueType": "bool", "officon": "", "offcolor": "", "x": 310, "y": 100, "wires": [ [ "4f2f81e6c9c20a90" ] ] }, { "id": "aa9cdf043b4ff6f3", "type": "ui-group", "name": "Group 1", "page": "545b3851d8568f59", "width": "6", "height": "1", "order": 1, "showTitle": false, "className": "", "visible": "true", "disabled": "false", "groupType": "default" }, { "id": "04263f2d054cc2a1", "type": "shelly-gen2-server", "port": "10001", "hostname": "unimatrix" }, { "id": "545b3851d8568f59", "type": "ui-page", "name": "Calefacción", "ui": "cf2bb7479e560f99", "path": "/heater", "icon": "home", "layout": "grid", "theme": "43a2d84f031e3dc7", "breakpoints": [ { "name": "Default", "px": "0", "cols": "3" }, { "name": "Tablet", "px": "576", "cols": "6" }, { "name": "Small Desktop", "px": "768", "cols": "9" }, { "name": "Desktop", "px": "1024", "cols": "12" } ], "order": 1, "className": "", "visible": "true", "disabled": "false" }, { "id": "cf2bb7479e560f99", "type": "ui-base", "name": "My Dashboard", "path": "/dashboard", "appIcon": "", "includeClientData": true, "acceptsClientConfig": [ "ui-notification", "ui-control" ], "showPathInSidebar": false, "headerContent": "page", "navigationStyle": "default", "titleBarStyle": "default", "showReconnectNotification": true, "notificationDisplayTime": 1, "showDisconnectNotification": true, "allowInstall": false }, { "id": "43a2d84f031e3dc7", "type": "ui-theme", "name": "Default Theme", "colors": { "surface": "#ffffff", "primary": "#0094CE", "bgPage": "#eeeeee", "groupBg": "#ffffff", "groupOutline": "#cccccc" }, "sizes": { "density": "default", "pagePadding": "12px", "groupGap": "12px", "groupBorderRadius": "4px", "widgetGap": "12px" } } ]