Felicity Solar per API abfragen

Ich habe einen 12,5kWh Akku von Felicity und kann bestätigen dass der genau so lokal angesprochen werden kann wie der WR, konnte den NR Flow einfach pasten.

Was ich noch geändert habe:
Habe den Inject node “get dev real infor” auf ein 5s interval gesetzt. Das JSON ergebnis des TCP calls sende ich in einen MQTT Out node, somit hat man schonmal direkt alle werte in HA verfügbar.

Wer alle werte unter einen device bündeln möchte kann dann zusätzlich noch die MQTT auto discovery messages senden, sieht dann so aus:

hier ein Beispiel solch einer discovery message die man ebenfalls in einen MQTT out node schicken muss:

Payload:

{
    "unique_id": "soc",
    "name": "State of Charge",
    "state_topic": "battery/state",
    "value_template": "{{ (value_json.Batsoc[0][0] / 100) | float }}",
    "unit_of_measurement": "%",
    "device_class": "battery",
    "device": {
        "identifiers": [
            "battery_fs1"
        ],
        "name": "Solar Battery FS1",
        "model": "48V LiFePO4 12.5kWh",
        "manufacturer": "Felicity Solar"
    }
}

Topic: homeassistant/sensor/battery_fs1/soc/config

Diese messages sollte man auf persist setzen, damit die sensoren erhalten bleiben

Hallo Mulder,
erstmal vielen Dank für deine Info nur leider ist das nun recht viel für mich.

  1. Schritt wäre die NodeRED
[
    {
        "id": "5c0b35da34348aee",
        "type": "tab",
        "label": "Daten holen",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "c50808832b04496e",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "get dev set infor",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "devsetinfor",
        "payload": "wifilocalMonitor:get dev set infor",
        "payloadType": "str",
        "x": 300,
        "y": 300,
        "wires": [
            [
                "bc737b9b2149196a"
            ]
        ]
    },
    {
        "id": "0912f67552aa3207",
        "type": "debug",
        "z": "5c0b35da34348aee",
        "name": "debug 2",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1020,
        "y": 300,
        "wires": []
    },
    {
        "id": "bc737b9b2149196a",
        "type": "tcp request",
        "z": "5c0b35da34348aee",
        "name": "",
        "server": "192.168.178.52",
        "port": "53970",
        "out": "time",
        "ret": "string",
        "splitc": "1000",
        "newline": "",
        "trim": false,
        "tls": "",
        "x": 770,
        "y": 300,
        "wires": [
            [
                "0912f67552aa3207",
                "025394cdf4e55bad"
            ]
        ]
    },
    {
        "id": "f6474b25abdd27bb",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "get dev basice infor",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "devbasiceinfor",
        "payload": "wifilocalMonitor:get dev basice infor",
        "payloadType": "str",
        "x": 310,
        "y": 360,
        "wires": [
            [
                "bc737b9b2149196a"
            ]
        ]
    },
    {
        "id": "cde5658634725368",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "get dev real infor",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "devrealinfor",
        "payload": "wifilocalMonitor:get dev real infor",
        "payloadType": "str",
        "x": 300,
        "y": 420,
        "wires": [
            [
                "bc737b9b2149196a"
            ]
        ]
    },
    {
        "id": "eca69a13889ce1ca",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "get Date",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "getdate",
        "payload": "wifilocalMonitor:get Date",
        "payloadType": "str",
        "x": 280,
        "y": 480,
        "wires": [
            [
                "bc737b9b2149196a"
            ]
        ]
    },
    {
        "id": "239574fd2adcb9d6",
        "type": "function",
        "z": "5c0b35da34348aee",
        "name": "global set devsetinfor",
        "func": "global.set(\"devsetinfor\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 360,
        "wires": [
            []
        ]
    },
    {
        "id": "75a9f5db9ca67c96",
        "type": "function",
        "z": "5c0b35da34348aee",
        "name": "global set devrealnfor",
        "func": "global.set(\"devrealinfor\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 480,
        "wires": [
            []
        ]
    },
    {
        "id": "c0a5ac693bd048d5",
        "type": "comment",
        "z": "5c0b35da34348aee",
        "name": "Hilfe",
        "info": "Die IP des Wechselrichters ist zu ersetzen!",
        "x": 770,
        "y": 240,
        "wires": []
    },
    {
        "id": "025394cdf4e55bad",
        "type": "switch",
        "z": "5c0b35da34348aee",
        "name": "",
        "property": "topic",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "devsetinfor",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "devbasiceinfor",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "devrealinfor",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "getdate",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 4,
        "x": 990,
        "y": 400,
        "wires": [
            [
                "239574fd2adcb9d6"
            ],
            [
                "d7b0e7de725a8d9a"
            ],
            [
                "75a9f5db9ca67c96"
            ],
            [
                "f44666bb6637c7e6"
            ]
        ]
    },
    {
        "id": "d7b0e7de725a8d9a",
        "type": "function",
        "z": "5c0b35da34348aee",
        "name": "global set devbasiceinfor",
        "func": "global.set(\"devbasiceinfor\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1250,
        "y": 420,
        "wires": [
            []
        ]
    },
    {
        "id": "f44666bb6637c7e6",
        "type": "function",
        "z": "5c0b35da34348aee",
        "name": "global get Date",
        "func": "global.set(\"getdate\",msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1220,
        "y": 540,
        "wires": [
            []
        ]
    },
    {
        "id": "9b7b42abcd132849",
        "type": "tab",
        "label": "Softwarestand",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "039c95c2c8c00770",
        "type": "inject",
        "z": "9b7b42abcd132849",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 100,
        "y": 80,
        "wires": [
            [
                "d48914c3b9458516"
            ]
        ]
    },
    {
        "id": "292822f5736e2cfb",
        "type": "debug",
        "z": "9b7b42abcd132849",
        "name": "debug 4",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "jsonata",
        "statusVal": "",
        "statusType": "auto",
        "x": 720,
        "y": 80,
        "wires": []
    },
    {
        "id": "dc45a99a2e88dde6",
        "type": "json",
        "z": "9b7b42abcd132849",
        "name": "",
        "property": "payload",
        "action": "",
        "pretty": false,
        "x": 530,
        "y": 80,
        "wires": [
            [
                "292822f5736e2cfb"
            ]
        ]
    },
    {
        "id": "d48914c3b9458516",
        "type": "function",
        "z": "9b7b42abcd132849",
        "name": "Device Basic Informations",
        "func": "msg.payload = global.get(\"devbasiceinfor\");\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 310,
        "y": 80,
        "wires": [
            [
                "dc45a99a2e88dde6"
            ]
        ]
    },
    {
        "id": "8fc43c6757c73477",
        "type": "tab",
        "label": "Geraeteeinstellungen",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "b4dad6a5d908b026",
        "type": "debug",
        "z": "8fc43c6757c73477",
        "name": "debug 8",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "jsonata",
        "statusVal": "",
        "statusType": "auto",
        "x": 1080,
        "y": 80,
        "wires": []
    },
    {
        "id": "4e668195a001e8c5",
        "type": "debug",
        "z": "8fc43c6757c73477",
        "name": "debug 9",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1080,
        "y": 160,
        "wires": []
    },
    {
        "id": "d921bc1f71291e48",
        "type": "json",
        "z": "8fc43c6757c73477",
        "name": "",
        "property": "payload",
        "action": "",
        "pretty": false,
        "x": 910,
        "y": 80,
        "wires": [
            [
                "b4dad6a5d908b026"
            ]
        ]
    },
    {
        "id": "da47b5d64a1e5ce1",
        "type": "json",
        "z": "8fc43c6757c73477",
        "name": "",
        "property": "payload",
        "action": "",
        "pretty": true,
        "x": 920,
        "y": 160,
        "wires": [
            [
                "4e668195a001e8c5"
            ]
        ]
    },
    {
        "id": "9862b51a9e73dc3b",
        "type": "inject",
        "z": "8fc43c6757c73477",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 140,
        "y": 80,
        "wires": [
            [
                "baab2536e7f2ee58"
            ]
        ]
    },
    {
        "id": "baab2536e7f2ee58",
        "type": "function",
        "z": "8fc43c6757c73477",
        "name": "Device Set Informations",
        "func": "msg.payload = global.get(\"devsetinfor\");\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 350,
        "y": 80,
        "wires": [
            [
                "56ad239c495a411e"
            ]
        ]
    },
    {
        "id": "19d5056e9ea0eecc",
        "type": "function",
        "z": "8fc43c6757c73477",
        "name": "Array[0]",
        "func": "msg.payload = msg.payload[0]+ \"}\";\n\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 740,
        "y": 80,
        "wires": [
            [
                "d921bc1f71291e48"
            ]
        ]
    },
    {
        "id": "10263c8e2b9b12e2",
        "type": "function",
        "z": "8fc43c6757c73477",
        "name": "Array[1]",
        "func": "msg.payload = \"{\" + msg.payload[1];\n\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 740,
        "y": 160,
        "wires": [
            [
                "da47b5d64a1e5ce1"
            ]
        ]
    },
    {
        "id": "56ad239c495a411e",
        "type": "string",
        "z": "8fc43c6757c73477",
        "name": "",
        "methods": [
            {
                "name": "split",
                "params": [
                    {
                        "type": "str",
                        "value": "}{"
                    },
                    {
                        "type": "num",
                        "value": "300000"
                    }
                ]
            }
        ],
        "prop": "payload",
        "propout": "payload",
        "object": "msg",
        "objectout": "msg",
        "x": 550,
        "y": 80,
        "wires": [
            [
                "19d5056e9ea0eecc",
                "10263c8e2b9b12e2"
            ]
        ]
    },
    {
        "id": "61f50c1675d21aa1",
        "type": "tab",
        "label": "Daten Echtzeit",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "ca486dac92734db2",
        "type": "inject",
        "z": "61f50c1675d21aa1",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 100,
        "y": 120,
        "wires": [
            [
                "7d6245613e3e6c6f"
            ]
        ]
    },
    {
        "id": "7d6245613e3e6c6f",
        "type": "function",
        "z": "61f50c1675d21aa1",
        "name": "Real Informations",
        "func": "msg.payload = global.get(\"devrealinfor\");\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 310,
        "y": 120,
        "wires": [
            [
                "d315b42003b16b73"
            ]
        ]
    },
    {
        "id": "d315b42003b16b73",
        "type": "string",
        "z": "61f50c1675d21aa1",
        "name": "",
        "methods": [
            {
                "name": "split",
                "params": [
                    {
                        "type": "str",
                        "value": "}{"
                    },
                    {
                        "type": "num",
                        "value": "10000"
                    }
                ]
            }
        ],
        "prop": "payload",
        "propout": "payload",
        "object": "msg",
        "objectout": "msg",
        "x": 510,
        "y": 120,
        "wires": [
            [
                "43307e9bbebd8c86",
                "be197eaa5b35810b"
            ]
        ]
    },
    {
        "id": "5a62ece942b21929",
        "type": "debug",
        "z": "61f50c1675d21aa1",
        "name": "debug 17",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "jsonata",
        "statusVal": "",
        "statusType": "auto",
        "x": 1080,
        "y": 120,
        "wires": []
    },
    {
        "id": "6f56b8ba3066bd32",
        "type": "debug",
        "z": "61f50c1675d21aa1",
        "name": "debug 18",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1080,
        "y": 200,
        "wires": []
    },
    {
        "id": "43307e9bbebd8c86",
        "type": "function",
        "z": "61f50c1675d21aa1",
        "name": "Array[0]",
        "func": "msg.payload = msg.payload[0]+ \"}\";\n\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 700,
        "y": 120,
        "wires": [
            [
                "e28b55691b720a70"
            ]
        ]
    },
    {
        "id": "e28b55691b720a70",
        "type": "json",
        "z": "61f50c1675d21aa1",
        "name": "",
        "property": "payload",
        "action": "",
        "pretty": false,
        "x": 890,
        "y": 120,
        "wires": [
            [
                "5a62ece942b21929"
            ]
        ]
    },
    {
        "id": "be197eaa5b35810b",
        "type": "function",
        "z": "61f50c1675d21aa1",
        "name": "Array[1]",
        "func": "msg.payload = \"{\" + msg.payload[1];\n\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 700,
        "y": 200,
        "wires": [
            [
                "d8da03b24201531d"
            ]
        ]
    },
    {
        "id": "d8da03b24201531d",
        "type": "json",
        "z": "61f50c1675d21aa1",
        "name": "",
        "property": "payload",
        "action": "",
        "pretty": true,
        "x": 880,
        "y": 200,
        "wires": [
            [
                "6f56b8ba3066bd32"
            ]
        ]
    },
    {
        "id": "155723a7a498260e",
        "type": "tab",
        "label": "Uhrzeit",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "f975745e9b37e261",
        "type": "inject",
        "z": "155723a7a498260e",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 100,
        "y": 100,
        "wires": [
            [
                "4e780b11deca9d16"
            ]
        ]
    },
    {
        "id": "4e780b11deca9d16",
        "type": "function",
        "z": "155723a7a498260e",
        "name": "Get Date",
        "func": "msg.payload = global.get(\"getdate\");\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 280,
        "y": 100,
        "wires": [
            [
                "8a6772914449867f"
            ]
        ]
    },
    {
        "id": "1f608bef2a8420be",
        "type": "debug",
        "z": "155723a7a498260e",
        "name": "debug 20",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "jsonata",
        "statusVal": "",
        "statusType": "auto",
        "x": 660,
        "y": 100,
        "wires": []
    },
    {
        "id": "8a6772914449867f",
        "type": "json",
        "z": "155723a7a498260e",
        "name": "",
        "property": "payload",
        "action": "",
        "pretty": false,
        "x": 470,
        "y": 100,
        "wires": [
            [
                "1f608bef2a8420be"
            ]
        ]
    }
]

