Skip to content

Instantly share code, notes, and snippets.

@nalditopr
Last active April 12, 2025 04:42
Show Gist options
  • Save nalditopr/493af377e9928b88c2639a9e1607f127 to your computer and use it in GitHub Desktop.
Save nalditopr/493af377e9928b88c2639a9e1607f127 to your computer and use it in GitHub Desktop.
Eco Flow Delta 3 + Node-Red + Homeassistant
[
{
"id": "5c3a7efbb734c312",
"type": "tab",
"label": "Ecoflow MQTT",
"disabled": false,
"info": "",
"env": []
},
{
"id": "773fab09ddaa9e53",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "connect",
"props": [
{
"p": "action",
"v": "connect",
"vt": "str"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 350,
"y": 520,
"wires": [
[
"d5d7e8960ba14429"
]
]
},
{
"id": "d5d7e8960ba14429",
"type": "mqtt out",
"z": "5c3a7efbb734c312",
"name": "ef-mqtt",
"topic": "",
"qos": "",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "4a025f91e9595714",
"x": 540,
"y": 540,
"wires": []
},
{
"id": "6d38c1d92d6c19eb",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get",
"qos": "2",
"datatype": "base64",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 970,
"y": 340,
"wires": [
[
"0cf29e3992e7bfdc"
]
]
},
{
"id": "c8d401ac3c0d530b",
"type": "debug",
"z": "5c3a7efbb734c312",
"name": "debug 2",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1180,
"y": 220,
"wires": []
},
{
"id": "0cf29e3992e7bfdc",
"type": "debug",
"z": "5c3a7efbb734c312",
"name": "debug 3",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1420,
"y": 340,
"wires": []
},
{
"id": "d9ecc011d0be04ea",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get_reply",
"qos": "2",
"datatype": "base64",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 990,
"y": 460,
"wires": [
[
"5dc759c3914d8893"
]
]
},
{
"id": "34495fd19ce3c931",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/set",
"qos": "2",
"datatype": "base64",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 970,
"y": 580,
"wires": [
[
"1b07cbc9319439e6"
]
]
},
{
"id": "196e8e1147aa9c70",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/set_reply",
"qos": "2",
"datatype": "base64",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 980,
"y": 700,
"wires": [
[
"222174cf92b067ba"
]
]
},
{
"id": "5dc759c3914d8893",
"type": "debug",
"z": "5c3a7efbb734c312",
"name": "debug 4",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1420,
"y": 460,
"wires": []
},
{
"id": "1b07cbc9319439e6",
"type": "debug",
"z": "5c3a7efbb734c312",
"name": "debug 5",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1420,
"y": 580,
"wires": []
},
{
"id": "222174cf92b067ba",
"type": "debug",
"z": "5c3a7efbb734c312",
"name": "debug 6",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1420,
"y": 700,
"wires": []
},
{
"id": "2ea889238290350b",
"type": "mqtt out",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/set",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "4a025f91e9595714",
"x": 990,
"y": 980,
"wires": []
},
{
"id": "3507d66f640759d3",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "beep_on",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":1},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 1080,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "2126c09b8693f86a",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/set",
"qos": "2",
"datatype": "auto-detect",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 990,
"y": 640,
"wires": [
[
"1b07cbc9319439e6"
]
]
},
{
"id": "1771f8034a515b9c",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get",
"qos": "2",
"datatype": "auto-detect",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 990,
"y": 400,
"wires": [
[
"0cf29e3992e7bfdc"
]
]
},
{
"id": "6bd61b7f744cd6dd",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get_reply",
"qos": "2",
"datatype": "auto-detect",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 1010,
"y": 520,
"wires": [
[
"5dc759c3914d8893",
"15622328ecef2318"
]
]
},
{
"id": "2aa01b5bcbc04c2d",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/set_reply",
"qos": "2",
"datatype": "auto-detect",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 1000,
"y": 760,
"wires": [
[
"222174cf92b067ba"
]
]
},
{
"id": "af84a2f4c0da27f2",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/device/status/[[SN]]",
"qos": "2",
"datatype": "auto-detect",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 900,
"y": 280,
"wires": [
[
"c8d401ac3c0d530b"
]
]
},
{
"id": "1879d2c74d981f0a",
"type": "encode",
"z": "5c3a7efbb734c312",
"name": "",
"protofile": "fd04eecb52341faa",
"protoType": "MessageFromJson",
"x": 620,
"y": 980,
"wires": [
[
"2ea889238290350b"
]
]
},
{
"id": "c41e867bd65c48cc",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "beep_off",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 1200,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "4ec8c1c4e51da6e7",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "get",
"props": [
{
"p": "payload"
}
],
"repeat": "15",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_14\":128301330,\"bytes_23\":\"Android\"}}}",
"payloadType": "json",
"x": 350,
"y": 660,
"wires": [
[
"d0662aaa5ced35c4"
]
]
},
{
"id": "1050b450dc646a9f",
"type": "mqtt out",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get",
"qos": "2",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "4a025f91e9595714",
"x": 990,
"y": 860,
"wires": []
},
{
"id": "d0662aaa5ced35c4",
"type": "encode",
"z": "5c3a7efbb734c312",
"name": "",
"protofile": "fd04eecb52341faa",
"protoType": "MessageFromJson",
"x": 620,
"y": 860,
"wires": [
[
"1050b450dc646a9f"
]
]
},
{
"id": "1981b4272caec0f1",
"type": "debug",
"z": "5c3a7efbb734c312",
"name": "debug 7",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 2240,
"y": 520,
"wires": []
},
{
"id": "668e876f10fa3918",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "charge_15",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_102\":15},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 1000,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "fab3e8f819aca276",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "charge_90",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_102\":90},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 920,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "15622328ecef2318",
"type": "decode",
"z": "5c3a7efbb734c312",
"name": "",
"protofile": "09526bce7b477f38",
"protoType": "MessageFromJson",
"x": 1560,
"y": 520,
"wires": [
[
"86e09c3f6d07938c"
]
]
},
{
"id": "86e09c3f6d07938c",
"type": "function",
"z": "5c3a7efbb734c312",
"name": "parser",
"func": "// Array of variables to convert (define the path to each variable as a string, excluding the array index)\nlet variablesToConvert = [\n \"NestedsubMesssage_1.batteryLevel\",\n \"NestedsubMesssage_1.acPower\",\n \"NestedsubMesssage_1.acOut\"\n];\n\n// Helper function to access and modify nested properties\nfunction convertFixed32ToFloat(obj, path) {\n let keys = path.split(\".\");\n let lastKey = keys.pop();\n let target = keys.reduce((o, k) => (o && o[k] ? o[k] : undefined), obj);\n\n if (target && target[lastKey] !== undefined) {\n let fixed32Value = target[lastKey];\n let buffer = Buffer.alloc(4);\n buffer.writeUInt32LE(fixed32Value); // Write as little-endian\n let dataView = new DataView(buffer.buffer);\n let floatValue = dataView.getFloat32(0, true); // Convert to float (little-endian)\n target[lastKey] = Math.round(floatValue * 100) / 100; // Round to 2 decimals\n }\n}\n\n// Validate that the array exists\nif (\n msg.payload.subMesssage_1 &&\n Array.isArray(msg.payload.subMesssage_1)\n) {\n // Automatically find the element with the largest NestedsubMesssage_1 (by number of keys)\n let selectedElement = msg.payload.subMesssage_1.reduce((largest, current) => {\n const currentSize = current?.NestedsubMesssage_1 ? Object.keys(current.NestedsubMesssage_1).length : 0;\n const largestSize = largest?.NestedsubMesssage_1 ? Object.keys(largest.NestedsubMesssage_1).length : 0;\n return currentSize > largestSize ? current : largest;\n }, null);\n\n if (selectedElement) {\n // Loop through the variables and convert them for the selected element\n variablesToConvert.forEach(path => {\n convertFixed32ToFloat(selectedElement, path);\n });\n\n // Flatten the selected element for output\n msg.payload = {\n ...selectedElement.NestedsubMesssage_1\n };\n } else {\n msg.payload = { error: \"No valid element found in subMesssage_1.\" };\n }\n} else {\n // Handle the case where the array is invalid\n msg.payload = {\n error: \"subMesssage_1 is not a valid array.\"\n };\n}\n\n// Return the flattened object as the payload\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1710,
"y": 520,
"wires": [
[
"1981b4272caec0f1",
"16d905301a29dbdf",
"4df43232664f45b5",
"2177e930db19a389",
"5adb6177ab992ca0"
]
]
},
{
"id": "ab9e1d2599c501f9",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "self-powered off",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"selfpowered_106\":{}},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 320,
"y": 860,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "2b4391ab6cfa2082",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "self-powered on",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_26\":0,\"selfpowered_106\":{\"int_1\":1},\"int_138\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":11,\"int_11\":1,\"int_14\":357051739,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 320,
"y": 740,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "16d905301a29dbdf",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "device_a_Battery Level",
"entityConfig": "49b4f2bfd1956a24",
"version": 0,
"state": "payload.batteryLevel",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1950,
"y": 700,
"wires": [
[
"1981b4272caec0f1"
]
]
},
{
"id": "4df43232664f45b5",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "device_a_Charge Target",
"entityConfig": "87a97985e13b1458",
"version": 0,
"state": "payload.target",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1960,
"y": 760,
"wires": [
[
"1981b4272caec0f1"
]
]
},
{
"id": "dfcac4c65259021a",
"type": "ha-switch",
"z": "5c3a7efbb734c312",
"name": "device_a_self-powered",
"version": 0,
"debugenabled": false,
"inputs": 0,
"outputs": 2,
"entityConfig": "20ef2d5be7415ccd",
"enableInput": false,
"outputOnStateChange": true,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 90,
"y": 800,
"wires": [
[
"14cf1dbdc9323cf5"
],
[
"168a92bf365a0769"
]
]
},
{
"id": "14cf1dbdc9323cf5",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "self-powered on",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_26\":0,\"selfpowered_106\":{\"int_1\":1},\"int_138\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":11,\"int_11\":1,\"int_14\":357051739,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 320,
"y": 780,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "168a92bf365a0769",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "self-powered off",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"selfpowered_106\":{}},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 320,
"y": 820,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "2177e930db19a389",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "device_a_AC Power",
"entityConfig": "6670dfa7e6a8c02e",
"version": 0,
"state": "payload.acPower",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1940,
"y": 640,
"wires": [
[
"1981b4272caec0f1"
]
]
},
{
"id": "18c73ca84e0549a8",
"type": "ha-number",
"z": "5c3a7efbb734c312",
"name": "device_a_charge-target",
"version": 1,
"debugenabled": false,
"inputs": 0,
"outputs": 1,
"entityConfig": "a0136659e84650bb",
"exposeAsEntityConfig": "",
"mode": "listen",
"value": "payload",
"valueType": "msg",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "value"
},
{
"property": "previousValue",
"propertyType": "msg",
"value": "",
"valueType": "previousValue"
}
],
"x": 90,
"y": 960,
"wires": [
[
"06a42ae752c09211"
]
]
},
{
"id": "06a42ae752c09211",
"type": "function",
"z": "5c3a7efbb734c312",
"name": "charge-target",
"func": "// Get the input number from the msg payload\nlet inputNumber = msg.payload;\n\n// Validate the input number and clamp it between 15 and 90\nif (inputNumber < 15) {\n inputNumber = 15;\n} else if (inputNumber > 90) {\n inputNumber = 90;\n}\n\n// Define the JSON structure\nconst jsonResponse = {\n \"subMesssage_1\": {\n \"NestedsubMesssage_1\": {\n \"int_102\": inputNumber // Use the validated input number here\n },\n \"int_2\": 32,\n \"int_3\": 2,\n \"int_4\": 1,\n \"int_5\": 1,\n \"int_8\": 254,\n \"int_9\": 17,\n \"int_10\": 3,\n \"int_11\": 1,\n \"int_14\": 148771586,\n \"int_15\": 1,\n \"int_16\": 19,\n \"int_17\": 1\n }\n};\n\n// Assign the JSON to msg.payload\nmsg.payload = jsonResponse;\n\n// Return the modified msg object\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 330,
"y": 960,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "20d9b6e2c35b70fc",
"type": "ha-switch",
"z": "5c3a7efbb734c312",
"name": "device_a_beep",
"version": 0,
"debugenabled": false,
"inputs": 0,
"outputs": 2,
"entityConfig": "43ab0950c992e96d",
"enableInput": false,
"outputOnStateChange": true,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 120,
"y": 1140,
"wires": [
[
"8d0c4baed56b9bfe"
],
[
"f591f651b4d2153a"
]
]
},
{
"id": "8d0c4baed56b9bfe",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "beep-on",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":1},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 340,
"y": 1120,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "f591f651b4d2153a",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "beep-off",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 340,
"y": 1160,
"wires": [
[
"1879d2c74d981f0a"
]
]
},
{
"id": "5adb6177ab992ca0",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "device_a_AC Out",
"entityConfig": "9531e396809c4293",
"version": 0,
"state": "payload.acOut",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1930,
"y": 580,
"wires": [
[
"1981b4272caec0f1"
]
]
},
{
"id": "61291127c9a9b736",
"type": "debug",
"z": "5c3a7efbb734c312",
"name": "debug 10",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1420,
"y": 1440,
"wires": []
},
{
"id": "78bcd84f0434c885",
"type": "mqtt out",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/set",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "4a025f91e9595714",
"x": 990,
"y": 1960,
"wires": []
},
{
"id": "cbc2dd792fc76a03",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "beep_on",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":1},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 2060,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "79a047ea301467c3",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get_reply",
"qos": "2",
"datatype": "auto-detect",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 1010,
"y": 1500,
"wires": [
[
"61291127c9a9b736",
"a3ddcd10a21dabe5"
]
]
},
{
"id": "4afdedfb126c3adb",
"type": "encode",
"z": "5c3a7efbb734c312",
"name": "",
"protofile": "fd04eecb52341faa",
"protoType": "MessageFromJson",
"x": 620,
"y": 1960,
"wires": [
[
"78bcd84f0434c885"
]
]
},
{
"id": "d2c67cfa36b8eddd",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "beep_off",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 2180,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "4c886e6bc42a159d",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "get",
"props": [
{
"p": "payload"
}
],
"repeat": "15",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_14\":128301340,\"bytes_23\":\"Android\"}}}",
"payloadType": "json",
"x": 350,
"y": 1640,
"wires": [
[
"a866568cee5cc41b"
]
]
},
{
"id": "53e91d153c751f3b",
"type": "mqtt out",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get",
"qos": "2",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "4a025f91e9595714",
"x": 990,
"y": 1840,
"wires": []
},
{
"id": "a866568cee5cc41b",
"type": "encode",
"z": "5c3a7efbb734c312",
"name": "",
"protofile": "fd04eecb52341faa",
"protoType": "MessageFromJson",
"x": 620,
"y": 1840,
"wires": [
[
"53e91d153c751f3b"
]
]
},
{
"id": "14915a090ac399a6",
"type": "debug",
"z": "5c3a7efbb734c312",
"name": "debug 13",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 2240,
"y": 1500,
"wires": []
},
{
"id": "3117402a17b4b898",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "charge_15",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_102\":15},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 1980,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "78ab8f746a16080b",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "charge_90",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_102\":90},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 1900,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "a3ddcd10a21dabe5",
"type": "decode",
"z": "5c3a7efbb734c312",
"name": "",
"protofile": "09526bce7b477f38",
"protoType": "MessageFromJson",
"x": 1560,
"y": 1500,
"wires": [
[
"2ccc9eebdc8b1c6d"
]
]
},
{
"id": "2ccc9eebdc8b1c6d",
"type": "function",
"z": "5c3a7efbb734c312",
"name": "parser",
"func": "// Array of variables to convert (define the path to each variable as a string, excluding the array index)\nlet variablesToConvert = [\n \"NestedsubMesssage_1.batteryLevel\",\n \"NestedsubMesssage_1.acPower\",\n \"NestedsubMesssage_1.acOut\"\n];\n\n// Helper function to access and modify nested properties\nfunction convertFixed32ToFloat(obj, path) {\n let keys = path.split(\".\");\n let lastKey = keys.pop();\n let target = keys.reduce((o, k) => (o && o[k] ? o[k] : undefined), obj);\n\n if (target && target[lastKey] !== undefined) {\n let fixed32Value = target[lastKey];\n let buffer = Buffer.alloc(4);\n buffer.writeUInt32LE(fixed32Value); // Write as little-endian\n let dataView = new DataView(buffer.buffer);\n let floatValue = dataView.getFloat32(0, true); // Convert to float (little-endian)\n target[lastKey] = Math.round(floatValue * 100) / 100; // Round to 2 decimals\n }\n}\n\n// Validate that the array exists\nif (\n msg.payload.subMesssage_1 &&\n Array.isArray(msg.payload.subMesssage_1)\n) {\n // Automatically find the element with the largest NestedsubMesssage_1 (by number of keys)\n let selectedElement = msg.payload.subMesssage_1.reduce((largest, current) => {\n const currentSize = current?.NestedsubMesssage_1 ? Object.keys(current.NestedsubMesssage_1).length : 0;\n const largestSize = largest?.NestedsubMesssage_1 ? Object.keys(largest.NestedsubMesssage_1).length : 0;\n return currentSize > largestSize ? current : largest;\n }, null);\n\n if (selectedElement) {\n // Loop through the variables and convert them for the selected element\n variablesToConvert.forEach(path => {\n convertFixed32ToFloat(selectedElement, path);\n });\n\n // Flatten the selected element for output\n msg.payload = {\n ...selectedElement.NestedsubMesssage_1\n };\n } else {\n msg.payload = { error: \"No valid element found in subMesssage_1.\" };\n }\n} else {\n // Handle the case where the array is invalid\n msg.payload = {\n error: \"subMesssage_1 is not a valid array.\"\n };\n}\n\n// Return the flattened object as the payload\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1710,
"y": 1500,
"wires": [
[
"14915a090ac399a6",
"9cee10300a29e6a9",
"1b4d1659ea3a926c",
"bada8f8ece2635aa",
"43c3e714cd35d499"
]
]
},
{
"id": "b48fdb9a8c3cc648",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "self-powered off",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"selfpowered_106\":{}},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 320,
"y": 1840,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "cdb9de6cfa82de2f",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "self-powered on",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_26\":0,\"selfpowered_106\":{\"int_1\":1},\"int_138\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":11,\"int_11\":1,\"int_14\":357051739,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 320,
"y": 1720,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "9cee10300a29e6a9",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "device_b_Battery Level",
"entityConfig": "dde3390b2670ecca",
"version": 0,
"state": "payload.batteryLevel",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1950,
"y": 1680,
"wires": [
[
"14915a090ac399a6"
]
]
},
{
"id": "1b4d1659ea3a926c",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "device_b_Charge Target",
"entityConfig": "8a7f89d5a9fa7c02",
"version": 0,
"state": "payload.target",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1950,
"y": 1740,
"wires": [
[
"14915a090ac399a6"
]
]
},
{
"id": "99b6426401998b0e",
"type": "ha-switch",
"z": "5c3a7efbb734c312",
"name": "device_b_self-powered",
"version": 0,
"debugenabled": false,
"inputs": 0,
"outputs": 2,
"entityConfig": "0ed3beaf87d1c18b",
"enableInput": false,
"outputOnStateChange": true,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 90,
"y": 1780,
"wires": [
[
"63aceac7ccac0171"
],
[
"d832c92ebdc1011f"
]
]
},
{
"id": "63aceac7ccac0171",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "self-powered on",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_26\":0,\"selfpowered_106\":{\"int_1\":1},\"int_138\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":11,\"int_11\":1,\"int_14\":357051739,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 320,
"y": 1760,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "d832c92ebdc1011f",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "self-powered off",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"selfpowered_106\":{}},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 320,
"y": 1800,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "bada8f8ece2635aa",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "device_b_AC Power",
"entityConfig": "026a8517f7533933",
"version": 0,
"state": "payload.acPower",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1940,
"y": 1620,
"wires": [
[
"14915a090ac399a6"
]
]
},
{
"id": "2ebdec0e9dfb2275",
"type": "ha-number",
"z": "5c3a7efbb734c312",
"name": "device_b_charge-target",
"version": 1,
"debugenabled": false,
"inputs": 0,
"outputs": 1,
"entityConfig": "3c4b70a170c5034c",
"exposeAsEntityConfig": "",
"mode": "listen",
"value": "payload",
"valueType": "msg",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "value"
},
{
"property": "previousValue",
"propertyType": "msg",
"value": "",
"valueType": "previousValue"
}
],
"x": 90,
"y": 1940,
"wires": [
[
"154a232e234fcd68"
]
]
},
{
"id": "154a232e234fcd68",
"type": "function",
"z": "5c3a7efbb734c312",
"name": "charge-target",
"func": "// Get the input number from the msg payload\nlet inputNumber = msg.payload;\n\n// Validate the input number and clamp it between 15 and 90\nif (inputNumber < 15) {\n inputNumber = 15;\n} else if (inputNumber > 90) {\n inputNumber = 90;\n}\n\n// Define the JSON structure\nconst jsonResponse = {\n \"subMesssage_1\": {\n \"NestedsubMesssage_1\": {\n \"int_102\": inputNumber // Use the validated input number here\n },\n \"int_2\": 32,\n \"int_3\": 2,\n \"int_4\": 1,\n \"int_5\": 1,\n \"int_8\": 254,\n \"int_9\": 17,\n \"int_10\": 3,\n \"int_11\": 1,\n \"int_14\": 148771586,\n \"int_15\": 1,\n \"int_16\": 19,\n \"int_17\": 1\n }\n};\n\n// Assign the JSON to msg.payload\nmsg.payload = jsonResponse;\n\n// Return the modified msg object\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 330,
"y": 1940,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "e01d4a7f5c8794e8",
"type": "ha-switch",
"z": "5c3a7efbb734c312",
"name": "device_b_beep",
"version": 0,
"debugenabled": false,
"inputs": 0,
"outputs": 2,
"entityConfig": "3631ea3e83d0c784",
"enableInput": false,
"outputOnStateChange": true,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 120,
"y": 2120,
"wires": [
[
"da187d62e67d4740"
],
[
"0db6d726d44ba972"
]
]
},
{
"id": "da187d62e67d4740",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "beep-on",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":1},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 340,
"y": 2100,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "0db6d726d44ba972",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "beep-off",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 340,
"y": 2140,
"wires": [
[
"4afdedfb126c3adb"
]
]
},
{
"id": "43c3e714cd35d499",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "device_b_AC Out",
"entityConfig": "2a388ed5ce9b5e60",
"version": 0,
"state": "payload.acOut",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1930,
"y": 1560,
"wires": [
[
"14915a090ac399a6"
]
]
},
{
"id": "2c1452e5064f0d52",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get_reply",
"qos": "2",
"datatype": "base64",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 1010,
"y": 1440,
"wires": [
[
"61291127c9a9b736"
]
]
},
{
"id": "40899d5bf070eb87",
"type": "mqtt out",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/set",
"qos": "0",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "4a025f91e9595714",
"x": 990,
"y": 2640,
"wires": []
},
{
"id": "e7b270e459122203",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "beep_on",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":1},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 2740,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "0df3e8fca92c4338",
"type": "encode",
"z": "5c3a7efbb734c312",
"name": "",
"protofile": "fd04eecb52341faa",
"protoType": "MessageFromJson",
"x": 620,
"y": 2640,
"wires": [
[
"40899d5bf070eb87"
]
]
},
{
"id": "da568bf8284dcb21",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "beep_off",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 2860,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "206aee2b11b63f84",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "get",
"props": [
{
"p": "payload"
}
],
"repeat": "15",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_14\":128301340,\"bytes_23\":\"Android\"}}}",
"payloadType": "json",
"x": 350,
"y": 2320,
"wires": [
[
"e48d93fa9bd1dede"
]
]
},
{
"id": "c041d0230aae2212",
"type": "mqtt out",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get",
"qos": "2",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "4a025f91e9595714",
"x": 990,
"y": 2520,
"wires": []
},
{
"id": "e48d93fa9bd1dede",
"type": "encode",
"z": "5c3a7efbb734c312",
"name": "",
"protofile": "fd04eecb52341faa",
"protoType": "MessageFromJson",
"x": 620,
"y": 2520,
"wires": [
[
"c041d0230aae2212"
]
]
},
{
"id": "9d19d00006660558",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "charge_15",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_102\":15},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 2660,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "9c7d06381f17ec47",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "charge_90",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_102\":90},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 340,
"y": 2580,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "606d09cff852da57",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "self-powered off",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"selfpowered_106\":{}},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 320,
"y": 2520,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "0c965edcfaee92e2",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "self-powered on",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_26\":0,\"selfpowered_106\":{\"int_1\":1},\"int_138\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":11,\"int_11\":1,\"int_14\":357051739,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"payloadType": "json",
"x": 320,
"y": 2400,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "2a75e18e8370d8dc",
"type": "ha-switch",
"z": "5c3a7efbb734c312",
"name": "game-room_self-powered",
"version": 0,
"debugenabled": false,
"inputs": 0,
"outputs": 2,
"entityConfig": "0ed3beaf87d1c18b",
"enableInput": false,
"outputOnStateChange": true,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 110,
"y": 2460,
"wires": [
[
"d58f942610d15d41"
],
[
"36b8aa2e46921246"
]
]
},
{
"id": "d58f942610d15d41",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "self-powered on",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_26\":0,\"selfpowered_106\":{\"int_1\":1},\"int_138\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":11,\"int_11\":1,\"int_14\":357051739,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 320,
"y": 2440,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "36b8aa2e46921246",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "self-powered off",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"selfpowered_106\":{}},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":3,\"int_11\":1,\"int_14\":148771586,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 320,
"y": 2480,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "a8889aac5fe8adba",
"type": "ha-number",
"z": "5c3a7efbb734c312",
"name": "game_room_charge-target",
"version": 1,
"debugenabled": false,
"inputs": 0,
"outputs": 1,
"entityConfig": "6d6efedc5ce72e03",
"exposeAsEntityConfig": "",
"mode": "listen",
"value": "payload",
"valueType": "msg",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "value"
},
{
"property": "previousValue",
"propertyType": "msg",
"value": "",
"valueType": "previousValue"
}
],
"x": 110,
"y": 2620,
"wires": [
[
"a0e3545c22e94120"
]
]
},
{
"id": "a0e3545c22e94120",
"type": "function",
"z": "5c3a7efbb734c312",
"name": "charge-target",
"func": "// Get the input number from the msg payload\nlet inputNumber = msg.payload;\n\n// Validate the input number and clamp it between 15 and 90\nif (inputNumber < 15) {\n inputNumber = 15;\n} else if (inputNumber > 90) {\n inputNumber = 90;\n}\n\n// Define the JSON structure\nconst jsonResponse = {\n \"subMesssage_1\": {\n \"NestedsubMesssage_1\": {\n \"int_102\": inputNumber // Use the validated input number here\n },\n \"int_2\": 32,\n \"int_3\": 2,\n \"int_4\": 1,\n \"int_5\": 1,\n \"int_8\": 254,\n \"int_9\": 17,\n \"int_10\": 3,\n \"int_11\": 1,\n \"int_14\": 148771586,\n \"int_15\": 1,\n \"int_16\": 19,\n \"int_17\": 1\n }\n};\n\n// Assign the JSON to msg.payload\nmsg.payload = jsonResponse;\n\n// Return the modified msg object\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 330,
"y": 2620,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "c87da4bdf1d50ee0",
"type": "ha-switch",
"z": "5c3a7efbb734c312",
"name": "game_romm_beep",
"version": 0,
"debugenabled": false,
"inputs": 0,
"outputs": 2,
"entityConfig": "7780b0daa4506eb3",
"enableInput": false,
"outputOnStateChange": true,
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "str"
}
],
"x": 150,
"y": 2800,
"wires": [
[
"84ef3666b4918b11"
],
[
"7797631b8793f548"
]
]
},
{
"id": "84ef3666b4918b11",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "beep-on",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":1},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 340,
"y": 2780,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "7797631b8793f548",
"type": "change",
"z": "5c3a7efbb734c312",
"name": "beep-off",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "{\"subMesssage_1\":{\"NestedsubMesssage_1\":{\"int_9\":0},\"int_2\":32,\"int_3\":2,\"int_4\":1,\"int_5\":1,\"int_8\":254,\"int_9\":17,\"int_10\":2,\"int_11\":1,\"int_14\":128301330,\"int_15\":1,\"int_16\":19,\"int_17\":1}}",
"tot": "json"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 340,
"y": 2820,
"wires": [
[
"0df3e8fca92c4338"
]
]
},
{
"id": "86fd2954650666b0",
"type": "debug",
"z": "5c3a7efbb734c312",
"name": "debug 14",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 1380,
"y": 2380,
"wires": []
},
{
"id": "384d158b61792940",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get_reply",
"qos": "2",
"datatype": "auto-detect",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 970,
"y": 2440,
"wires": [
[
"86fd2954650666b0",
"26d30e88ae82ce2e"
]
]
},
{
"id": "d0116386713bae5c",
"type": "debug",
"z": "5c3a7efbb734c312",
"name": "debug 15",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 2260,
"y": 2440,
"wires": []
},
{
"id": "26d30e88ae82ce2e",
"type": "decode",
"z": "5c3a7efbb734c312",
"name": "",
"protofile": "09526bce7b477f38",
"protoType": "MessageFromJson",
"x": 1520,
"y": 2440,
"wires": [
[
"549457785dda7568",
"d0116386713bae5c"
]
]
},
{
"id": "549457785dda7568",
"type": "function",
"z": "5c3a7efbb734c312",
"name": "parser",
"func": "// Array of variables to convert (define the path to each variable as a string, excluding the array index)\nlet variablesToConvert = [\n \"NestedsubMesssage_1.batteryLevel\",\n \"NestedsubMesssage_1.acPower\",\n \"NestedsubMesssage_1.acOut\"\n];\n\n// Helper function to access and modify nested properties\nfunction convertFixed32ToFloat(obj, path) {\n let keys = path.split(\".\");\n let lastKey = keys.pop();\n let target = keys.reduce((o, k) => (o && o[k] ? o[k] : undefined), obj);\n\n if (target && target[lastKey] !== undefined) {\n let fixed32Value = target[lastKey];\n let buffer = Buffer.alloc(4);\n buffer.writeUInt32LE(fixed32Value); // Write as little-endian\n let dataView = new DataView(buffer.buffer);\n let floatValue = dataView.getFloat32(0, true); // Convert to float (little-endian)\n target[lastKey] = Math.round(floatValue * 100) / 100; // Round to 2 decimals\n }\n}\n\n// Validate that the array exists\nif (\n msg.payload.subMesssage_1 &&\n Array.isArray(msg.payload.subMesssage_1)\n) {\n // Automatically find the element with the largest NestedsubMesssage_1 (by number of keys)\n let selectedElement = msg.payload.subMesssage_1.reduce((largest, current) => {\n const currentSize = current?.NestedsubMesssage_1 ? Object.keys(current.NestedsubMesssage_1).length : 0;\n const largestSize = largest?.NestedsubMesssage_1 ? Object.keys(largest.NestedsubMesssage_1).length : 0;\n return currentSize > largestSize ? current : largest;\n }, null);\n\n if (selectedElement) {\n // Loop through the variables and convert them for the selected element\n variablesToConvert.forEach(path => {\n convertFixed32ToFloat(selectedElement, path);\n });\n\n // Flatten the selected element for output\n msg.payload = {\n ...selectedElement.NestedsubMesssage_1\n };\n } else {\n msg.payload = { error: \"No valid element found in subMesssage_1.\" };\n }\n} else {\n // Handle the case where the array is invalid\n msg.payload = {\n error: \"subMesssage_1 is not a valid array.\"\n };\n}\n\n// Return the flattened object as the payload\nreturn msg;\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1670,
"y": 2440,
"wires": [
[
"d0116386713bae5c",
"0c4901bd2280a3d7",
"45baf5736570e2ad",
"329113f3c0c5de18",
"e0919f7e1a368afa"
]
]
},
{
"id": "0c4901bd2280a3d7",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "game_room_Battery Level",
"entityConfig": "7151f98c7353537a",
"version": 0,
"state": "payload.batteryLevel",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1940,
"y": 2620,
"wires": [
[
"d0116386713bae5c"
]
]
},
{
"id": "45baf5736570e2ad",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "game_room_Charge Target",
"entityConfig": "441b901f84dcda6f",
"version": 0,
"state": "payload.target",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1940,
"y": 2680,
"wires": [
[
"d0116386713bae5c"
]
]
},
{
"id": "329113f3c0c5de18",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "game_room_AC Power",
"entityConfig": "0f0fe1c43b8f4534",
"version": 0,
"state": "payload.acPower",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1930,
"y": 2560,
"wires": [
[
"d0116386713bae5c"
]
]
},
{
"id": "e0919f7e1a368afa",
"type": "ha-sensor",
"z": "5c3a7efbb734c312",
"name": "game_room_AC Out",
"entityConfig": "859ef31dd27d08ad",
"version": 0,
"state": "payload.acOut",
"stateType": "msg",
"attributes": [],
"inputOverride": "allow",
"outputProperties": [],
"x": 1920,
"y": 2500,
"wires": [
[
"d0116386713bae5c"
]
]
},
{
"id": "fd881a468a285660",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/[[APPID]]/[[SN]]/thing/property/get_reply",
"qos": "2",
"datatype": "base64",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 970,
"y": 2380,
"wires": [
[
"86fd2954650666b0"
]
]
},
{
"id": "671e0ceff575862c",
"type": "inject",
"z": "5c3a7efbb734c312",
"name": "disconnect",
"props": [
{
"p": "action",
"v": "disconnect",
"vt": "str"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 340,
"y": 580,
"wires": [
[
"d5d7e8960ba14429"
]
]
},
{
"id": "5b6c19b0a776f928",
"type": "mqtt in",
"z": "5c3a7efbb734c312",
"name": "",
"topic": "/app/device/status/[[SN]]",
"qos": "2",
"datatype": "base64",
"broker": "4a025f91e9595714",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 900,
"y": 220,
"wires": [
[
"c8d401ac3c0d530b"
]
]
},
{
"id": "4a025f91e9595714",
"type": "mqtt-broker",
"name": "ecoflow",
"broker": "mqtts://mqtt.ecoflow.com:8883",
"port": "8883",
"clientid": "ANDROID_58AC938C-00B3-4635-8D83-D0575E20C8B7_[[APPID]]",
"autoConnect": false,
"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": "fd04eecb52341faa",
"type": "protobuf-file",
"protopath": "/homeassistant/www/get-delta3.proto",
"watchFile": true,
"keepCase": false
},
{
"id": "09526bce7b477f38",
"type": "protobuf-file",
"protopath": "/homeassistant/www/decodev2-delta3.proto",
"watchFile": true,
"keepCase": false
},
{
"id": "49b4f2bfd1956a24",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "5953bb61763c4552",
"name": "device_a_Battery Level",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "Battery Level"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": "battery"
},
{
"property": "unit_of_measurement",
"value": "%"
},
{
"property": "state_class",
"value": "measurement"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "87a97985e13b1458",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "5953bb61763c4552",
"name": "device_a_Charge Target",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "Charge Target"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": ""
},
{
"property": "unit_of_measurement",
"value": "%"
},
{
"property": "state_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "20ef2d5be7415ccd",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "5953bb61763c4552",
"name": "device_a_self-powered",
"version": "6",
"entityType": "switch",
"haConfig": [
{
"property": "name",
"value": "self-powered"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "config"
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "6670dfa7e6a8c02e",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "5953bb61763c4552",
"name": "device_a_AC Power",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "AC Power"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": "energy"
},
{
"property": "unit_of_measurement",
"value": "Wh"
},
{
"property": "state_class",
"value": "measurement"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "a0136659e84650bb",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "5953bb61763c4552",
"name": "device_a_charge-target",
"version": "6",
"entityType": "number",
"haConfig": [
{
"property": "name",
"value": "charge-target"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "config"
},
{
"property": "device_class",
"value": ""
},
{
"property": "unit_of_measurement",
"value": "%"
},
{
"property": "min_value",
"value": 15
},
{
"property": "max_value",
"value": 90
},
{
"property": "step_value",
"value": 1
},
{
"property": "mode",
"value": "auto"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "43ab0950c992e96d",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "5953bb61763c4552",
"name": "device_a_beep",
"version": "6",
"entityType": "switch",
"haConfig": [
{
"property": "name",
"value": "Beep"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "config"
},
{
"property": "device_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "9531e396809c4293",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "5953bb61763c4552",
"name": "device_a_AC Out",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "AC Out"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": "energy"
},
{
"property": "unit_of_measurement",
"value": "Wh"
},
{
"property": "state_class",
"value": "measurement"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "dde3390b2670ecca",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "65845f97489716d9",
"name": "device_b_Battery Level",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "Battery Level"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": "battery"
},
{
"property": "unit_of_measurement",
"value": "%"
},
{
"property": "state_class",
"value": "measurement"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "8a7f89d5a9fa7c02",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "65845f97489716d9",
"name": "device_b_Charge Target",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "Charge Target"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": ""
},
{
"property": "unit_of_measurement",
"value": "%"
},
{
"property": "state_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "0ed3beaf87d1c18b",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "295aed1158103b7f",
"name": "game-room_self-powered",
"version": "6",
"entityType": "switch",
"haConfig": [
{
"property": "name",
"value": "self-powered"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": ""
},
{
"property": "device_class",
"value": "switch"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "026a8517f7533933",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "65845f97489716d9",
"name": "device_b_AC Power",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "AC Power"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": "energy"
},
{
"property": "unit_of_measurement",
"value": "Wh"
},
{
"property": "state_class",
"value": "measurement"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "3c4b70a170c5034c",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "65845f97489716d9",
"name": "device_b_charge-target",
"version": "6",
"entityType": "number",
"haConfig": [
{
"property": "name",
"value": "charge-target"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "config"
},
{
"property": "device_class",
"value": ""
},
{
"property": "unit_of_measurement",
"value": "%"
},
{
"property": "min_value",
"value": 15
},
{
"property": "max_value",
"value": 90
},
{
"property": "step_value",
"value": 1
},
{
"property": "mode",
"value": "slider"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "3631ea3e83d0c784",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "65845f97489716d9",
"name": "device_b_beep",
"version": "6",
"entityType": "switch",
"haConfig": [
{
"property": "name",
"value": "Beep"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "config"
},
{
"property": "device_class",
"value": "switch"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "2a388ed5ce9b5e60",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "65845f97489716d9",
"name": "device_b_AC Out",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "AC Out"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": "energy"
},
{
"property": "unit_of_measurement",
"value": "Wh"
},
{
"property": "state_class",
"value": "measurement"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "6d6efedc5ce72e03",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "295aed1158103b7f",
"name": "game_room_charge-target",
"version": "6",
"entityType": "number",
"haConfig": [
{
"property": "name",
"value": ""
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "config"
},
{
"property": "device_class",
"value": ""
},
{
"property": "unit_of_measurement",
"value": "%"
},
{
"property": "min_value",
"value": 15
},
{
"property": "max_value",
"value": 90
},
{
"property": "step_value",
"value": 1
},
{
"property": "mode",
"value": "slider"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "7780b0daa4506eb3",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "295aed1158103b7f",
"name": "game_room_beep",
"version": "6",
"entityType": "switch",
"haConfig": [
{
"property": "name",
"value": "Beep"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "config"
},
{
"property": "device_class",
"value": "switch"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "7151f98c7353537a",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "295aed1158103b7f",
"name": "game_room_Battery_Level",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "Battery Level"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": "battery"
},
{
"property": "unit_of_measurement",
"value": "%"
},
{
"property": "state_class",
"value": "measurement"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "441b901f84dcda6f",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "295aed1158103b7f",
"name": "game_room_charge_target",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "Charge Target"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": ""
},
{
"property": "unit_of_measurement",
"value": "%"
},
{
"property": "state_class",
"value": ""
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "0f0fe1c43b8f4534",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "295aed1158103b7f",
"name": "game_room_AC_Power",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "AC Power"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": "energy"
},
{
"property": "unit_of_measurement",
"value": "Wh"
},
{
"property": "state_class",
"value": "measurement"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "859ef31dd27d08ad",
"type": "ha-entity-config",
"server": "399b9507.fdb0ea",
"deviceConfig": "295aed1158103b7f",
"name": "game_room_AC Out",
"version": "6",
"entityType": "sensor",
"haConfig": [
{
"property": "name",
"value": "AC Out"
},
{
"property": "icon",
"value": ""
},
{
"property": "entity_picture",
"value": ""
},
{
"property": "entity_category",
"value": "diagnostic"
},
{
"property": "device_class",
"value": "energy"
},
{
"property": "unit_of_measurement",
"value": "Wh"
},
{
"property": "state_class",
"value": "measurement"
}
],
"resend": false,
"debugEnabled": false
},
{
"id": "399b9507.fdb0ea",
"type": "server",
"name": "Home Assistant",
"addon": true
},
{
"id": "5953bb61763c4552",
"type": "ha-device-config",
"name": "device_a D3+",
"hwVersion": "",
"manufacturer": "EcoFlow",
"model": "Delta 3+",
"swVersion": ""
},
{
"id": "65845f97489716d9",
"type": "ha-device-config",
"name": "device_b D3+",
"hwVersion": "",
"manufacturer": "EcoFlow",
"model": "Delta 3+",
"swVersion": ""
},
{
"id": "295aed1158103b7f",
"type": "ha-device-config",
"name": "Game Room D3+",
"hwVersion": "",
"manufacturer": "EcoFlow",
"model": "Delta 3+",
"swVersion": ""
}
]
@phoniclynx
Copy link

Has there been any updates on this at all? All the sensors have changed on their own accord and now make even less ssnes:
image

I just want to be able to monitor my usage in the Electricity Usage panel LOL

@nalditopr
Copy link
Author

nalditopr commented Apr 9, 2025

@phoniclynx I have updated the node.red java function nodes that will auto parse the array, sharing new code here.

This is for the parsers.

    // Array of variables to convert (define the path to each variable as a string, excluding the array index)
    let variablesToConvert = [
        "NestedsubMesssage_1.batteryLevel",
        "NestedsubMesssage_1.acPower",
        "NestedsubMesssage_1.acOut"
    ];
    
    // Helper function to access and modify nested properties
    function convertFixed32ToFloat(obj, path) {
        let keys = path.split(".");
        let lastKey = keys.pop();
        let target = keys.reduce((o, k) => (o && o[k] ? o[k] : undefined), obj);
    
        if (target && target[lastKey] !== undefined) {
            let fixed32Value = target[lastKey];
            let buffer = Buffer.alloc(4);
            buffer.writeUInt32LE(fixed32Value); // Write as little-endian
            let dataView = new DataView(buffer.buffer);
            let floatValue = dataView.getFloat32(0, true); // Convert to float (little-endian)
            target[lastKey] = Math.round(floatValue * 100) / 100; // Round to 2 decimals
        }
    }
    
    // Validate that the array exists
    if (
        msg.payload.subMesssage_1 &&
        Array.isArray(msg.payload.subMesssage_1)
    ) {
        // Automatically find the element with the largest NestedsubMesssage_1 (by number of keys)
        let selectedElement = msg.payload.subMesssage_1.reduce((largest, current) => {
            const currentSize = current?.NestedsubMesssage_1 ? Object.keys(current.NestedsubMesssage_1).length : 0;
            const largestSize = largest?.NestedsubMesssage_1 ? Object.keys(largest.NestedsubMesssage_1).length : 0;
            return currentSize > largestSize ? current : largest;
        }, null);
    
        if (selectedElement) {
            // Loop through the variables and convert them for the selected element
            variablesToConvert.forEach(path => {
                convertFixed32ToFloat(selectedElement, path);
            });
    
            // Flatten the selected element for output
            msg.payload = {
                ...selectedElement.NestedsubMesssage_1
            };
        } else {
            msg.payload = { error: "No valid element found in subMesssage_1." };
        }
    } else {
        // Handle the case where the array is invalid
        msg.payload = {
            error: "subMesssage_1 is not a valid array."
        };
    }
    
    // Return the flattened object as the payload
    return msg;

@nalditopr
Copy link
Author

The above code will fix the issues you mentioned.

@nalditopr
Copy link
Author

nalditopr commented Apr 9, 2025

@imhotep thanks for sharing this!

@phoniclynx make sure you install node-red-contrib-protobuf from your node-red palette

Also, this flow assumes the use of home assistant add-on so you have to reconfigure each entity node to use your home assistant instance if you're not using the add-on and delete the other home assistant add-on entry. This flow also assumes you're using 2 instances of Ecoflow D3+ so disregard Unit B if you only have one device. You also have to edit each MQTT IN entity to replace {{SN}} with your Ecoflow delta 3's serial number (found in the app under settings -> specifications) and {{APP_ID}} with the last part of your MQTT Client ID (whatever is after the last underscore). I got my MQTT credentials using this website Finally, my protobuf messages convert to something slightly different that what shows in the flow. subMessage1 comes in as an array and all the values are in the first index of that array so for each entity I had to change

payload.subMessage_1[0].NestedsubMessage_1.acOut

instead of

payload.subMessage_1.NestedsubMessage_1.acOut

Also not sure why but in the flow above subMessage1 and NestedSubMessage_1 were spelled with 3 s'. Perhaps a bug from before.

Don't forget to actually create those protobuf file and validate them using something like protobufpal. I use node-red in docker so I configured mine to go under /data/homeassistant/get-delta3.proto and /data/homeassistant/decodev2-delta3.proto

Here they are for convenience

get-delta3.proto

syntax = "proto3";

message MessageFromJson {

  subMessage_1SubMsg sub_message_1 = 1;

  message NestedsubMessage_1SubMsg {

    int32 int_7 = 7;
    int32 int_9 = 9;
    int32 int_102 = 102;
    int32 int_26 = 26;
    selfpowered_nested selfpowered_106 = 106;
    int32 int_138 = 138;

  }

  message subMessage_1SubMsg {
    NestedsubMessage_1SubMsg Nestedsub_message_1 = 1;
    int32 int_2 = 2;
    int32 int_3 = 3;
    int32 int_4 = 4;
    int32 int_5 = 5;
    int32 int_6 = 6;
    int32 int_7 = 7;
    int32 int_8 = 8;
    int32 int_9 = 9;
    int32 int_10 = 10;
    int32 int_11 = 11;
    int32 int_12 = 12;
    int32 int_13 = 13;
    int32 int_14 = 14;
    int32 int_15 = 15;
    int32 int_16 = 16;
    int32 int_17 = 17;
    string bytes_23 = 23;
    int32 int_102 = 102;
  }

  message selfpowered_nested {
    int32 int_1 = 1;
  }
}

decode-delta3.proto

syntax = "proto3";

message MessageFromJson {
  repeated subMessage_1SubMsg sub_message_1 = 1;

  message NestedsubMessage_1SubMsg {
    fixed32 battery_level = 262;
    int32 target = 8;
    selfpowered_nested selfpowered_106 = 106;
    fixed32 ac_power = 54;
    fixed32 ac_out = 368;

  }

  message subMessage_1SubMsg {
    
    NestedsubMessage_1SubMsg Nestedsub_message_1 = 1;

  }

  message selfpowered_nested {
    int32 int_1 = 1;
  }
}

The values seem to only update frequently when using the app sadly :/

Thanks so much for this, I had to learn it all from nothing and used a lot of LLM to help. Your feedback is greatly appreciated. I will try to put a new version of the tutorial together once I apply your fixes. Also see my other commet around a new java code for the parsers.

@phoniclynx
Copy link

phoniclynx commented Apr 9, 2025

You are more than welcome, I'm happy to do what I can do get this working too..

So I've just updated the Java and the two proto files, and now I'm getting an invalid Array error that's coming from your Javascript Debug Flow

10/04/2025, 08:57:50[node: debug 9](https://nodered.home.com/#)
/app/1893486175733309441/P351ZUH4PGC60236/thing/property/get_reply : msg.payload : Object
object
error: "subMesssage_1 is not a valid array.

image

This has stopped the downflow objects that now don't get updated. Did I miss a step?

@phoniclynx
Copy link

phoniclynx commented Apr 9, 2025

What I do not get is that is is an array but the JS isn't picking it up?
image
image
image

@nalditopr
Copy link
Author

@phoniclynx

This is the protobuf I have on the decode part.

syntax = "proto3";

message MessageFromJson {

    repeated subMesssage_1SubMsg sub_messsage_1 = 1;

    message NestedsubMesssage_1SubMsg {

            fixed32 battery_level = 262;
            int32 target = 8;
            selfpowered_nested selfpowered_106 = 106;
            fixed32 ac_power = 54;
            fixed32 ac_out = 368;

    }

    message subMesssage_1SubMsg {

        NestedsubMesssage_1SubMsg Nestedsub_messsage_1 = 1;

    }

    message selfpowered_nested {
        int32 int_1 = 1;
    }
}

image

@nalditopr
Copy link
Author

What I do not get is that is is an array but the JS isn't picking it up? image image image

@phoniclynx Actually, I think its because I have 3 sss on the variable name and you have two. I have not fixed the typo on mine.

@phoniclynx
Copy link

I cant see anything that's different with the protobuf.... soo..

I replaced all the "sss" with "ss" and the error is the same:

  // Array of variables to convert (define the path to each variable as a string, excluding the array index)
  let variablesToConvert = [
    "NestedsubMessage_1.batteryLevel",
    "NestedsubMessage_1.acPower",
    "NestedsubMessage_1.acOut"
];

// Helper function to access and modify nested properties
function convertFixed32ToFloat(obj, path) {
    let keys = path.split(".");
    let lastKey = keys.pop();
    let target = keys.reduce((o, k) => (o && o[k] ? o[k] : undefined), obj);

    if (target && target[lastKey] !== undefined) {
        let fixed32Value = target[lastKey];
        let buffer = Buffer.alloc(4);
        buffer.writeUInt32LE(fixed32Value); // Write as little-endian
        let dataView = new DataView(buffer.buffer);
        let floatValue = dataView.getFloat32(0, true); // Convert to float (little-endian)
        target[lastKey] = Math.round(floatValue * 100) / 100; // Round to 2 decimals
    }
}

// Validate that the array exists
if (
    msg.payload.subMessage_1 &&
    Array.isArray(msg.payload.subMessage_1)
) {
    // Automatically find the element with the largest NestedsubMessage_1 (by number of keys)
    let selectedElement = msg.payload.subMessage_1.reduce((largest, current) => {
        const currentSize = current?.NestedsubMessage_1 ? Object.keys(current.NestedsubMessage_1).length : 0;
        const largestSize = largest?.NestedsubMessage_1 ? Object.keys(largest.NestedsubMessage_1).length : 0;
        return currentSize > largestSize ? current : largest;
    }, null);

    if (selectedElement) {
        // Loop through the variables and convert them for the selected element
        variablesToConvert.forEach(path => {
            convertFixed32ToFloat(selectedElement, path);
        });

        // Flatten the selected element for output
        msg.payload = {
            ...selectedElement.NestedsubMessage_1
        };
    } else {
        msg.payload = { error: "No valid element found in subMessage_1." };
    }
} else {
    // Handle the case where the array is invalid
    msg.payload = {
        error: "subMessage_1 is not a valid array."
    };
}

// Return the flattened object as the payload
return msg;
syntax = "proto3";

message MessageFromJson {

    repeated subMessage_1SubMsg sub_Message_1 = 1;

    message NestedsubMessage_1SubMsg {

            fixed32 battery_level = 262;
            int32 target = 8;
            selfpowered_nested selfpowered_106 = 106;
            fixed32 ac_power = 54;
            fixed32 ac_out = 368;

    }

    message subMessage_1SubMsg {

        NestedsubMessage_1SubMsg Nestedsub_Message_1 = 1;

    }

    message selfpowered_nested {
        int32 int_1 = 1;
    }
}

@phoniclynx
Copy link

I changed the protobug message from "repeated subMessage_1SubMsg sub_Message_1 = 1;" to "repeated subMessage_1SubMsg subMessage_1 = 1;" and I seem to get a different result... this seems to be the only place I can find the difference between the errors above
image

@phoniclynx
Copy link

phoniclynx commented Apr 10, 2025

Sorry about all the messages... but I found another error but stuck after that (so far).
Proto:

NestedsubMessage_1SubMsg Nestedsub_Message_1 = 1;

should be

NestedsubMessage_1SubMsg NestedsubMessage_1 = 1;

Now it's giving me the correct values:
image

Should this be now, then for each element:

payload.acOut

I do have a request... How can I get the values for the SOLAR inputs.. 2 DC inputs don't show up in your MQTT here
Screenshot_20250410_102540

@nalditopr
Copy link
Author

@phoniclynx

I just updated the gist with my latest workflow. not sure what's wrong to be honest, its all working for me and it auto updates the array value each time it changes, its been solid for more than a month after implementing the new parser.

@phoniclynx
Copy link

image
The two DC inputs are not there in this flow

@nalditopr
Copy link
Author

@phoniclynx adding more values is a matter of using the debug nodes to capture the get_reply json and throw that in a protobuf parser.

https://protobuf-decoder.netlify.app/

once you see the json, find the corresponding value. For example, lets say you know the solar input is 100w, then you search for that value and then its a matter of defining it on the protobuf. I am making it sound simple but its a lot of reverse engineering and looking at outputs, ect...

@phoniclynx
Copy link

Ok so if that is the case looking at that this would be here.. how do I put this into the proto? I don't quite know what I'm looking for?
image

@phoniclynx
Copy link

I'm not sure I'm getting all the values or even if the value above is what I think it is.. it's close but it seems to be DC1 and DC2 added together.. but right now I don't have any AC in either so it could be all W in.

This is my debug:

Co4ECoQECAAdAABdQyUAAAtDKIABOAFAMk0AAAAAVQAAAABdAACAv2UAAAAAaA5wDngOgAEOiAEAkAGsApgBAKAB0AWwAQC4AQrIAQDwAQGIAgStAgAAAADoAgTwAg74AgStAwAAAAC1AwAAAADoAwHwAzK1BPoRUUOABQCIBQCQBQDgBwHqByAKBggBEAEYCAoGCAEQAxgKCgYIAhABGAgKBggCEAMYCqgIhAeyCBJBdXN0cmFsaWEvQWRlbGFpZGW4CADCCAwKBAgBEAgKBAgDEArKCADgCADyCAD4CACACQqICQCQCQCYCQDACQLICQH1CQAA0EGwCwCYDADQDAGIDfQDmA0yoA0AqA0A2g0AkA4A8A6IDpUPLfG7Qp0PAADIQsAPoJwB8A+zLvgP7wGQECGYECKgECSoECa1EKTwu0K9EAAAyELgELMu6BDvAfAQX/gQBYARCogRX5ARAJgRAcgRAtARAugRAPARAM0SAAAAAKAWCMAWDs0W0JVIQdAWAdgWAuAWAegWCPAWPfgWDoUXcdAHw8oYAggB2BgA4BgA8BkOqBoBsBoCuBoAwBoAzRoAAAAA0BoA2BoA4BoA8BoB+BoAghsSChAAAAAAAAAAAAAAAAAAAAAAihsAkBsBmBsAoBsBqBsAsBsAkBwA2ByIDuAc9APoHDLwHIAImB0AoB0AqB0AEAJA/gFIFQr6AgrxAggAEAEYAiAAKLyAgBAwXjitogNAnAFIIlABWKCcAWDqkgFooJwBcDV4ZIABmhqIAfsZkAEimAEhoAEmqAEksAEAuAEDwAHQD80BU/G7QtABCNgBAOABsB3oAQPwAQD4AR+AAhCKAiCZGpkalhqNGpcamBqAGpcamhr7GZcamRqJGpkamhqRGpACBJoCBCIhIiKiAgZWMS4wLjGoAoYCsAL//wO6AhAwMDAwMDAwMDAwMDAwMDAwwAJPyAIC1QIzObpC3QI0C4E+5QJ7FbpC6AL/////D/AC...

It seems to have "items left over" and there is also an error message in NodeRed "Wire format is invalid: Error: invalid wire type 6 at offset 550"

@nalditopr
Copy link
Author

nalditopr commented Apr 10, 2025

@phoniclynx I dont think that is the value for dc input as on mine that one has data, and I dont have dc input.

But lets say that is the one.

You will modify the protobuf as such;

    syntax = "proto3";
      
      message MessageFromJson {
      
          repeated subMesssage_1SubMsg sub_messsage_1 = 1;
      
          message NestedsubMesssage_1SubMsg {
      
                  fixed32 battery_level = 262;
                  int32 target = 8;
                  selfpowered_nested selfpowered_106 = 106;
                  fixed32 ac_power = 54;
                  fixed32 ac_out = 368;
                  fixed32 dc_in = 3;             // THIS IS THE NEW VALUE
      
          }
      
          message subMesssage_1SubMsg {
      
              NestedsubMesssage_1SubMsg Nestedsub_messsage_1 = 1;
      
          }
      
          message selfpowered_nested {
              int32 int_1 = 1;
          }
      }

@phoniclynx
Copy link

I think 3 might be the Total Input, and 4 is the Total Output (AC and DC).

It doesn't seem to be liking that in the protobuf file
image

If I comment that new line out it will parse it ok

@phoniclynx
Copy link

phoniclynx commented Apr 10, 2025

Also, the AC Out value is negative. Should that not be positive?
image

I know it shows up as negative in the protobuf, but I there any way of converting it to positive as HA doesn't like the value being negative in the Energy page:
397-403 368 fixed32
As int: -1023039032
As uint: 3271928264
As float: -133.6632080078125

@phoniclynx
Copy link

This is the readout of the error there:
image

@nalditopr
Copy link
Author

@phoniclynx you might need to split the positive and negatives values with helper entities, there is a writeup about it here. https://community.home-assistant.io/t/rewritten-tesla-style-solar-power-card/294466/22?page=2
home-assistant/core#124671

"To extract the positive value from grid_power I wound up using {{ [ states('sensor.my_home_grid_power')|float(0), 0.0 ] | max }}, which because I am not fluent in the language used, I had to adapt from a search result. The method to convert a negative value into a positive value I wound up using was {{ [ ( -1 * states('sensor.my_home_grid_power')|float(0)), 0.0 ] | max }}."

@phoniclynx
Copy link

phoniclynx commented Apr 10, 2025

That might not be such a major issue as these other two in 3 and 4 seem to be the values I want.. however I can't confirm because there is too much sun. But as you said you have the values it should be a pretty good guess.

I am still having those same problems with the protobuf saying it's invalid which it shouldn't be :\

syntax = "proto3";

message MessageFromJson {

    repeated subMessage_1SubMsg subMessage_1 = 1;

    message NestedsubMessage_1SubMsg {

            fixed32 battery_level = 262;
            int32 target = 8;
            selfpowered_nested selfpowered_106 = 106;
            fixed32 ac_power = 54;
            fixed32 ac_out = 368;
            fixed32 batt_in = 3;
            fixed32 batt_out = 4;
            fixed32 dcone_in = 361;
            fixed32 dctwo_in = 70;

    }

    message subMessage_1SubMsg {

        NestedsubMessage_1SubMsg NestedsubMessage_1 = 1;

    }

    message selfpowered_nested {
        int32 int_1 = 1;
    }
}

Javascript:

  // Array of variables to convert (define the path to each variable as a string, excluding the array index)
  let variablesToConvert = [
    "NestedsubMessage_1.batteryLevel",
    "NestedsubMessage_1.acPower",
    "NestedsubMessage_1.acOut",
    "NestedsubMessage_1.battIn",
    "NestedsubMessage_1.battOut",
    "NestedsubMessage_1.dcOneIn",
    "NestedsubMessage_1.dcTwoIn"
];

Can you see my mistake at all?

@phoniclynx
Copy link

I'm stumped. I've been at this for a few hours and not getting any closer
image

@phoniclynx
Copy link

I changed it ever so slightly and have dcOneIn working but the others to me look the same yet they cause the error above if I uncomment them

syntax = "proto3";

message MessageFromJson {

    repeated subMessage_1SubMsg subMessage_1 = 1;

    message NestedsubMessage_1SubMsg {

            fixed32 battery_level = 262;
            int32 target = 8;
            selfpowered_nested selfpowered_106 = 106;
            fixed32 ac_power = 54;
            fixed32 ac_out = 368;
//            fixed32 battIn = 3;
//            fixed32 battOut = 4;
            fixed32 dcOneIn = 361;
//            fixed32 dcTwoIn = 70;

    }

    message subMessage_1SubMsg {

        NestedsubMessage_1SubMsg NestedsubMessage_1 = 1;

    }

    message selfpowered_nested {
        int32 int_1 = 1;
    }
}

@phoniclynx
Copy link

phoniclynx commented Apr 10, 2025

"fixed32 dcTwoIn = 70;" gives an error: Wire format is invalid: RangeError: index out of range: 1261 + 10 > 1261

110-116	70	fixed32	
As int: 0
As float: 0

"fixed32 dcOneIn = 361;" seems to work fine

373-379	361	fixed32	
As int: 0
As float: 0

They both look the same "fixed32" but for some reason, it can't decode it

"fixed32 battIn = 3;" gives an error: Wire format is invalid: Error: invalid wire type 4 at offset 548

2-7	3	fixed32	
As int: 0
As float: 0

"fixed32 battOut = 4;" seems to work fine. However, interestingly, it wasn't working when I started this post, but now it's working fine (I hope it stays that way)........... having said that.. sometimes it works and then it stops for a few mins then starts working again: Wire format is invalid: RangeError: index out of range: 1257 + 10 > 1257

7-12	4	fixed32	
As int: 1124597760
As float: 136

@nalditopr
Copy link
Author

I connected a 12v power supply and was able to decode dc_in_02 , 01 does not work, still checking.

    syntax = "proto3";
    
    message MessageFromJson {
    
        repeated subMessage_1SubMsg sub_message_1 = 1;
    
        message NestedsubMessage_1SubMsg {
    
            optional fixed32 battery_level = 262;
            optional int32 target = 8;
            optional fixed32 ac_power = 54;
            optional fixed32 ac_out = 368;
            //optional fixed32 dc_in_01 = 70;
            optional fixed32 dc_in_02 = 361;
    
        }
    
        message subMessage_1SubMsg {
    
            NestedsubMessage_1SubMsg Nestedsub_message_1 = 1;
    
        }
    }

@nalditopr
Copy link
Author

nalditopr commented Apr 10, 2025

@phoniclynx The root cause is that the message coming from ecoflow has some nesting in the protobuf structure that I have not been able to parse.

for example, dc_input 1 is located at position 70 as fixed 32, but on the next value of the array, position 70 has a string message, this causes it to fail decoding.

the other values do not have this problem and parse just fine.

fwiw, value 3 is combined dc input, 70 is dc_01 and 361 is dc_02.

@phoniclynx
Copy link

phoniclynx commented Apr 11, 2025

Did you mean 70 is dc_02 and 361 is dc_01? That's what I worked out on mine.

I'm guessing you need to parse the protobuf file differently?

I've also noticed a small error in the way you've set up the sensors. Category and Last Reset should be blank: (According to this: HA Forum Link - but I could be wrong)
image

However, Last Reset should be filled out here: (If not, you are not able to use it in the energy pages)
image

I'm not too sure if the actual date means anything or if it needs to be calculated elsewhere for some reason. But it does stop the Energy pages from throwing up an error message.

The final step is to get that protobuf nesting solved; then, it should work quite nicely. Until we find a different error LOL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment