[ { "id": "8674301a91924f57", "type": "tab", "label": "Enphase David", "disabled": false, "info": "", "env": [] }, { "id": "a92538baa3ea546d", "type": "tab", "label": "enphaseSensor", "disabled": false, "info": "", "env": [] }, { "id": "a85d09f25bda04f5", "type": "group", "z": "8674301a91924f57", "name": "Login to Envoy with token to obtain sessionId", "style": { "fill": "#ffdf7f", "label": true }, "nodes": [ "637cab856f33d8a6", "47d0bdc56d74a9f5", "cb318edd3628d9eb", "6de1f1152b56f610" ], "x": 54, "y": 559, "w": 852, "h": 82 }, { "id": "aa42cd7bb43799d4", "type": "group", "z": "8674301a91924f57", "name": "Obtain token from Enphase", "style": { "fill": "#ffbfbf", "label": true }, "nodes": [ "2c74b1c938385a3f", "be1fc49a72a10553", "a029c8150379567e", "0cd520b3a57daa4a", "f5e136bf70c880b3", "28848db58b91d335", "b9d66d16ccb69bb7", "bde18f862dbf8650", "75fad209f527e36f", "0bdd7b567a5820db", "dd7f4944785553ce", "7219d464e019ab81", "5e2f7fb4a9d0f206" ], "x": 54, "y": 753, "w": 2752, "h": 168 }, { "id": "41012b984e4c27c8", "type": "group", "z": "8674301a91924f57", "name": "Read Envoy using sessionId", "style": { "fill": "#c8e7a7", "label": true }, "nodes": [ "fd4e65d7a26e9958", "11f83b474b6c30b6", "c25dbda5cc1d79b1", "9c1a4e0977151879", "9de0237a4ca885b9", "7498c37d1b992a22", "47fa4dbd2ce2806a", "7bed715d9e17a707", "37df5d7b48523463", "164d17143782238f", "fb4a167c6e2c7634", "bc5c4edfb4fc4c35", "1705dc9cb63aa88e", "cc8d165658c3181e" ], "x": 94, "y": 119, "w": 2732, "h": 402 }, { "id": "75fad209f527e36f", "type": "group", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "", "style": { "fill": "#ffff00", "label": true }, "nodes": [ "fd1f5956ad68734f" ], "x": 854, "y": 779, "w": 232, "h": 82 }, { "id": "4492d51daa637ab5", "type": "mqtt-broker", "name": "Local (.50)", "broker": "192.168.1.50", "port": "1883", "clientid": "", "autoConnect": true, "usetls": false, "protocolVersion": "4", "keepalive": "60", "cleansession": true, "autoUnsubscribe": true, "birthTopic": "", "birthQos": "0", "birthPayload": "", "birthMsg": {}, "closeTopic": "", "closeQos": "0", "closePayload": "", "closeMsg": {}, "willTopic": "", "willQos": "0", "willPayload": "", "willMsg": {}, "userProps": "", "sessionExpiry": "" }, { "id": "8c4ebb9b0f21e1e7", "type": "mqtt-broker", "name": "PiMQTT_21", "broker": "192.168.1.21", "port": 1883, "clientid": "", "autoConnect": true, "usetls": false, "protocolVersion": 4, "keepalive": 60, "cleansession": true, "autoUnsubscribe": true, "birthTopic": "", "birthQos": "0", "birthRetain": "false", "birthPayload": "", "birthMsg": {}, "closeTopic": "", "closeQos": "0", "closeRetain": "false", "closePayload": "", "closeMsg": {}, "willTopic": "", "willQos": "0", "willRetain": "false", "willPayload": "", "willMsg": {}, "userProps": "", "sessionExpiry": "" }, { "id": "413771b8cd5d14dc", "type": "server", "name": "Home Assistant", "version": 5, "addon": true, "rejectUnauthorizedCerts": true, "ha_boolean": "y|yes|true|on|home|open", "connectionDelay": true, "cacheJson": true, "heartbeat": true, "heartbeatInterval": "15", "areaSelector": "friendlyName", "deviceSelector": "friendlyName", "entitySelector": "friendlyName", "statusSeparator": ": ", "statusYear": "hidden", "statusMonth": "short", "statusDay": "numeric", "statusHourCycle": "default", "statusTimeFormat": "h:m", "enableGlobalContextStore": false }, { "id": "d7c79fc7a3bf35d1", "type": "ha-device-config", "name": "Enphase", "hwVersion": "", "manufacturer": "Node-RED", "model": "", "swVersion": "" }, { "id": "58bbafb0758a7bcc", "type": "ha-entity-config", "server": "413771b8cd5d14dc", "deviceConfig": "d7c79fc7a3bf35d1", "name": "Enphase Power Production Phase A", "version": 6, "entityType": "sensor", "haConfig": [ { "property": "name", "value": "Enphase Power Production Phase A" }, { "property": "icon", "value": "" }, { "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": "9cc354ff17163508", "type": "ha-entity-config", "server": "413771b8cd5d14dc", "deviceConfig": "d7c79fc7a3bf35d1", "name": "battery_state_powerXYZ", "version": 6, "entityType": "sensor", "haConfig": [ { "property": "name", "value": "xyz" }, { "property": "icon", "value": "" }, { "property": "entity_picture", "value": "" }, { "property": "entity_category", "value": "" }, { "property": "device_class", "value": "" }, { "property": "unit_of_measurement", "value": "" }, { "property": "state_class", "value": "" } ], "resend": false, "debugEnabled": false }, { "id": "10b97d6ea19edeb0", "type": "ha-entity-config", "server": "413771b8cd5d14dc", "deviceConfig": "d7c79fc7a3bf35d1", "name": "battPower", "version": 6, "entityType": "sensor", "haConfig": [ { "property": "name", "value": "battPower" }, { "property": "icon", "value": "" }, { "property": "entity_picture", "value": "" }, { "property": "entity_category", "value": "" }, { "property": "device_class", "value": "" }, { "property": "unit_of_measurement", "value": "" }, { "property": "state_class", "value": "" } ], "resend": false, "debugEnabled": false }, { "id": "cd802eb32211d47d", "type": "ha-entity-config", "server": "413771b8cd5d14dc", "deviceConfig": "d7c79fc7a3bf35d1", "name": "enphase_solar_generated_power", "version": 6, "entityType": "sensor", "haConfig": [ { "property": "name", "value": "enphase_solar_generated_power" }, { "property": "icon", "value": "" }, { "property": "entity_picture", "value": "" }, { "property": "entity_category", "value": "" }, { "property": "device_class", "value": "" }, { "property": "unit_of_measurement", "value": "W" }, { "property": "state_class", "value": "" } ], "resend": false, "debugEnabled": false }, { "id": "99ef028a56f134d5", "type": "ha-entity-config", "server": "413771b8cd5d14dc", "deviceConfig": "d7c79fc7a3bf35d1", "name": "enphase_grid_state_power", "version": 6, "entityType": "sensor", "haConfig": [ { "property": "name", "value": "enphase_grid_state_power" }, { "property": "icon", "value": "" }, { "property": "entity_picture", "value": "" }, { "property": "entity_category", "value": "" }, { "property": "device_class", "value": "" }, { "property": "unit_of_measurement", "value": "W" }, { "property": "state_class", "value": "" } ], "resend": false, "debugEnabled": false }, { "id": "5e3e1bc3f3247044", "type": "ha-entity-config", "server": "413771b8cd5d14dc", "deviceConfig": "d7c79fc7a3bf35d1", "name": "enphase_battery_state_power", "version": 6, "entityType": "sensor", "haConfig": [ { "property": "name", "value": "enphase_battery_state_power" }, { "property": "icon", "value": "" }, { "property": "entity_picture", "value": "" }, { "property": "entity_category", "value": "" }, { "property": "device_class", "value": "" }, { "property": "unit_of_measurement", "value": "W" }, { "property": "state_class", "value": "" } ], "resend": false, "debugEnabled": false }, { "id": "ed78fa1e3bbee374", "type": "ha-entity-config", "server": "413771b8cd5d14dc", "deviceConfig": "d7c79fc7a3bf35d1", "name": "enphase_battery_soc", "version": 6, "entityType": "sensor", "haConfig": [ { "property": "name", "value": "enphase_battery_soc" }, { "property": "icon", "value": "" }, { "property": "entity_picture", "value": "" }, { "property": "entity_category", "value": "" }, { "property": "device_class", "value": "" }, { "property": "unit_of_measurement", "value": "%" }, { "property": "state_class", "value": "" } ], "resend": false, "debugEnabled": false }, { "id": "d292a7b0a0eacf0b", "type": "comment", "z": "8674301a91924f57", "name": "Connection to envoy failed. Request new sessionId", "info": "", "x": 350, "y": 420, "wires": [] }, { "id": "bd44f6e6b96d2aee", "type": "comment", "z": "8674301a91924f57", "name": "Feed the received sessionId back", "info": "", "x": 790, "y": 420, "wires": [] }, { "id": "8a8fefcd6db3e1ac", "type": "comment", "z": "8674301a91924f57", "name": "Login to Envoy using token failed. Request new token from Enphase", "info": "", "x": 340, "y": 700, "wires": [] }, { "id": "8c250171f5698175", "type": "comment", "z": "8674301a91924f57", "name": "Feed the received token back", "info": "", "x": 1080, "y": 600, "wires": [] }, { "id": "db84e7cfdc0a280b", "type": "comment", "z": "8674301a91924f57", "name": "Source 1", "info": "https://github.com/H4nsie/EnphaseEnvoy/blob/main/plugin.py", "x": 240, "y": 100, "wires": [] }, { "id": "fae66073d1b32701", "type": "comment", "z": "8674301a91924f57", "name": "Source 2", "info": "https://support.enphase.com/s/question/0D53m00008ketz6CAA/i-have-a-new-enphase-system-and-reading-my-envoy-using-the-local-api-this-goes-well-for-one-endpoint-but-not-for-another?t=1678709630042\n\nBased on post:\nKneib_3226\nEdited February 24, 2023 at 10:35 AM", "x": 380, "y": 100, "wires": [] }, { "id": "e714775903d60ebf", "type": "function", "z": "8674301a91924f57", "name": "getToken", "func": "// flow.set('Enphase_local_token',msg.payload);\n\nvar myToken = flow.get(\"Enphase_local_token\");\nglobal.set('Enphase_global_token', myToken);\n\nmsg.Token = myToken;\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 700, "y": 140, "wires": [ [ "873288d8ed63a592" ] ] }, { "id": "1f8f7034d0e3ecbf", "type": "inject", "z": "8674301a91924f57", "name": "get", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": true, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 570, "y": 140, "wires": [ [ "e714775903d60ebf" ] ] }, { "id": "873288d8ed63a592", "type": "debug", "z": "8674301a91924f57", "name": "token", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 830, "y": 140, "wires": [] }, { "id": "dd68e881b3dc0ce3", "type": "comment", "z": "8674301a91924f57", "name": "Source 0", "info": "https://github.com/Maarten234/Enphase-Envoy-D7.0.X-node-red", "x": 100, "y": 100, "wires": [] }, { "id": "637cab856f33d8a6", "type": "function", "z": "8674301a91924f57", "g": "a85d09f25bda04f5", "name": "set http headers", "func": "let token = msg.token||flow.get('Enphase_local_token');\n\nmsg.headers={\n \"Accept\": \"application/json\",\n \"content-type\": \"application/x-www-form-urlencoded\",\n \"Cache-Control\": \"no-cache\",\n \"Authorization\": \"Bearer \" + token\n};\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 160, "y": 600, "wires": [ [ "47d0bdc56d74a9f5" ] ] }, { "id": "47d0bdc56d74a9f5", "type": "http request", "z": "8674301a91924f57", "g": "a85d09f25bda04f5", "name": "auth/check_jwt", "method": "GET", "ret": "txt", "paytoqs": "ignore", "url": "https://{{envoyaddress}}/auth/check_jwt", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 360, "y": 600, "wires": [ [ "cb318edd3628d9eb" ] ], "info": "Envoy returns a sessionId when the Bearer token is accepted. The sessionId can be used to make API calls" }, { "id": "cb318edd3628d9eb", "type": "switch", "z": "8674301a91924f57", "g": "a85d09f25bda04f5", "name": "HTTP status code=200", "property": "statusCode", "propertyType": "msg", "rules": [ { "t": "eq", "v": "200", "vt": "str" }, { "t": "else" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 570, "y": 600, "wires": [ [ "6de1f1152b56f610" ], [ "7219d464e019ab81" ] ], "outputLabels": [ "sessionID obtained", "error" ], "info": "When the envoy accepted the token it returns HTTP status code 200" }, { "id": "6de1f1152b56f610", "type": "function", "z": "8674301a91924f57", "g": "a85d09f25bda04f5", "name": "save sessionId", "func": "// Save sessionId\nflow.set('sessionId',msg.responseCookies.sessionId.value);\nglobal.set('sessionId', msg.responseCookies.sessionId.value);\n\n// Set node status to show date time last called into action\nlet d=new Date();\nnode.status({text:d.toISOString().split('T')[0]+\" \"+d.toTimeString().split(\" \")[0]});\n\n// continu flow\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 800, "y": 600, "wires": [ [ "fd4e65d7a26e9958" ] ] }, { "id": "2c74b1c938385a3f", "type": "http request", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "info.xml", "method": "GET", "ret": "txt", "paytoqs": "ignore", "url": "https://{{envoyaddress}}/info.xml", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 420, "y": 820, "wires": [ [ "a029c8150379567e" ] ] }, { "id": "be1fc49a72a10553", "type": "xml", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "", "property": "payload", "attr": "", "chr": "", "x": 790, "y": 820, "wires": [ [ "fd1f5956ad68734f" ] ] }, { "id": "a029c8150379567e", "type": "switch", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "HTTP status code=200", "property": "statusCode", "propertyType": "msg", "rules": [ { "t": "eq", "v": "200", "vt": "str" }, { "t": "else" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 610, "y": 820, "wires": [ [ "be1fc49a72a10553" ], [ "5e2f7fb4a9d0f206" ] ], "outputLabels": [ "success", "error" ], "info": "When the envoy accepted the token it returns HTTP status code 200" }, { "id": "0cd520b3a57daa4a", "type": "function", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "set msg.serialnumber", "func": "msg.serialnumber=msg.payload.envoy_info.device[0].sn[0];\nmsg.headers={\n \"Accept\": \"application/json\",\n \"content-type\": \"application/x-www-form-urlencoded\",\n \"Cache-Control\": \"no-cache\"\n};\nmsg.payload={\n \"user[email]\": msg.username,\n \"user[password]\": msg.password\n}\n\n//remove property password\ndelete msg.password;\nmsg.rejectUnauthorized=true;\n\n// Set node status to show date time last called into action\nlet d=new Date();\nnode.status({text:d.toISOString().split('T')[0]+\" \"+d.toTimeString().split(\" \")[0]});\n\n//Continu flow\nreturn msg;\n", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1200, "y": 820, "wires": [ [ "f5e136bf70c880b3" ] ] }, { "id": "f5e136bf70c880b3", "type": "http request", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "enlighten.enphaseenergy.com/login/login.json", "method": "POST", "ret": "obj", "paytoqs": "ignore", "url": "https://enlighten.enphaseenergy.com/login/login.json", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 1500, "y": 820, "wires": [ [ "0bdd7b567a5820db" ] ] }, { "id": "28848db58b91d335", "type": "function", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "set payload", "func": "msg.payload={\n session_id: msg.payload.session_id,\n serial_num: msg.serialnumber,\n username: msg.username\n}\ndelete msg.username;\n\n// Set node status to show date time last called into action\nlet d=new Date();\nnode.status({text:d.toISOString().split('T')[0]+\" \"+d.toTimeString().split(\" \")[0]});\n\n//continu flow\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2010, "y": 820, "wires": [ [ "b9d66d16ccb69bb7" ] ] }, { "id": "b9d66d16ccb69bb7", "type": "http request", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "entrez.enphaseenergy.com/tokens", "method": "POST", "ret": "txt", "paytoqs": "ignore", "url": "https://entrez.enphaseenergy.com/tokens", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 2240, "y": 820, "wires": [ [ "dd7f4944785553ce" ] ] }, { "id": "bde18f862dbf8650", "type": "function", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "Save token", "func": "flow.set('Enphase_local_token',msg.payload);\nglobal.set('Enphase_global_token', msg.payload);\nmsg.token=msg.payload;\nmsg.rejectUnauthorized=false;\n\n// Set node status to show date time last called into action\nlet d=new Date();\nnode.status({text:d.toISOString().split('T')[0]+\" \"+d.toTimeString().split(\" \")[0]});\n\n//Continu flow\nreturn msg;\n", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2710, "y": 820, "wires": [ [ "637cab856f33d8a6" ] ] }, { "id": "fd1f5956ad68734f", "type": "change", "z": "8674301a91924f57", "g": "75fad209f527e36f", "name": "Login credentials", "rules": [ { "t": "set", "p": "username", "pt": "msg", "to": "rainer@langheiter.at", "tot": "str" }, { "t": "set", "p": "password", "pt": "msg", "to": "HwHye,.13", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 970, "y": 820, "wires": [ [ "0cd520b3a57daa4a" ] ] }, { "id": "0bdd7b567a5820db", "type": "switch", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "HTTP status code=200", "property": "statusCode", "propertyType": "msg", "rules": [ { "t": "eq", "v": "200", "vt": "str" }, { "t": "else" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 1810, "y": 820, "wires": [ [ "28848db58b91d335" ], [ "5e2f7fb4a9d0f206" ] ], "outputLabels": [ "success", "error" ], "info": "When the envoy accepted the token it returns HTTP status code 200" }, { "id": "dd7f4944785553ce", "type": "switch", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "name": "HTTP status code=200", "property": "statusCode", "propertyType": "msg", "rules": [ { "t": "eq", "v": "200", "vt": "str" }, { "t": "else" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 2510, "y": 820, "wires": [ [ "bde18f862dbf8650" ], [ "5e2f7fb4a9d0f206" ] ], "outputLabels": [ "success", "error" ], "info": "When the envoy accepted the token it returns HTTP status code 200" }, { "id": "fd4e65d7a26e9958", "type": "function", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "set parameters HTTP request", "func": "msg.headers={\n Accept: \"application/json\",\n \"content-type\": \"application/x-www-form-urlencoded\",\n \"Cache-Control\": 'no-cache'\n};\nmsg.cookies={\"sessionId\": flow.get('sessionId')||0};\n\n// rejectUnauthorized:\n// If set to false, allows requests to be made to https sites that use self signed certificates.\n// An alternative is to set the following in the HTTP request node as is done in the \"auth/check_jwt\" HTTP request node:\n// Check \"Enable secure (SSL/TLS) connection\" and create an TLS configuration node with all checkboxes unchecked\nmsg.rejectUnauthorized=false; \n \nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 670, "y": 220, "wires": [ [ "11f83b474b6c30b6" ] ] }, { "id": "11f83b474b6c30b6", "type": "http request", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "api/v1/production/inverters", "method": "GET", "ret": "obj", "paytoqs": "ignore", "url": "https://{{envoyaddress}}/api/v1/production/inverters", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 960, "y": 220, "wires": [ [ "9c1a4e0977151879" ] ] }, { "id": "c25dbda5cc1d79b1", "type": "inject", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "Envoy address", "props": [ { "p": "envoyaddress", "v": "192.168.1.78", "vt": "str" } ], "repeat": "3600", "crontab": "", "once": true, "onceDelay": 0.1, "topic": "", "x": 220, "y": 160, "wires": [ [ "fd4e65d7a26e9958" ] ] }, { "id": "9c1a4e0977151879", "type": "switch", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "HTTP status code=200", "property": "statusCode", "propertyType": "msg", "rules": [ { "t": "eq", "v": "200", "vt": "str" }, { "t": "else" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 1240, "y": 220, "wires": [ [ "9de0237a4ca885b9" ], [ "637cab856f33d8a6" ] ], "outputLabels": [ "succes", "error" ], "info": "When the envoy accepted the token it returns HTTP status code 200" }, { "id": "7498c37d1b992a22", "type": "http request", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "/ivp/meters/readings", "method": "GET", "ret": "obj", "paytoqs": "ignore", "url": "http://{{envoyaddress}}/ivp/meters/readings", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 1840, "y": 280, "wires": [ [ "47fa4dbd2ce2806a" ] ] }, { "id": "47fa4dbd2ce2806a", "type": "switch", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "HTTP status code=200", "property": "statusCode", "propertyType": "msg", "rules": [ { "t": "eq", "v": "200", "vt": "str" }, { "t": "else" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 2080, "y": 280, "wires": [ [ "9de0237a4ca885b9", "7bed715d9e17a707", "fb4a167c6e2c7634", "784549fe319731b5" ], [ "637cab856f33d8a6" ] ], "outputLabels": [ "succes", "error" ], "info": "When the envoy accepted the token it returns HTTP status code 200" }, { "id": "37df5d7b48523463", "type": "debug", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "debug ep readings", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 2690, "y": 220, "wires": [] }, { "id": "7bed715d9e17a707", "type": "function", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "Extract Data for HomeAssistant", "func": "const event = msg.payload;\n\nfunction getPower(data) {\n return Math.round(data['activePower']);\n}\n\nfunction getStats(reading, toZero = 0) {\n let total = getPower(reading);\n\n const powers = reading.channels.map(getPower)\n .map((p) => {\n if (p > 0 && p < toZero) {\n total -= p;\n return 0;\n }\n return p;\n });\n\n return {\n total,\n a: powers[0],\n b: powers[1],\n c: powers[2],\n }\n}\n\nconst stats = {\n production: getStats(event[0], 4),\n totalConsumption: getStats(event[1]),\n}\nmsg.payload = stats;\n\nreturn msg;", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2390, "y": 280, "wires": [ [ "37df5d7b48523463", "164d17143782238f", "cc8d165658c3181e" ] ] }, { "id": "164d17143782238f", "type": "mqtt out", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "", "topic": "enphase/stream", "qos": "0", "retain": "false", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "8c4ebb9b0f21e1e7", "x": 2680, "y": 280, "wires": [] }, { "id": "fb4a167c6e2c7634", "type": "debug", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "debug ep raw readings", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 2360, "y": 220, "wires": [] }, { "id": "784549fe319731b5", "type": "function", "z": "8674301a91924f57", "name": "Extract Data for Victron", "func": "const event = msg.payload;\n\nfunction getData(phase) {\n return {\n power: phase['activePower'],\n voltage: phase['voltage'],\n current: phase['current'],\n frequency: phase['freq'],\n }\n}\n\nfunction getStats(reading, toZero = 0) {\n const total = getData(reading);\n\n const channels = reading.channels.map(getData);\n\n for (const c of channels) {\n if (c.power > 0 && c.power < toZero) {\n total.power -= c.power;\n c.power = 0;\n }\n }\n\n return {\n ...total,\n L1: channels[0],\n L2: channels[1],\n L3: channels[2],\n }\n}\n\nconst stats = {\n pv: getStats(event[0], 4),\n grid: getStats(event[1]),\n}\nmsg.payload = stats;\nmsg.topic = 'enphase';\n\nreturn msg;", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2370, "y": 360, "wires": [ [ "edc2aa348bb36541" ] ] }, { "id": "b997234486729366", "type": "debug", "z": "8674301a91924f57", "name": "debug victron data", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 2690, "y": 480, "wires": [] }, { "id": "e5bc476007eeba26", "type": "mqtt out", "z": "8674301a91924f57", "name": "", "topic": "enphase/victron", "qos": "0", "retain": "false", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "4492d51daa637ab5", "x": 2680, "y": 420, "wires": [] }, { "id": "bc5c4edfb4fc4c35", "type": "mqtt in", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "Solar Garage (Shelly)", "topic": "power-solar-garage/status/switch:0", "qos": "2", "datatype": "json", "broker": "4492d51daa637ab5", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 1920, "y": 420, "wires": [ [ "60970cdbe7fa0e6e" ] ] }, { "id": "edc2aa348bb36541", "type": "join", "z": "8674301a91924f57", "name": "", "mode": "custom", "build": "object", "property": "payload", "propertyType": "msg", "key": "topic", "joiner": "\\n", "joinerType": "str", "accumulate": true, "timeout": "", "count": "1", "reduceRight": false, "reduceExp": "", "reduceInit": "", "reduceInitType": "", "reduceFixup": "", "x": 2310, "y": 420, "wires": [ [ "1705dc9cb63aa88e" ] ] }, { "id": "60970cdbe7fa0e6e", "type": "function", "z": "8674301a91924f57", "name": "Garage Data", "func": "const event = msg.payload;\n\n// {\"id\":0, \"source\":\"WS_in\", \"output\":true, \"apower\":338.5, \"voltage\":232.0, \"current\":1.475, \"aenergy\":{\"total\":44.131,\"by_minute\":[5658.624,5727.318,5789.183],\"minute_ts\":1728224400},\"temperature\":{\"tC\":41.5, \"tF\":106.6}}\n\nmsg.topic = 'garage';\nmsg.payload = event['apower'];\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2130, "y": 420, "wires": [ [ "edc2aa348bb36541" ] ] }, { "id": "1705dc9cb63aa88e", "type": "function", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "Combine Enphase and Garage", "func": "const event = msg.payload;\n\n// {\"id\":0, \"source\":\"WS_in\", \"output\":true, \"apower\":338.5, \"voltage\":232.0, \"current\":1.475, \"aenergy\":{\"total\":44.131,\"by_minute\":[5658.624,5727.318,5789.183],\"minute_ts\":1728224400},\"temperature\":{\"tC\":41.5, \"tF\":106.6}}\n\nmsg.payload = {\n ...event.enphase\n}\nif (msg.payload?.pv?.L2?.power != null && event.garage != null) {\n msg.payload['pv']['power'] = msg.payload['pv']['power'] + event.garage;\n msg.payload['pv']['L2']['power'] = msg.payload['pv']['L2']['power'] + event.garage;\n}\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 2410, "y": 480, "wires": [ [ "e5bc476007eeba26", "b997234486729366" ] ] }, { "id": "9de0237a4ca885b9", "type": "rate-limiter", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "delay_action": "ratelimit", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "drop_select": "queue", "addcurrentcount": false, "name": "", "outputs": 1, "buffer_size": "1", "buffer_drop": "buffer_drop_old", "emit_msg_2nd": false, "control_topic": "", "version": 0.0018, "x": 1560, "y": 220, "wires": [ [ "7498c37d1b992a22" ] ] }, { "id": "7219d464e019ab81", "type": "rate-limiter", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "delay_action": "ratelimit", "rate": "1", "nbRateUnits": "1", "rateUnits": "minute", "drop_select": "queue", "addcurrentcount": false, "name": "", "outputs": 1, "buffer_size": "1", "buffer_drop": "buffer_drop_old", "emit_msg_2nd": false, "control_topic": "", "version": 0.0018, "x": 200, "y": 820, "wires": [ [ "2c74b1c938385a3f" ] ] }, { "id": "5e2f7fb4a9d0f206", "type": "rate-limiter", "z": "8674301a91924f57", "g": "aa42cd7bb43799d4", "delay_action": "ratelimit", "rate": "1", "nbRateUnits": "10", "rateUnits": "minute", "drop_select": "queue", "addcurrentcount": false, "name": "", "outputs": 1, "buffer_size": "1", "buffer_drop": "buffer_drop_old", "emit_msg_2nd": false, "control_topic": "", "version": 0.0018, "x": 210, "y": 880, "wires": [ [ "2c74b1c938385a3f" ] ] }, { "id": "cc8d165658c3181e", "type": "link out", "z": "8674301a91924f57", "g": "41012b984e4c27c8", "name": "data-HA", "mode": "link", "links": [ "7d76789f9b8cfe99" ], "x": 2615, "y": 340, "wires": [] }, { "id": "7d76789f9b8cfe99", "type": "link in", "z": "a92538baa3ea546d", "name": "data-HA in", "links": [ "cc8d165658c3181e" ], "x": 175, "y": 80, "wires": [ [ "1d5ec3294e3de98e", "39946e3d2e542cdf", "4029b6f5072debfb" ] ] }, { "id": "1d5ec3294e3de98e", "type": "debug", "z": "a92538baa3ea546d", "name": "debug 2", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 360, "y": 40, "wires": [] }, { "id": "81ba1254baed3fd2", "type": "ha-sensor", "z": "a92538baa3ea546d", "name": "enphase_battery_state_power", "entityConfig": "5e3e1bc3f3247044", "version": 0, "state": "payload.power", "stateType": "msg", "attributes": [], "inputOverride": "allow", "outputProperties": [], "x": 450, "y": 280, "wires": [ [] ] }, { "id": "d4c1f853894f75d7", "type": "mqtt in", "z": "a92538baa3ea546d", "name": "", "topic": "victron/battery", "qos": "2", "datatype": "auto-detect", "broker": "8c4ebb9b0f21e1e7", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 210, "y": 280, "wires": [ [ "a9d004b046785ac1", "81ba1254baed3fd2", "402249fad23506cb" ] ] }, { "id": "a9d004b046785ac1", "type": "debug", "z": "a92538baa3ea546d", "name": "debug 4", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 400, "y": 340, "wires": [] }, { "id": "39946e3d2e542cdf", "type": "ha-sensor", "z": "a92538baa3ea546d", "name": "enphase_grid_state_power", "entityConfig": "99ef028a56f134d5", "version": 0, "state": "payload.totalConsumption.total", "stateType": "msg", "attributes": [], "inputOverride": "allow", "outputProperties": [], "x": 420, "y": 80, "wires": [ [] ] }, { "id": "4029b6f5072debfb", "type": "ha-sensor", "z": "a92538baa3ea546d", "name": "enphase_solar_generated_power", "entityConfig": "cd802eb32211d47d", "version": 0, "state": "payload.production.total", "stateType": "msg", "attributes": [], "inputOverride": "allow", "outputProperties": [], "x": 440, "y": 140, "wires": [ [] ] }, { "id": "7b847b06b8051f2f", "type": "ha-sensor", "z": "a92538baa3ea546d", "name": "Production A", "entityConfig": "58bbafb0758a7bcc", "version": 0, "state": "payload.production.a", "stateType": "msg", "attributes": [], "inputOverride": "allow", "outputProperties": [], "x": 230, "y": 540, "wires": [ [] ] }, { "id": "9fdc13df497a823a", "type": "function", "z": "a92538baa3ea546d", "name": "function 2", "func": "msg.payload = Math.floor(Math.random() * 500) + 25;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 220, "y": 620, "wires": [ [ "24e2caa086e88c4e", "78886969f4ede8fa" ] ] }, { "id": "24e2caa086e88c4e", "type": "ha-sensor", "z": "a92538baa3ea546d", "name": "battery_state_power", "entityConfig": "9cc354ff17163508", "version": 0, "state": "payload", "stateType": "msg", "attributes": [], "inputOverride": "allow", "outputProperties": [], "x": 460, "y": 620, "wires": [ [] ] }, { "id": "78886969f4ede8fa", "type": "ha-sensor", "z": "a92538baa3ea546d", "name": "battPower", "entityConfig": "10b97d6ea19edeb0", "version": 0, "state": "payload", "stateType": "msg", "attributes": [], "inputOverride": "allow", "outputProperties": [], "x": 420, "y": 700, "wires": [ [] ] }, { "id": "402249fad23506cb", "type": "ha-sensor", "z": "a92538baa3ea546d", "name": "enphase_battery_soc", "entityConfig": "ed78fa1e3bbee374", "version": 0, "state": "payload.soc", "stateType": "msg", "attributes": [], "inputOverride": "allow", "outputProperties": [], "x": 420, "y": 240, "wires": [ [] ] } ]