Hier mal zur Verständnis, kann man hier Prüfen ob man Daten empfängt ?

  1. Schritt Eintrag in die Sensor.yaml, wenn ich die Daten so eintrage mit berücksichtigung der IP Adresse bekommen ich Fehler

Konfigurationswarnungen

Integration error: sensors - Integration ‘sensors’ not found.

- name: Felicity Solar Inverter
   type: rtuovertcp
   host: 192.168.2.177
   port: 1502
   sensors:
   - name: "Felicity Working Mode"
     slave: 1
     address: 4353
     input_type: holding
     data_type: int16
     scale: 1
     unit_of_measurement: ""
     unique_id: felicity_working_mode
     # Possible Values: 0 (Standby), 1 (CC Mode), 2 (CV Mode), 3 (CF Mode)

   - name: "Felicity Fault Code"
     slave: 1
     address: 4360
     input_type: holding
     data_type: int16
     scale: 0.1
     precision: 1
     unit_of_measurement: "V"
     device_class: "voltage"
     unique_id: felicity_fault_code

   - name: "Felicity Battery Capacity"
     slave: 1
     address: 4368
     input_type: holding
     data_type: int16
     scale: 1
     precision: 1
     unit_of_measurement: "%"
     device_class: "power"
     unique_id: felicity_battery_capacity

   - name: "Felicity Load Percentage"
     slave: 1
     address: 4374
     input_type: holding
     data_type: int16
     scale: 0.1
     precision: 1
     unit_of_measurement: "%"
     device_class: "power"
     unique_id: felicity_load_percentage

   - name: "Felicity Total AC input power"
     slave: 1
     address: 4392
     input_type: holding
     data_type: int16
     scale: 0.1
     precision: 1
     unit_of_measurement: "Wh"
     device_class: "energy"
     unique_id: felicity_total_AC_input_power

   - name: "Felicity Total AC output active power"
     slave: 1
     address: 4404
     input_type: holding
     data_type: int32
     scale: 1
     unit_of_measurement: "Wh"
     device_class: "energy"
     unique_id: felicity Total_AC_output_active_power
     
   - name: "Felicity Total SoC"
     slave: 1
     address: 4624
     input_type: holding
     data_type: int16
     scale: 1
     unit_of_measurement: "%"
     device_class: "battery"
     unique_id: felicity_total_soc  
     
   - name: "Felicity PV generated inquiry day"
     slave: 1
     address: 4446
     input_type: holding
     data_type: int32
     scale: 1
     unit_of_measurement: "V"
     device_class: "voltage"
     unique_id: felicity_pv_generated_inquiry_day

   - name: "Felicity AC generated inquiry day"
     slave: 1
     address: 4476
     input_type: holding
     data_type: int32
     scale: 1
     unit_of_measurement: "V"
     device_class: "voltage"
     unique_id: felicity_ac_generated_inquiry_day

Könnte hier man was Prüfen zwecks empfangen der Daten ?

Um zu prüfen ob man Daten empfängt, muss man lediglich den debug node aktivieren der bereits in dem hier geposteten flow vorhanden ist :wink:

Die Integrationder Sensoren regle ich anders, rtuovertcp scheint eine Modbus Integration zu sein, nutze ich bei mir nicht, ich schicke die Werte aus dem NodeRed flow direkt an den HA MQTT Server.

Hier mein vereinfachter flow:

[
    {
        "id": "4b760d7a09844df3",
        "type": "debug",
        "z": "5c0b35da34348aee",
        "name": "debug 3",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1680,
        "y": 540,
        "wires": []
    },
    {
        "id": "e326d50d35e9169d",
        "type": "tcp request",
        "z": "5c0b35da34348aee",
        "name": "",
        "server": "192.168.0.179",
        "port": "53970",
        "out": "time",
        "ret": "string",
        "splitc": "1000",
        "newline": "",
        "trim": false,
        "tls": "",
        "x": 1430,
        "y": 580,
        "wires": [
            [
                "4b760d7a09844df3",
                "04cefcaf7c8a8a03"
            ]
        ]
    },
    {
        "id": "3ceb89c7968a0d5a",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "get dev real infor",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "devrealinfor",
        "payload": "wifilocalMonitor:get dev real infor",
        "payloadType": "str",
        "x": 1180,
        "y": 580,
        "wires": [
            [
                "e326d50d35e9169d"
            ]
        ]
    },
    {
        "id": "04cefcaf7c8a8a03",
        "type": "mqtt out",
        "z": "5c0b35da34348aee",
        "name": "",
        "topic": "battery/state",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "7fa3f1d811f67597",
        "x": 1690,
        "y": 620,
        "wires": []
    },
    {
        "id": "7fa3f1d811f67597",
        "type": "mqtt-broker",
        "name": "",
        "broker": "192.168.0.106",
        "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": ""
    }
]

und zum registrieren der sensoren brauchst du jeweils so einen flow, den du genau einmal pro sensor injecten musst:

[
    {
        "id": "eac8ad0b4511734a",
        "type": "mqtt out",
        "z": "5c0b35da34348aee",
        "name": "",
        "topic": "",
        "qos": "",
        "retain": "true",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "7fa3f1d811f67597",
        "x": 1310,
        "y": 900,
        "wires": []
    },
    {
        "id": "4b760da5cbf25877",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure SoC",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/soc/config",
        "payload": "{\"unique_id\":\"soc\",\"name\":\"State of Charge\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ (value_json.Batsoc[0][0] / 100) | float }}\",\"unit_of_measurement\":\"%\",\"device_class\":\"battery\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 1110,
        "y": 900,
        "wires": [
            [
                "eac8ad0b4511734a"
            ]
        ]
    },
    {
        "id": "7fa3f1d811f67597",
        "type": "mqtt-broker",
        "name": "",
        "broker": "192.168.0.106",
        "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": ""
    }
]

keine config in yaml notwendig. Wenn dir da noch kentnisse fehlen, schlage ich vor ein paar basic videos zu Node Red und HA zu schauen.

Das mit rtuovertcp ist war als Alternative gedacht. Und funktioniert auch nur am COM-Port mit den Pins 3 & 4 der RS485-Schnittstelle. Das hat mit der NodeRED Variante überhaupt nichts zu tun, null Übereinstimmung dazu. Eine Vermischung mit dem anderen macht alles eventuell nur unverständlicher und komplizierter. Das wollte ich nicht.

noch was Schönes : anscheinend ist es mir gelungen, dass Felicity eingesehen hat, dass der Zugriff via API etwas kompliziert ist und weil sie zugegeben haben, noch keine Erfahrung über Modbus via TCP zu haben und in Erwägung ziehen, das ebenfalls freizugeben, soll ich Ihnen Beispiele zuspielen und so zeigen, wie einfach das dann wird und was damit alles möglich ist via Modbus und TCP. Das hatte ich so nicht erwartet, aber da es viele Leute mit Problemen gibt den Felicity Wechselrichter anzubinden, ist das doch eine gute und erstaunliche Entwicklung.

Dann muss man meine rtuovertcp-Anpassung etwas anpassen, aber dann geht auch das.Vielleicht wird so meine Vorarbeit noch ganz nützlich.

Hi Slauf,

also deine NodRed variante habe ich bei mir eingefügt habe auch die IPadresse (vom WE) getauscht.

Jetzt müsste ich nur noch die Daten am besten in Mqtt bringen → liege ich hier richtig ?


Hi Mulder,
vielen Dank für den Flow und das Beispiel für den SOC.
Genau soweit klappt es auch bei mir.
Doch ich scheitere an den restlichen Sensoren.
Hast du zufällig weitere Beispiele, die du zur Verfügung stellen kannst?

Vielen Dank.

Hier sind alle Sensor Setups die ich aus dem Akku ziehe, hoffe das hilft:

[
    {
        "id": "503fcd02369cafa6",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure SoC",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/soc/config",
        "payload": "{\"unique_id\":\"soc\",\"name\":\"State of Charge\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ (value_json.Batsoc[0][0] / 100) | round(0) }}\",\"unit_of_measurement\":\"%\",\"device_class\":\"battery\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 130,
        "y": 360,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "79ae1cecaba1da96",
        "type": "mqtt out",
        "z": "5c0b35da34348aee",
        "name": "",
        "topic": "",
        "qos": "",
        "retain": "true",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "7fa3f1d811f67597",
        "x": 510,
        "y": 620,
        "wires": []
    },
    {
        "id": "b6d5906ac37a8c06",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure Voltage",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_voltage/config",
        "payload": "{\"unique_id\":\"fs1_batt_voltage\",\"name\":\"Battery Voltage\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ (value_json.Batt[0][0] / 1000) | float }}\",\"unit_of_measurement\":\"V\",\"device_class\":\"voltage\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 140,
        "y": 400,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "d4605dbad9fefef4",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure Current",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_current/config",
        "payload": "{\"unique_id\":\"fs1_batt_current\",\"name\":\"Battery Current\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ (value_json.Batt[1][0] / 10) | float }}\",\"unit_of_measurement\":\"A\",\"device_class\":\"current\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 140,
        "y": 440,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "771b51c9d45f1389",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure Power",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_power/config",
        "payload": "{\"unique_id\":\"fs1_batt_power\",\"name\":\"Battery Power\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ (((value_json.Batt[0][0] / 1000) * (value_json.Batt[1][0] / 10)) | round(0)) }}\",\"unit_of_measurement\":\"W\",\"device_class\":\"power\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 140,
        "y": 480,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "3901dea156d095bd",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure Temp",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_temp/config",
        "payload": "{\"unique_id\":\"fs1_batt_temp\",\"name\":\"Battery Temperature\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ (value_json.BTemp[0][0] / 10) | round(1) }}\",\"unit_of_measurement\":\"°C\",\"device_class\":\"temperature\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 140,
        "y": 520,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "d5fd07a6cb87ca79",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure Fault",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_fault/config",
        "payload": "{\"unique_id\":\"fs1_batt_fault\",\"name\":\"Battery Fault\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ 1 if value_json.Bfault > 0 else 0 }}\",\"device_class\":\"problem\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 140,
        "y": 560,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "e0e762ac6f6658ad",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure Warning",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_warning/config",
        "payload": "{\"unique_id\":\"fs1_batt_warning\",\"name\":\"Battery Warning\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ 1 if value_json.Bwarn > 0 else 0 }}\",\"device_class\":\"problem\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 150,
        "y": 600,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "0cfcb636419c460e",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure State",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_state/config",
        "payload": "{\"unique_id\":\"fs1_batt_state\",\"name\":\"Battery State\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ 'Full' if value_json.Estate == 320 else 'Standby' if value_json.Estate == 960 else 'Charging' if value_json.Estate == 9152 else 'Discharging' if value_json.Estate == 5056 else 'Unknown: ' + value_json.Estate | string }}\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 140,
        "y": 640,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "b4de60bbcd4f510c",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure MaxCellV",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_max_cell_voltage/config",
        "payload": "{\"unique_id\":\"fs1_batt_max_cell_voltage\",\"name\":\"Battery Max Cell Voltage\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ (value_json.BMaxMin[0][0] / 1000) | round(3) }}\",\"unit_of_measurement\":\"V\",\"device_class\":\"voltage\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 150,
        "y": 760,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "a71726262222d74c",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure MinCellV",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_mincv/config",
        "payload": "{\"unique_id\":\"fs1_batt_mincv\",\"name\":\"Battery Min Cell Voltage\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ (value_json.BMaxMin[0][1] / 1000) | round(3) }}\",\"unit_of_measurement\":\"V\",\"device_class\":\"voltage\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 150,
        "y": 800,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "08f66b39042986e4",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure Cell Drift",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_cell_drift/config",
        "payload": "{\"unique_id\":\"fs1_batt_cell_drift\",\"name\":\"Battery Cell Drift\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ ((value_json.BMaxMin[0][0] - value_json.BMaxMin[0][1]) / 1000) | round(3) }}\",\"unit_of_measurement\":\"V\",\"device_class\":\"voltage\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 150,
        "y": 840,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "20431280d8c41a43",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure Cell n Voltage",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_cell_3_voltage/config",
        "payload": "{\"unique_id\":\"fs1_batt_cell_3_voltage\",\"name\":\"Cell 3 Voltage\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ value_json.BatcelList[0][2] / 1000 }}\",\"unit_of_measurement\":\"V\",\"device_class\":\"voltage\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 160,
        "y": 880,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "924a6fac3859e750",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure charge limit",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_max_charge_current/config",
        "payload": "{\"unique_id\":\"fs1_batt_max_charge_current\",\"name\":\"Max Charge Current\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ (value_json.LVolCur[1][0] / 10) | round(0) }}\",\"unit_of_measurement\":\"A\",\"device_class\":\"current\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 160,
        "y": 680,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "0f4058f30eb00ed1",
        "type": "inject",
        "z": "5c0b35da34348aee",
        "name": "configure discharge limit",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "homeassistant/sensor/battery_fs1/fs1_batt_max_discharge_current/config",
        "payload": "{\"unique_id\":\"fs1_batt_max_discharge_current\",\"name\":\"Max Discharge Current\",\"state_topic\":\"battery/state\",\"value_template\":\"{{ (value_json.LVolCur[1][1] / 10) | round(0) }}\",\"unit_of_measurement\":\"A\",\"device_class\":\"current\",\"device\":{\"identifiers\":[\"battery_fs1\"],\"name\":\"Solar Battery FS1\",\"model\":\"48V LiFePO4 12.5kWh\",\"manufacturer\":\"Felicity Solar\"}}",
        "payloadType": "json",
        "x": 170,
        "y": 720,
        "wires": [
            [
                "79ae1cecaba1da96"
            ]
        ]
    },
    {
        "id": "7fa3f1d811f67597",
        "type": "mqtt-broker",
        "name": "",
        "broker": "192.168.0.106",
        "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": ""
    }
]

Das hilft sehr.
Besten Dank.

Hi,

damit ich das auch hinbekomme bei mir - was muss jetzt wohin genau ?
Liebe Grüße und danke für die Hilfe im Voraus !

Guten Morgen,
ich bekomme es nicht hin aus der IPAdresse:53970 die Daten abzufragen.
Hättest du da bitte mehr Infos?!

Ich versuche das auslesen aus Loxone zu realisieren mit einer ModBus Extension, außerdem habe ich auch noch einen Loxberry (RaspberryPi)
Danke

Hallo zusammen, wie ich sehe gibt es viele Fragezeichen hat jemand nun die Daten per API abgegriffen ? Wäre auch jemand bereit dieses in Schritt für Schritt darzustellen/erklären ?

Guten Morgen, klasse das es euch gibt!

Mein Problem ist eigentlich nur das die App den Wechselrichter nur alle 5 minuten abfragt.

Ich suche nach einer Lösung entweder am Handy oder mit nem tablet oder sowas in der Art die Daten des WR und des aktuellen Hausverbrauchs unkompliziert anzeigen zu lassen.

Habt ihr da eine unkomplizierte Idee?

Hello, sorry I do not speak german but through translation I was able to use the local api calls to get my inverter into Home Assistant. I even tweaked some parts and added some additional entities ( I will gladly share if someone is interested).
I am now trying to get settings values and maybe change settings of the inverter, but I couldn’t figure out anything when using wireshark. There is no local communication between the Fsolar app and the inverter, so all packets are encrypted.
Does anyone know what payload can be sent to obtain inverter settings (charging priority, discharge cutoff, etc…), or at least help me force the inverter into local mode so that I can sniff packets with wireshark?

Thank you so much.

Sorry we/I would be happy if I had the data such as Soc, String 1/2, charging power, unloading location in the HA

@mic233 Ich brauche mal deine Hilfe =)

Der flow in NodeRed läuft nur bedingt. Wenn ich das Debugging window offen habe, antwortet zwar mein WR aber nur bei einem Teil der anfragen. Sonst sind Fehler in der JSOn Datei. Wie kann das?

Schade das du den Beitrag gelöscht hast. Ich hatte es kurz am Handy gesehen und ja die Meldung kommt bei mir auch!

Was habt ihr einiger wie eingetragen ?

Moin, kann einen kleinen Erfolg vermelden.

Ich habe jetzt die sensor daten des Speichers.

Aber ich weiß noch nicht wie ich die Sensoren aus dem wechselrichter benennen soll. Könnt ihr mir da noch Tipps geben?

sorry I didn’t want to clutter the page here if it was not your problem. That error is because the response is providing two responses, 1 for inverter and 1 for battery.

I modified a lot of the flow, and made it user friendly. Feel free to import to your NodeRed, and follow the instructions. You need to modify 2 nodes only, and then click “Create Sensors”.

[{"id":"29c887befe280b70","type":"tab","label":"Felicity Inverter","disabled":true,"info":"","env":[]},{"id":"a30aaddd5daeb1b0","type":"group","z":"29c887befe280b70","name":"Get info from inverter locally","style":{"label":true,"color":"#bfbfbf","fill":"#bfdbef","fill-opacity":"0.3"},"nodes":["12db757824215eb8","46845906337ab6b4","a7c36b8bfb83e339","5d45a78e2721e0c3","2564482e9b2a3b42","7818c761c132ed8e","bf943deed6c1bedd","6178ae9e99148806","db09d1838d487e9b","e5e41351d3dcd6a1","e21f92a11cee4126","3632a32802b9c6c9","5c8734638ceb9137","ad91b5078af5d8c6","e69193f22ece2bfb","124f0aec0e4531b3","26442e839fd50b6a","5981cd3c46b7ae99"],"x":19,"y":334,"w":1272,"h":292},{"id":"e90aabdb500bb547","type":"group","z":"29c887befe280b70","name":"Additional Inverter Entities","style":{"fill":"#dbcbe7","label":true,"fill-opacity":"0.2"},"nodes":["1a4e3fee13ec8588"],"x":32,"y":657,"w":1056,"h":366},{"id":"1a4e3fee13ec8588","type":"group","z":"29c887befe280b70","g":"e90aabdb500bb547","name":"Estimate Battery Times","style":{"label":true},"nodes":["ae3dc6bbe23d7756","8cecb62f87f81e12"],"x":58,"y":683,"w":1004,"h":314},{"id":"ae3dc6bbe23d7756","type":"group","z":"29c887befe280b70","g":"1a4e3fee13ec8588","name":"Battery Runtime (Discharge)","style":{"label":true},"nodes":["b3113159ccb8d6cb","645488c02db606e0","64875674f2ce4d6b","65ae6b5304ec0efc","1647a12172770002","2f1b79e25a100e56","0f20fb7ea418ea6d","335b0ef01524a1c6","8c49f1e83b970111","46c0aff5f34d1ed1"],"x":84,"y":709,"w":952,"h":162},{"id":"8cecb62f87f81e12","type":"group","z":"29c887befe280b70","g":"1a4e3fee13ec8588","name":"Battery Charge Time","style":{"label":true},"nodes":["a347d55288b88773","92e2bdc3dd900cf6","98fc3027962df1f0","397cdfe563f110fd"],"x":84,"y":889,"w":732,"h":82},{"id":"7d8592a87f7a1690","type":"group","z":"29c887befe280b70","name":"⚙️ System Configuration (Setup once)","style":{"stroke":"#929292","fill":"#e5e5e5","label":true},"nodes":["55336ddfaae7dfe6","796e59ef61436baf","6b40d8748eeb0d25","391b152b41ec8b20","470d9ef368817781","17addf91115ec69a","65809f93b1e262de"],"x":23,"y":4,"w":963,"h":288},{"id":"6b40d8748eeb0d25","type":"group","z":"29c887befe280b70","g":"7d8592a87f7a1690","name":"Define entities using HA Discovery","style":{"stroke":"none","fill":"#ffffbf","label":true},"nodes":["cc940a16d881b6be","e0b4d040337abb99","56f314e1538a7daa","09a2eb44673d2e09"],"x":49,"y":169,"w":667,"h":97},{"id":"12db757824215eb8","type":"inject","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"Basic","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"devbasiceinfor","payload":"wifilocalMonitor:get dev basice infor","payloadType":"str","x":115,"y":435,"wires":[["3632a32802b9c6c9"]]},{"id":"46845906337ab6b4","type":"inject","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"Date","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"getdate","payload":"wifilocalMonitor:get Date","payloadType":"str","x":115,"y":495,"wires":[["3632a32802b9c6c9"]]},{"id":"a7c36b8bfb83e339","type":"tcp request","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"Inverter TCP","server":"","port":"","out":"time","ret":"string","splitc":"1000","newline":"","trim":false,"tls":"","x":625,"y":450,"wires":[["5d45a78e2721e0c3","7818c761c132ed8e"]]},{"id":"5d45a78e2721e0c3","type":"debug","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"tcp","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":745,"y":510,"wires":[]},{"id":"2564482e9b2a3b42","type":"function","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"devsetinfor","func":"global.set(\"devsetinfor\",msg.payload);\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":945,"y":375,"wires":[[]]},{"id":"7818c761c132ed8e","type":"switch","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"devsetinfor","vt":"str"},{"t":"eq","v":"devbasiceinfor","vt":"str"},{"t":"eq","v":"devrealinfor","vt":"str"},{"t":"eq","v":"getdate","vt":"str"}],"checkall":"true","repair":false,"outputs":4,"x":775,"y":450,"wires":[["2564482e9b2a3b42","e5e41351d3dcd6a1","ad91b5078af5d8c6"],["5981cd3c46b7ae99"],["e21f92a11cee4126","26442e839fd50b6a"],["bf943deed6c1bedd"]]},{"id":"bf943deed6c1bedd","type":"function","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"Date","func":"global.set(\"getdate\",msg.payload);\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":930,"y":585,"wires":[[]]},{"id":"6178ae9e99148806","type":"inject","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"Monitor","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"5","crontab":"","once":false,"onceDelay":"5","topic":"devrealinfor","payload":"wifilocalMonitor:get dev real infor","payloadType":"str","x":125,"y":465,"wires":[["3632a32802b9c6c9"]]},{"id":"db09d1838d487e9b","type":"inject","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"Settings","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":false,"onceDelay":"1","topic":"devsetinfor","payload":"wifilocalMonitor:get dev set infor","payloadType":"str","x":125,"y":405,"wires":[["3632a32802b9c6c9"]]},{"id":"e5e41351d3dcd6a1","type":"function","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"Parse Config","func":"// 1. Parse Input\n// TCP requests return strings, so we must parse it into an Object.\nif (typeof msg.payload === \"string\") {\n    try {\n        msg.payload = JSON.parse(msg.payload);\n    } catch (e) {\n        node.warn(\"Failed to parse JSON: \" + e.message);\n        return null;\n    }\n}\n\n// Ensure we have data\nlet data = msg.payload;\nif (!data) return null;\n\nlet msgs = [];\n\n// Helper to create MQTT message\nfunction send(topicSuffix, value) {\n    msgs.push({\n        topic: \"felicity/state/\" + topicSuffix,\n        payload: value,\n        retain: true\n    });\n}\n\n// 2. NUMERIC VALUES (Matches your Inverter JSON keys)\n// We check for undefined to safely skip if the key is missing\n// Convert MACCurr from DC to AC for display (Divide by 4.6)\nif (data.MACCurr !== undefined) {\n    let acAmps = (data.MACCurr / 4.6).toFixed(1); // e.g. 50A DC -> 10.9A AC\n    send(\"maccurr\", Number(acAmps));\n}\n// Old DC way for Grid charging current\n// if (data.MACCurr !== undefined) send(\"maccurr\", data.MACCurr);\nif (data.BBkUt !== undefined) send(\"bbkut\", data.BBkUt);\nif (data.BBkBat !== undefined) send(\"bbkbat\", data.BBkBat);\nif (data.BSOCUN !== undefined) send(\"bsocun\", data.BSOCUN);\n\n// 3. MAPPING OSPri (Int -> Text)\n// 0=USB, 1=SUB, 2=SBU\nif (data.oSPri !== undefined) {\n    let map = [\"Utility First (USB)\", \"Solar First (SUB)\", \"Battery First (SBU)\"];\n    // Ensure the value is within the map's range\n    if (map[data.oSPri]) send(\"ospri\", map[data.oSPri]);\n}\n\n// 4. MAPPING CSPri (Int -> Text)\n// 1=CSO, 2=SNU, 3=OSO\nif (data.cSPri !== undefined) {\n    // Array index 0 is null because map starts at 1\n    let map = [null, \"Solar First (CSO)\", \"Solar + Utility (SNU)\", \"Solar Only (OSO)\"];\n    if (map[data.cSPri]) send(\"cspri\", map[data.cSPri]);\n}\n\n// Return all MQTT messages as a single burst\nreturn [msgs];","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1080,"y":420,"wires":[["e69193f22ece2bfb"]]},{"id":"e21f92a11cee4126","type":"function","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"Parse & Fix JSON","func":"// 1. Convert buffer/payload to string\nlet input = msg.payload.toString();\nlet mergedData = {};\nlet hasData = false;\n\n// 2. Handle \"Back-to-Back\" JSONs\nif (input.includes(\"}{\")) {\n    let parts = input.split(\"}{\");\n    parts.forEach((part, index) => {\n        let cleanPart = part;\n        if (index < parts.length - 1) cleanPart = cleanPart + \"}\";\n        if (index > 0) cleanPart = \"{\" + cleanPart;\n        try {\n            let data = JSON.parse(cleanPart);\n            if (data && data !== 0 && data !== \"0\") {\n                Object.assign(mergedData, data);\n                hasData = true;\n            }\n        } catch (e) { node.warn(\"Part parse error\"); }\n    });\n} else {\n    // Single Message\n    try {\n        let data = JSON.parse(input);\n        if (data && data !== 0 && data !== \"0\") {\n            Object.assign(mergedData, data);\n            hasData = true;\n        }\n    } catch (e) { return null; }\n}\n\n// 3. SANITY CHECKS & ENRICHMENT\nif (hasData) {\n    // Check if SOC exists\n    if (mergedData.Batsoc && Array.isArray(mergedData.Batsoc) && mergedData.Batsoc[0]) {\n        let rawSoc = mergedData.Batsoc[0][0];\n\n        // A. Zero Protection\n        if (rawSoc === 0) {\n            node.warn(\"🛡️ Glitch Protection: Dropped packet because SOC was 0\");\n            return null;\n        }\n\n        // B. Gradient/Spike Protection (New)\n        let currentSoc = rawSoc / 100;\n        let lastSoc = context.get('lastSoc');\n\n        // Initialize on first run\n        if (lastSoc === undefined) {\n            context.set('lastSoc', currentSoc);\n            lastSoc = currentSoc;\n        }\n\n        let diff = Math.abs(currentSoc - lastSoc);\n\n        // THRESHOLD: If SOC jumps by more than 5% in one reading\n        if (diff > 5) {\n            let strikes = context.get('socStrikes') || 0;\n            strikes++;\n            context.set('socStrikes', strikes);\n\n            // Ignore the first 2 weird readings (approx 6-10 seconds)\n            if (strikes < 3) {\n                node.warn(`🛡️ Glitch Protection: Ignored SOC spike ${lastSoc}% -> ${currentSoc}% (Strike ${strikes})`);\n                return null; // Stop here. Don't publish.\n            }\n            // If it happens 3 times, it's real (or we accepted the new reality)\n            context.set('socStrikes', 0);\n        } else {\n            // Valid value, reset strikes\n            context.set('socStrikes', 0);\n        }\n\n        // Save valid SOC for next time\n        context.set('lastSoc', currentSoc);\n    }\n\n    // --- INJECT BSOCUN FROM GLOBAL MEMORY ---\n    let settingsStr = global.get(\"devsetinfor\");\n    if (settingsStr) {\n        try {\n            let settings = (typeof settingsStr === 'string') ? JSON.parse(settingsStr) : settingsStr;\n            if (settings.BSOCUN !== undefined) {\n                mergedData.BSOCUN = settings.BSOCUN;\n            }\n        } catch (e) { /* Ignore parsing errors from global */ }\n    }\n    // ---------------------------------------------\n\n    msg.payload = mergedData;\n    msg.topic = \"inverter_fs1/state\";\n    return msg;\n}\n\nreturn null;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1085,"y":510,"wires":[["e69193f22ece2bfb"]]},{"id":"3632a32802b9c6c9","type":"delay","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"1msg/3s","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"3","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":305,"y":450,"wires":[["124f0aec0e4531b3"]]},{"id":"5c8734638ceb9137","type":"link in","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"link in 6","links":["dafd53b3be75ccb0"],"x":110,"y":525,"wires":[["3632a32802b9c6c9"]]},{"id":"ad91b5078af5d8c6","type":"debug","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"settings","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":740,"y":390,"wires":[]},{"id":"e69193f22ece2bfb","type":"link out","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"To MQTT","mode":"link","links":["470d9ef368817781"],"x":1250,"y":465,"wires":[]},{"id":"124f0aec0e4531b3","type":"change","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"Set IP/Port","rules":[{"t":"set","p":"host","pt":"msg","to":"inverter_ip","tot":"global"},{"t":"set","p":"port","pt":"msg","to":"inverter_port","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":450,"wires":[["a7c36b8bfb83e339"]]},{"id":"b3113159ccb8d6cb","type":"server-state-changed","z":"29c887befe280b70","g":"ae3dc6bbe23d7756","name":"Watch Raw Load","server":"43e792f7.5c883c","version":6,"outputs":1,"exposeAsEntityConfig":"","entities":{"entity":["sensor.inverter_fs1_load_power"],"substring":[],"regex":[]},"outputInitially":true,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":true,"ignorePrevStateUnknown":true,"ignorePrevStateUnavailable":true,"ignoreCurrentStateUnknown":true,"ignoreCurrentStateUnavailable":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"string","valueType":"entityState"}],"x":190,"y":750,"wires":[["645488c02db606e0"]]},{"id":"645488c02db606e0","type":"time moving average","z":"29c887befe280b70","g":"ae3dc6bbe23d7756","name":"Avg Load (30m)","timeframe":"1800","rampPositive":"","rampNegative":"","rampTimeframe":"","round":true,"roundDecimals":"0","x":405,"y":750,"wires":[["64875674f2ce4d6b"]]},{"id":"64875674f2ce4d6b","type":"function","z":"29c887befe280b70","g":"ae3dc6bbe23d7756","name":"Save","func":"flow.set(\"inverter_avg_load\", msg.payload);\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":575,"y":750,"wires":[["0f20fb7ea418ea6d"]]},{"id":"65ae6b5304ec0efc","type":"server-state-changed","z":"29c887befe280b70","g":"ae3dc6bbe23d7756","name":"Watch Raw Batt Out","server":"43e792f7.5c883c","version":6,"outputs":1,"exposeAsEntityConfig":"","entities":{"entity":["sensor.inverter_fs1_battery_power_out"],"substring":[],"regex":[]},"outputInitially":true,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":true,"ignorePrevStateUnknown":true,"ignorePrevStateUnavailable":true,"ignoreCurrentStateUnknown":true,"ignoreCurrentStateUnavailable":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"string","valueType":"entityState"}],"x":200,"y":830,"wires":[["1647a12172770002"]]},{"id":"1647a12172770002","type":"time moving average","z":"29c887befe280b70","g":"ae3dc6bbe23d7756","name":"Avg Batt (30m)","timeframe":"1800","rampPositive":"","rampNegative":"","rampTimeframe":"","round":true,"roundDecimals":"0","x":405,"y":830,"wires":[["2f1b79e25a100e56"]]},{"id":"2f1b79e25a100e56","type":"function","z":"29c887befe280b70","g":"ae3dc6bbe23d7756","name":"Save","func":"flow.set(\"inverter_avg_batt\", msg.payload);\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":575,"y":830,"wires":[["0f20fb7ea418ea6d"]]},{"id":"0f20fb7ea418ea6d","type":"api-current-state","z":"29c887befe280b70","g":"ae3dc6bbe23d7756","name":"Get kWh Available","server":"43e792f7.5c883c","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.inverter_fs1_battery_state_of_charge","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"kwh_available","propertyType":"msg","value":"$entity().attributes.kwh_available","valueType":"jsonata"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":755,"y":765,"wires":[["335b0ef01524a1c6"]]},{"id":"335b0ef01524a1c6","type":"function","z":"29c887befe280b70","g":"ae3dc6bbe23d7756","name":"Smart Discharge Calc (Averaged)","func":"const batt_w = parseFloat(flow.get(\"inverter_avg_batt\")) || 0;\nconst load_w = parseFloat(flow.get(\"inverter_avg_load\")) || 0;\nconst kwh = parseFloat(msg.kwh_available) || 0;\n\nlet effective_load = 0;\nlet mode = \"\";\n\nif (batt_w > 20) {\n    effective_load = batt_w;\n    mode = \"Real Usage (Avg)\";\n} else {\n    effective_load = load_w;\n    mode = \"Prediction (Avg Load)\";\n}\n\nlet runtime_hours = 0;\nif (effective_load > 1 && kwh > 0) {\n    const load_kw = effective_load / 1000;\n    runtime_hours = kwh / load_kw;\n} else {\n    runtime_hours = 24; \n    mode += \" (Idle)\";\n}\n\nif (runtime_hours > 24) runtime_hours = 24;\n\nlet empty_time_iso = null;\nlet human_str = \"Stable (>24h)\";\n\nif (runtime_hours > 0 && runtime_hours < 24) {\n    const now = new Date();\n    const ms_remaining = runtime_hours * 3600 * 1000;\n    let target_time = new Date(now.getTime() + ms_remaining);\n\n    const coeff = 1000 * 60 * 15;\n    target_time = new Date(Math.round(target_time.getTime() / coeff) * coeff);\n\n    empty_time_iso = target_time.toISOString();\n\n    const today = new Date();\n    const tomorrow = new Date(today);\n    tomorrow.setDate(tomorrow.getDate() + 1);\n    const isSameDay = (d1, d2) => d1.toDateString() === d2.toDateString();\n    const time_str = target_time.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' });\n\n    if (isSameDay(target_time, today)) {\n        human_str = `Today at ${time_str}`;\n    } else if (isSameDay(target_time, tomorrow)) {\n        human_str = `Tomorrow at ${time_str}`;\n    } else {\n        human_str = target_time.toLocaleDateString('en-GB', { weekday: 'short', day: 'numeric' }) + \" \" + time_str;\n    }\n}\n\nconst msgState = {\n    topic: \"inverter_fs1/sensor/battery_runtime/state\",\n    payload: parseFloat(runtime_hours.toFixed(1)),\n    retain: true\n};\n\nconst msgAttrs = {\n    topic: \"inverter_fs1/sensor/battery_runtime/attributes\",\n    payload: {\n        empty_at: empty_time_iso,\n        empty_time: human_str,\n        raw_kwh: kwh,\n        effective_load_used: effective_load,\n        average_load_watts: load_w,\n        average_batt_out_watts: batt_w,\n        calculation_mode: mode\n    },\n    retain: true\n};\n\nreturn [[msgState, msgAttrs]];","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":825,"y":810,"wires":[["8c49f1e83b970111"]]},{"id":"8c49f1e83b970111","type":"link out","z":"29c887befe280b70","g":"ae3dc6bbe23d7756","name":"To MQTT","mode":"link","links":["470d9ef368817781"],"x":995,"y":810,"wires":[]},{"id":"46c0aff5f34d1ed1","type":"inject","z":"29c887befe280b70","g":"ae3dc6bbe23d7756","name":"Refresh","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":180,"y":795,"wires":[["645488c02db606e0"]]},{"id":"a347d55288b88773","type":"server-state-changed","z":"29c887befe280b70","g":"8cecb62f87f81e12","name":"Watch Power In","server":"43e792f7.5c883c","version":6,"outputs":1,"exposeAsEntityConfig":"","entities":{"entity":["sensor.inverter_fs1_battery_power_in"],"substring":[],"regex":[]},"outputInitially":true,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":true,"ignorePrevStateUnknown":true,"ignorePrevStateUnavailable":true,"ignoreCurrentStateUnknown":true,"ignoreCurrentStateUnavailable":true,"outputProperties":[{"property":"charge_watts","propertyType":"msg","value":"string","valueType":"entityState"}],"x":190,"y":930,"wires":[["92e2bdc3dd900cf6"]]},{"id":"92e2bdc3dd900cf6","type":"api-current-state","z":"29c887befe280b70","g":"8cecb62f87f81e12","name":"Get SOC Attributes","server":"43e792f7.5c883c","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.inverter_fs1_battery_state_of_charge","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"kwh_current","propertyType":"msg","value":"$entity().attributes.kwh_total","valueType":"jsonata"},{"property":"battery_capacity","propertyType":"msg","value":"$entity().attributes.battery_size_kwh","valueType":"jsonata"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":410,"y":930,"wires":[["98fc3027962df1f0"]]},{"id":"98fc3027962df1f0","type":"function","z":"29c887befe280b70","g":"8cecb62f87f81e12","name":"Calc Charge Time","func":"// Inputs\nconst charge_w = parseFloat(msg.charge_watts);\nconst kwh_current = parseFloat(msg.kwh_current);\n\n// DYNAMIC CAPACITY (From Attribute)\n// Fallback to 25.6 if attribute is missing\nconst battery_capacity = parseFloat(msg.battery_capacity) || 25.6;\n\n// 1. Calculate Remaining Capacity to Fill\nconst kwh_needed = battery_capacity - kwh_current;\n\n// 2. Calculate Charge Time\nlet charge_hours = 0;\n\n// Logic: Charging Power > 0 AND we actually need charge\nif (charge_w > 0 && kwh_needed > 0) {\n    const charge_kw = charge_w / 1000;\n    charge_hours = kwh_needed / charge_kw;\n} else {\n    charge_hours = 0;\n}\n\n// CAP: STRICT 24H LIMIT\nif (charge_hours > 24) charge_hours = 24;\n\n// 3. Calculate Timestamp\nlet full_at = null;\nlet human_str = \"Discharging / Full\";\n\nif (charge_hours > 0 && charge_hours < 24) { // Only calculate timestamp if under 24h\n    const now = new Date();\n    const ms_remaining = charge_hours * 3600 * 1000;\n    let target_time = new Date(now.getTime() + ms_remaining);\n\n    // Smooth to 15 mins\n    const coeff = 1000 * 60 * 15;\n    target_time = new Date(Math.round(target_time.getTime() / coeff) * coeff);\n\n    full_at = target_time.toISOString();\n\n    const today = new Date();\n    const tomorrow = new Date(today);\n    tomorrow.setDate(tomorrow.getDate() + 1);\n    const isSameDay = (d1, d2) => d1.toDateString() === d2.toDateString();\n    const time_str = target_time.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' });\n\n    if (isSameDay(target_time, today)) {\n        human_str = `Today at ${time_str}`;\n    } else if (isSameDay(target_time, tomorrow)) {\n        human_str = `Tomorrow at ${time_str}`;\n    } else {\n        human_str = target_time.toLocaleDateString('en-GB', { weekday: 'short', day: 'numeric' }) + \" \" + time_str;\n    }\n} else if (charge_hours >= 24) {\n    human_str = \"> 24 Hours\";\n}\n\n// 4. Prepare Outputs\nconst msgState = {\n    topic: \"inverter_fs1/sensor/battery_charge_remaining/state\",\n    payload: parseFloat(charge_hours.toFixed(1)),\n    retain: true\n};\n\nconst msgAttrs = {\n    topic: \"inverter_fs1/sensor/battery_charge_remaining/attributes\",\n    payload: {\n        full_at: full_at,\n        full_time: human_str,\n        raw_kwh_needed: parseFloat(kwh_needed.toFixed(2)),\n        raw_charge_w: charge_w,\n        capacity_used_for_calc: battery_capacity\n    },\n    retain: true\n};\n\nreturn [[msgState, msgAttrs]];","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":640,"y":930,"wires":[["397cdfe563f110fd"]]},{"id":"397cdfe563f110fd","type":"link out","z":"29c887befe280b70","g":"8cecb62f87f81e12","name":"To MQTT","mode":"link","links":["470d9ef368817781"],"x":775,"y":930,"wires":[]},{"id":"55336ddfaae7dfe6","type":"inject","z":"29c887befe280b70","g":"7d8592a87f7a1690","name":"On Startup","props":[],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","x":145,"y":120,"wires":[["796e59ef61436baf"]]},{"id":"796e59ef61436baf","type":"function","z":"29c887befe280b70","g":"7d8592a87f7a1690","name":"Set Globals","func":"// === NETWORK CONFIG ===\nglobal.set(\"inverter_ip\", \"192.168.xx.xx\");\nglobal.set(\"inverter_port\", \"53970\");\n\n// SILENT SUCCESS\n// Sets a green dot under the node instead of spamming debug\nnode.status({ fill: \"green\", shape: \"dot\", text: \"Config Loaded\" });\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":335,"y":120,"wires":[[]]},{"id":"cc940a16d881b6be","type":"function","z":"29c887befe280b70","g":"6b40d8748eeb0d25","name":"Define Sensors","func":"// Retrieve setup from previous node\nlet device = msg.device;\nlet configs = msg.configs;\n\n// HELPER FUNCTION\nfunction add(topic, payload) {\n    payload.device = device;\n    configs.push({ topic: topic, payload: payload });\n}\n\n// =========================================\n// GROUP 1: GENERAL STATUS & DIAGNOSTICS\n// =========================================\n\nadd(\"homeassistant/binary_sensor/inverter_fs1/fs1_fault/config\", {\n    \"unique_id\": \"fs1_fault\", \"name\": \"Fault\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ 'ON' if value_json.fault == 1 else 'OFF' }}\",\n    \"device_class\": \"problem\", \"entity_category\": \"diagnostic\"\n});\n\nadd(\"homeassistant/binary_sensor/inverter_fs1/fs1_warning/config\", {\n    \"unique_id\": \"fs1_warning\", \"name\": \"Warning\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ 'ON' if value_json.warn == 1 else 'OFF' }}\",\n    \"device_class\": \"problem\", \"entity_category\": \"diagnostic\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_batt_state/config\", {\n    \"unique_id\": \"fs1_batt_state\",\n    \"name\": \"Battery State\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ 'Full' if value_json.Bstate == 320 else 'Standby' if value_json.Bstate == 960 else 'Charging' if value_json.Bstate == 9152 else 'Discharging' if value_json.Bstate == 5056 else 'Unknown: ' + value_json.Bstate | string }}\",\n    \"icon\": \"mdi:battery-sync\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_workm/config\", {\n    \"unique_id\": \"fs1_workm\",\n    \"name\": \"Work Mode\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{% set modes = {0: 'Initializing', 1: '1', 2: '2', 3: 'Battery', 4: '4', 5: 'Grid'} %} {{ modes.get(value_json.workM, 'Unknown (' + value_json.workM|string + ')') }}\",\n    \"icon\": \"mdi:state-machine\",\n    \"entity_category\": \"diagnostic\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pflowe1/config\", {\n    \"unique_id\": \"fs1_pflowe1\", \"name\": \"pFlowE1\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ value_json.pFlowE1 }}\",\n    \"entity_category\": \"diagnostic\"\n});\n\n// =========================================\n// GROUP 2: GRID (AC IN)\n// =========================================\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_grid_voltage/config\", {\n    \"unique_id\": \"fs1_grid_voltage\", \"name\": \"Grid Voltage\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.ACin[0][0] / 10) | float }}\",\n    \"unit_of_measurement\": \"V\", \"device_class\": \"voltage\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_grid_current/config\", {\n    \"unique_id\": \"fs1_grid_current\", \"name\": \"Grid Current\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.ACin[1][0] / 10) | float }}\",\n    \"unit_of_measurement\": \"A\", \"device_class\": \"current\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_grid_power/config\", {\n    \"unique_id\": \"fs1_grid_power\", \"name\": \"Grid Power\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.ACin[3][0] ) | float }}\",\n    \"unit_of_measurement\": \"W\", \"device_class\": \"power\", \"state_class\": \"measurement\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_grid_freq/config\", {\n    \"unique_id\": \"fs1_grid_freq\",\n    \"name\": \"Grid Frequency\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ 'unavailable' if value_json.ACin[2][0] == 0 else (value_json.ACin[2][0] / 100) | float }}\",\n    \"device_class\": \"frequency\",\n    \"unit_of_measurement\": \"Hz\"\n});\n\nadd(\"homeassistant/binary_sensor/inverter_fs1/fs1_grid_available/config\", {\n    \"unique_id\": \"fs1_grid_available\", \"name\": \"Grid Available\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ 'ON' if (value_json.ACin[0][0] / 10 > 0) else 'OFF' }}\",\n    \"device_class\": \"power\"\n});\n\nadd(\"homeassistant/binary_sensor/inverter_fs1/fs1_grid_in_use/config\", {\n    \"unique_id\": \"fs1_grid_in_use\", \"name\": \"Grid in Use\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ 'ON' if (value_json.ACin[1][0] / 10 > 0.1) else 'OFF' }}\",\n    \"device_class\": \"power\"\n});\n\n// =========================================\n// GROUP 3: BATTERY\n// =========================================\n\nadd(\"homeassistant/sensor/inverter_fs1/soc/config\", {\n    \"unique_id\": \"soc\", \"name\": \"Battery State of Charge\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.Batsoc[0][0] / 100) | round(0) }}\",\n    \"unit_of_measurement\": \"%\", \"device_class\": \"battery\",\n    \"json_attributes_topic\": \"inverter_fs1/state\",\n    \"json_attributes_template\": \"{{ {'battery_size_kwh': 25.6, 'kwh_total': (0.00256 * value_json.Batsoc[0][0]) | round(2), 'kwh_available': ([0, (0.00256 * value_json.Batsoc[0][0]) - (0.256 * value_json.BSOCUN | float(10))] | max) | round(2) } | to_json }}\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_batt_voltage/config\", {\n    \"unique_id\": \"fs1_batt_voltage\", \"name\": \"Battery Voltage\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.Batt[0][0] / 1000) | float }}\",\n    \"unit_of_measurement\": \"V\", \"device_class\": \"voltage\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_batt_current/config\", {\n    \"unique_id\": \"fs1_batt_current\", \"name\": \"Battery Current\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.Batt[1][0] / 10) | float }}\",\n    \"unit_of_measurement\": \"A\", \"device_class\": \"current\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_batt_power/config\", {\n    \"unique_id\": \"fs1_batt_power\", \"name\": \"Battery Power\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (((value_json.Batt[0][0] / 1000) * (value_json.Batt[1][0] / 10)) | round(0)) }}\",\n    \"unit_of_measurement\": \"W\", \"device_class\": \"power\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_batt_power_in/config\", {\n    \"unique_id\": \"fs1_batt_power_in\", \"name\": \"Battery Power In\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ [(((value_json.Batt[0][0] / 1000) * (value_json.Batt[1][0] / 10)) | round(0)), 0] | max }}\",\n    \"unit_of_measurement\": \"W\", \"device_class\": \"power\", \"state_class\": \"measurement\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_batt_power_out/config\", {\n    \"unique_id\": \"fs1_batt_power_out\", \"name\": \"Battery Power Out\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ [(-1 * ((value_json.Batt[0][0] / 1000) * (value_json.Batt[1][0] / 10)) | round(0)), 0] | max }}\",\n    \"unit_of_measurement\": \"W\", \"device_class\": \"power\", \"state_class\": \"measurement\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_batt_temp/config\", {\n    \"unique_id\": \"fs1_batt_temp\", \"name\": \"Battery Temperature\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.Temp[0][0] / 10) | round(1) }}\",\n    \"unit_of_measurement\": \"°C\", \"device_class\": \"temperature\", \"entity_category\": \"diagnostic\"\n});\n\nadd(\"homeassistant/binary_sensor/inverter_fs1/fs1_bcstat/config\", {\n    \"unique_id\": \"fs1_bcstat\", \"name\": \"Battery Charging\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ 'ON' if value_json.bCStat == 1 else 'OFF' }}\"\n});\n\n// =========================================\n// GROUP 4: LOAD (AC OUT)\n// =========================================\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_load_voltage/config\", {\n    \"unique_id\": \"fs1_load_voltage\", \"name\": \"Load Voltage\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.ACout[0][0] / 10) | float }}\",\n    \"unit_of_measurement\": \"V\", \"device_class\": \"voltage\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_load_current/config\", {\n    \"unique_id\": \"fs1_load_current\", \"name\": \"Load Current\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.ACout[1][0] / 10) | float }}\",\n    \"unit_of_measurement\": \"A\", \"device_class\": \"current\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_load_power/config\", {\n    \"unique_id\": \"fs1_load_power\", \"name\": \"Load Power\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.ACout[3][0] ) | float }}\",\n    \"unit_of_measurement\": \"W\", \"device_class\": \"power\", \"state_class\": \"measurement\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_load_perc/config\", {\n    \"unique_id\": \"fs1_load_perc\", \"name\": \"Load Percentage\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.lPerc / 10) | float }}\",\n    \"unit_of_measurement\": \"%\"\n});\n\n// =========================================\n// GROUP 5: PV (SOLAR)\n// =========================================\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv_power/config\", {\n    \"unique_id\": \"fs1_pv_power\", \"name\": \"PV Power\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.PV[3][0]) | float }}\",\n    \"unit_of_measurement\": \"W\", \"device_class\": \"power\", \"state_class\": \"measurement\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv1_voltage/config\", {\n    \"unique_id\": \"fs1_pv1_voltage\", \"name\": \"PV1 Voltage\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.PV[0][0] / 10) | float }}\",\n    \"unit_of_measurement\": \"V\", \"device_class\": \"voltage\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv1_current/config\", {\n    \"unique_id\": \"fs1_pv1_current\", \"name\": \"PV1 Current\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.PV[1][0] / 10) | float }}\",\n    \"unit_of_measurement\": \"A\", \"device_class\": \"current\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv1_power/config\", {\n    \"unique_id\": \"fs1_pv1_power\", \"name\": \"PV1 Power\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.PV[2][0]) | float }}\",\n    \"unit_of_measurement\": \"W\", \"device_class\": \"power\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv2_voltage/config\", {\n    \"unique_id\": \"fs1_pv2_voltage\", \"name\": \"PV2 Voltage\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.PV[0][1] / 10) | float }}\",\n    \"unit_of_measurement\": \"V\", \"device_class\": \"voltage\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv2_current/config\", {\n    \"unique_id\": \"fs1_pv2_current\", \"name\": \"PV2 Current\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.PV[1][1] / 10) | float }}\",\n    \"unit_of_measurement\": \"A\", \"device_class\": \"current\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv2_power/config\", {\n    \"unique_id\": \"fs1_pv2_power\", \"name\": \"PV2 Power\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.PV[2][1]) | float }}\",\n    \"unit_of_measurement\": \"W\", \"device_class\": \"power\"\n});\n\n// ENERGY COUNTERS\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv_energy_today/config\", {\n    \"unique_id\": \"fs1_pv_energy_today\", \"name\": \"PV Energy Today\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.Energy[0][2]) / 1000 | float }}\",\n    \"unit_of_measurement\": \"kWh\", \"device_class\": \"energy\", \"state_class\": \"total_increasing\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv_energy_month/config\", {\n    \"unique_id\": \"fs1_pv_energy_month0\", \"name\": \"PV Energy This Month\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.Energy[0][3]) / 1000 | float }}\",\n    \"unit_of_measurement\": \"kWh\", \"device_class\": \"energy\", \"state_class\": \"total_increasing\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv_energy_year/config\", {\n    \"unique_id\": \"fs1_pv_energy_year\", \"name\": \"PV Energy This Year\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.Energy[0][4]) / 1000 | float }}\",\n    \"unit_of_measurement\": \"kWh\", \"device_class\": \"energy\", \"state_class\": \"total_increasing\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_pv_energy_total/config\", {\n    \"unique_id\": \"fs1_pv_energy_total\", \"name\": \"PV Energy Total Lifetime\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.Energy[0][1]) / 1000 | float }}\",\n    \"unit_of_measurement\": \"kWh\", \"device_class\": \"energy\", \"state_class\": \"total_increasing\"\n});\n\n// =========================================\n// GROUP 6: ADVANCED DIAGNOSTICS (NEW)\n// =========================================\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_inv_temp_ac/config\", {\n    \"unique_id\": \"fs1_inv_temp_ac\", \"name\": \"Inverter AC Temp\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.Temp[0][1] / 10) | float }}\",\n    \"unit_of_measurement\": \"°C\", \"device_class\": \"temperature\",\n    \"entity_category\": \"diagnostic\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_inv_temp_dc/config\", {\n    \"unique_id\": \"fs1_inv_temp_dc\", \"name\": \"Inverter DC Temp\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.Temp[0][2] / 10) | float }}\",\n    \"unit_of_measurement\": \"°C\", \"device_class\": \"temperature\",\n    \"entity_category\": \"diagnostic\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_batt_soh/config\", {\n    \"unique_id\": \"fs1_batt_soh\", \"name\": \"Battery SOH\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.BatsocList[0][1] / 10) | float }}\",\n    \"unit_of_measurement\": \"%\", \"icon\": \"mdi:heart-pulse\",\n    \"entity_category\": \"diagnostic\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_cell_max_vol/config\", {\n    \"unique_id\": \"fs1_cell_max_vol\", \"name\": \"Max Cell Voltage\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.BMaxMin[0][0] / 1000) | float }}\",\n    \"unit_of_measurement\": \"V\", \"device_class\": \"voltage\", \"icon\": \"mdi:battery-plus\",\n    \"entity_category\": \"diagnostic\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_cell_min_vol/config\", {\n    \"unique_id\": \"fs1_cell_min_vol\", \"name\": \"Min Cell Voltage\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.BMaxMin[0][1] / 1000) | float }}\",\n    \"unit_of_measurement\": \"V\", \"device_class\": \"voltage\", \"icon\": \"mdi:battery-minus\",\n    \"entity_category\": \"diagnostic\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_cell_imbalance/config\", {\n    \"unique_id\": \"fs1_cell_imbalance\", \"name\": \"Cell Imbalance\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.BMaxMin[0][0] - value_json.BMaxMin[0][1]) }}\",\n    \"unit_of_measurement\": \"mV\", \"icon\": \"mdi:scale-balance\",\n    \"entity_category\": \"diagnostic\"\n});\n\nadd(\"homeassistant/sensor/inverter_fs1/fs1_bus_voltage/config\", {\n    \"unique_id\": \"fs1_bus_voltage\", \"name\": \"Bus Voltage\",\n    \"state_topic\": \"inverter_fs1/state\",\n    \"value_template\": \"{{ (value_json.busVp / 10) | float }}\",\n    \"unit_of_measurement\": \"V\", \"device_class\": \"voltage\",\n    \"entity_category\": \"diagnostic\"\n});\n\n\n// =========================================\n// GROUP 7: ADVANCED SENSORS (LOGIC)\n// =========================================\n\n// Battery Runtime (MAIN)\nadd(\"homeassistant/sensor/inverter_fs1/battery_runtime/config\", {\n    \"name\": \"Battery Runtime\",\n    \"unique_id\": \"inverter_fs1_battery_runtime\",\n    \"state_topic\": \"inverter_fs1/sensor/battery_runtime/state\",\n    \"json_attributes_topic\": \"inverter_fs1/sensor/battery_runtime/attributes\",\n    \"device_class\": \"duration\",\n    \"unit_of_measurement\": \"h\",\n    \"icon\": \"mdi:timer-sand\",\n    \"state_class\": \"measurement\"\n});\n\n// Battery Charge Time\nadd(\"homeassistant/sensor/inverter_fs1/battery_charge_remaining/config\", {\n    \"name\": \"Battery Charge Time\",\n    \"unique_id\": \"inverter_fs1_battery_charge_remaining\",\n    \"state_topic\": \"inverter_fs1/sensor/battery_charge_remaining/state\",\n    \"json_attributes_topic\": \"inverter_fs1/sensor/battery_charge_remaining/attributes\",\n    \"device_class\": \"duration\",\n    \"unit_of_measurement\": \"h\",\n    \"icon\": \"mdi:battery-charging-100\",\n    \"state_class\": \"measurement\"\n});\n\n// =========================================\n// SEND SEQUENTIALLY (AVOID FLOODING)\n// =========================================\nconfigs.forEach((c, index) => {\n    setTimeout(() => {\n        node.send({\n            topic: c.topic,\n            payload: c.payload,\n            retain: true\n        });\n    }, index * 50); // 50ms delay between each\n});\n\nreturn null;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":225,"wires":[["391b152b41ec8b20"]]},{"id":"e0b4d040337abb99","type":"inject","z":"29c887befe280b70","g":"6b40d8748eeb0d25","name":"Create Sensors","props":[],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","x":175,"y":225,"wires":[["56f314e1538a7daa"]]},{"id":"470d9ef368817781","type":"link in","z":"29c887befe280b70","g":"7d8592a87f7a1690","name":"link in 7","links":["2b6b66536dafeb01","f424bee361b00c32","e69193f22ece2bfb","97cf33da8e39f957","c04769f81418f2b2","8c49f1e83b970111","397cdfe563f110fd"],"x":645,"y":90,"wires":[["391b152b41ec8b20"]]},{"id":"391b152b41ec8b20","type":"mqtt out","z":"29c887befe280b70","g":"7d8592a87f7a1690","name":"Send to MQTT","topic":"","qos":"","retain":"","broker":"357b169354f2f5e9","x":880,"y":90,"wires":[]},{"id":"26442e839fd50b6a","type":"function","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"devrealnfor","func":"global.set(\"devrealinfor\",msg.payload);\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":990,"y":540,"wires":[[]]},{"id":"5981cd3c46b7ae99","type":"function","z":"29c887befe280b70","g":"a30aaddd5daeb1b0","name":"devbasiceinfor","func":"global.set(\"devbasiceinfor\",msg.payload);\nreturn msg;\n\n// // 1. Ensure payload is a string\n// let inputString = msg.payload.toString();\n\n// // 2. Check if we have the \"}{\" duplicate pattern\n// // This implies two objects are stuck together\n// let splitIndex = inputString.indexOf(\"}{\");\n\n// if (splitIndex !== -1) {\n//     // If found, slice the string from the start up to the first closing bracket\n//     // splitIndex is where '}' starts in the pattern \"}{\", so we add 1 to include it.\n//     inputString = inputString.substring(0, splitIndex + 1);\n// }\n\n// // 3. Parse the cleaned string to ensure it is valid JSON\n// try {\n//     let jsonObject = JSON.parse(inputString);\n\n//     // Store the clean object, not the string\n//     global.set(\"devbasiceinfor\", jsonObject);\n\n//     // Update the message payload to the clean object for downstream nodes\n//     msg.payload = jsonObject;\n\n// } catch (e) {\n//     node.error(\"Failed to parse JSON: \" + e.message, msg);\n// }\n\n// return msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":990,"y":450,"wires":[[]]},{"id":"17addf91115ec69a","type":"comment","z":"29c887befe280b70","g":"7d8592a87f7a1690","name":"Read Me","info":"Modify the following:\n1- \"Set Globals\": change IP\n2- Modify \"Define Inverter HA Device\" to use the correct info for your inverter\n3- Click \"Create Sensors\" once. The entities will be created inside HA\n4- Success. You should have a new device in HA frontend with all the values","x":120,"y":45,"wires":[]},{"id":"56f314e1538a7daa","type":"function","z":"29c887befe280b70","g":"6b40d8748eeb0d25","name":"Define Inverter HA Device","func":"// 1. CENTRAL DEVICE DEFINITION\n// We attach this to 'msg' so the next node can use it\nmsg.device = {\n    \"identifiers\": [\"inverter_fs1\"],\n    \"name\": \"Inverter FS1\",\n    \"model\": \"48V LiFePO4 25kWh\",\n    \"manufacturer\": \"Felicity Solar\"\n};\n\n// Initialize the array to hold our configurations\nmsg.configs = [];\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":390,"y":225,"wires":[["cc940a16d881b6be"]]},{"id":"65809f93b1e262de","type":"comment","z":"29c887befe280b70","g":"7d8592a87f7a1690","name":"MODIFY THIS","info":"","x":355,"y":105,"wires":[]},{"id":"09a2eb44673d2e09","type":"comment","z":"29c887befe280b70","g":"6b40d8748eeb0d25","name":"MODIFY THIS","info":"","x":415,"y":210,"wires":[]},{"id":"43e792f7.5c883c","type":"server","name":"Home Assistant","version":6,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":["y","yes","true","on","home","open"],"connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"357b169354f2f5e9","type":"mqtt-broker","name":"","broker":"localhost","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"6a617d40e71a8b30","type":"global-config","env":[],"modules":{"node-red-contrib-home-assistant-websocket":"0.80.3","node-red-contrib-time-moving-average":"1.0.3"}}]
1 „Gefällt mir“

@imania7 Many many Thanks!!! Perfect!!! It works!