[
    {
        "id": "4b3cc34dbff8443d",
        "type": "tab",
        "label": "Selfa SFH 12.1",
        "disabled": false,
        "info": ""
    },
    {
        "id": "cb34fa883e7e0c52",
        "type": "inject",
        "z": "4b3cc34dbff8443d",
        "name": "HA Discovery (once)",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 140,
        "y": 60,
        "wires": [
            [
                "50ad0da119eb102c"
            ]
        ]
    },
    {
        "id": "50ad0da119eb102c",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Publish HA Discovery",
        "func": "const dev = {\n  identifiers: [\"selfa_sfh_121\"],\n  name: \"Selfa SFH 12.1\",\n  model: \"SFH 12.1\",\n  manufacturer: \"Selfa\"\n};\nconst sensors = [\n  { id:\"status\",         name:\"Status\",                       topic:\"status\",                         dc:null,          sc:null,               unit:null,  icon:\"mdi:solar-power\" },\n  { id:\"working_mode\",   name:\"Working Mode\",                 topic:\"Working_Mode\",                   dc:null,          sc:null,               unit:null,  icon:\"mdi:cog-outline\" },\n  { id:\"fault_flag1\",    name:\"Fault FLAG1\",                  topic:\"Fault_FLAG1\",                    dc:null,          sc:null,               unit:null,  icon:\"mdi:alert\" },\n  { id:\"fault_flag2\",    name:\"Fault FLAG2\",                  topic:\"Fault_FLAG2\",                    dc:null,          sc:null,               unit:null,  icon:\"mdi:alert\" },\n  { id:\"fault_flag3\",    name:\"Fault FLAG3\",                  topic:\"Fault_FLAG3\",                    dc:null,          sc:null,               unit:null,  icon:\"mdi:alert\" },\n  { id:\"pmeter_a\",       name:\"Pmeter Phase A\",               topic:\"Pmeter_Phase_A_W\",               dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:null },\n  { id:\"pmeter_b\",       name:\"Pmeter Phase B\",               topic:\"Pmeter_Phase_B_W\",               dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:null },\n  { id:\"pmeter_c\",       name:\"Pmeter Phase C\",               topic:\"Pmeter_Phase_C_W\",               dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:null },\n  { id:\"pmeter_total\",   name:\"Pmeter Total\",                 topic:\"Pmeter_Total_W\",                 dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:null },\n  { id:\"meter_inject\",   name:\"Grid Injection Total\",         topic:\"Meter_Grid_Injection_Total_kWh\", dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"meter_purchase\", name:\"Grid Purchasing Total\",        topic:\"Meter_Purchasing_Total_kWh\",     dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"v_ab\",           name:\"Voltage Line AB\",              topic:\"Voltage_Line_AB_V\",              dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"v_bc\",           name:\"Voltage Line BC\",              topic:\"Voltage_Line_BC_V\",              dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"v_ca\",           name:\"Voltage Line CA\",              topic:\"Voltage_Line_CA_V\",              dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"v_a\",            name:\"Voltage Phase A\",              topic:\"Voltage_Phase_A_V\",              dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"i_a\",            name:\"Current Phase A\",              topic:\"Current_Phase_A_A\",              dc:\"current\",     sc:\"measurement\",      unit:\"A\",   icon:null },\n  { id:\"v_b\",            name:\"Voltage Phase B\",              topic:\"Voltage_Phase_B_V\",              dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"i_b\",            name:\"Current Phase B\",              topic:\"Current_Phase_B_A\",              dc:\"current\",     sc:\"measurement\",      unit:\"A\",   icon:null },\n  { id:\"v_c\",            name:\"Voltage Phase C\",              topic:\"Voltage_Phase_C_V\",              dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"i_c\",            name:\"Current Phase C\",              topic:\"Current_Phase_C_A\",              dc:\"current\",     sc:\"measurement\",      unit:\"A\",   icon:null },\n  { id:\"freq\",           name:\"Grid Frequency\",               topic:\"Frequency_Grid_Hz\",              dc:\"frequency\",   sc:\"measurement\",      unit:\"Hz\",  icon:null },\n  { id:\"pac\",            name:\"Active Power Total\",           topic:\"ActivePower_Total_W\",            dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:null },\n  { id:\"e_today\",        name:\"Energy Today\",                 topic:\"Energy_Today_kWh\",               dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"e_total\",        name:\"Energy Total\",                 topic:\"Energy_Total_kWh\",               dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"gen_hours\",      name:\"Generation Hours Total\",       topic:\"GenerationTime_Total_h\",         dc:null,          sc:\"total_increasing\", unit:\"h\",   icon:\"mdi:clock-outline\" },\n  { id:\"pv_power\",       name:\"PV Input Power Total\",         topic:\"PV_InputPower_Total_W\",          dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:\"mdi:solar-panel\" },\n  { id:\"temp1\",          name:\"Temperature 1\",                topic:\"Temperature_1_C\",                dc:\"temperature\", sc:\"measurement\",      unit:\"°C\",  icon:null },\n  { id:\"temp2\",          name:\"Temperature 2\",                topic:\"Temperature_2_C\",                dc:\"temperature\", sc:\"measurement\",      unit:\"°C\",  icon:null },\n  { id:\"temp3\",          name:\"Temperature 3\",                topic:\"Temperature_3_C\",                dc:\"temperature\", sc:\"measurement\",      unit:\"°C\",  icon:null },\n  { id:\"temp4\",          name:\"Temperature 4\",                topic:\"Temperature_4_C\",                dc:\"temperature\", sc:\"measurement\",      unit:\"°C\",  icon:null },\n  { id:\"pv1_v\",          name:\"PV1 Voltage\",                  topic:\"Voltage_PV1_V\",                  dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"pv1_i\",          name:\"PV1 Current\",                  topic:\"Current_PV1_A\",                  dc:\"current\",     sc:\"measurement\",      unit:\"A\",   icon:null },\n  { id:\"pv1_p\",          name:\"PV1 Power\",                    topic:\"Power_PV1_W\",                    dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:\"mdi:solar-panel\" },\n  { id:\"pv2_v\",          name:\"PV2 Voltage\",                  topic:\"Voltage_PV2_V\",                  dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"pv2_i\",          name:\"PV2 Current\",                  topic:\"Current_PV2_A\",                  dc:\"current\",     sc:\"measurement\",      unit:\"A\",   icon:null },\n  { id:\"pv2_p\",          name:\"PV2 Power\",                    topic:\"Power_PV2_W\",                    dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:\"mdi:solar-panel\" },\n  { id:\"soc\",            name:\"Battery SOC\",                  topic:\"SOC_pct\",                        dc:\"battery\",     sc:\"measurement\",      unit:\"%\",   icon:null },\n  { id:\"soh\",            name:\"Battery SOH\",                  topic:\"SOH_pct\",                        dc:null,          sc:\"measurement\",      unit:\"%\",   icon:\"mdi:battery-heart\" },\n  { id:\"bms_status\",     name:\"BMS Status\",                   topic:\"BMS_Status\",                     dc:null,          sc:null,               unit:null,  icon:\"mdi:battery-check\" },\n  { id:\"bms_temp\",       name:\"BMS Pack Temperature\",         topic:\"BMS_Pack_Temperature_C\",         dc:\"temperature\", sc:\"measurement\",      unit:\"°C\",  icon:null },\n  { id:\"cell_tmax\",      name:\"Max Cell Temperature\",         topic:\"Max_Cell_Temperature_C\",         dc:\"temperature\", sc:\"measurement\",      unit:\"°C\",  icon:null },\n  { id:\"cell_tmin\",      name:\"Min Cell Temperature\",         topic:\"Min_Cell_Temperature_C\",         dc:\"temperature\", sc:\"measurement\",      unit:\"°C\",  icon:null },\n  { id:\"cell_vmax\",      name:\"Max Cell Voltage\",             topic:\"Max_Cell_Voltage_V\",             dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"cell_vmin\",      name:\"Min Cell Voltage\",             topic:\"Min_Cell_Voltage_V\",             dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"bms_err\",        name:\"BMS Error Code\",               topic:\"BMS_ERROR_CODE\",                 dc:null,          sc:null,               unit:null,  icon:\"mdi:alert-circle\" },\n  { id:\"bms_warn\",       name:\"BMS Warn Code\",                topic:\"BMS_WARN_CODE\",                  dc:null,          sc:null,               unit:null,  icon:\"mdi:alert-circle-outline\" },\n  { id:\"bak_a_v\",        name:\"Backup Phase A Voltage\",       topic:\"Backup_A_V_V\",                   dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"bak_a_i\",        name:\"Backup Phase A Current\",       topic:\"Backup_A_I_A\",                   dc:\"current\",     sc:\"measurement\",      unit:\"A\",   icon:null },\n  { id:\"bak_a_f\",        name:\"Backup Phase A Frequency\",     topic:\"Backup_A_F_Hz\",                  dc:\"frequency\",   sc:\"measurement\",      unit:\"Hz\",  icon:null },\n  { id:\"bak_a_p\",        name:\"Backup Phase A Power\",         topic:\"Backup_A_P_W\",                   dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:null },\n  { id:\"bak_b_v\",        name:\"Backup Phase B Voltage\",       topic:\"Backup_B_V_V\",                   dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"bak_b_i\",        name:\"Backup Phase B Current\",       topic:\"Backup_B_I_A\",                   dc:\"current\",     sc:\"measurement\",      unit:\"A\",   icon:null },\n  { id:\"bak_b_f\",        name:\"Backup Phase B Frequency\",     topic:\"Backup_B_F_Hz\",                  dc:\"frequency\",   sc:\"measurement\",      unit:\"Hz\",  icon:null },\n  { id:\"bak_b_p\",        name:\"Backup Phase B Power\",         topic:\"Backup_B_P_W\",                   dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:null },\n  { id:\"bak_c_v\",        name:\"Backup Phase C Voltage\",       topic:\"Backup_C_V_V\",                   dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"bak_c_i\",        name:\"Backup Phase C Current\",       topic:\"Backup_C_I_A\",                   dc:\"current\",     sc:\"measurement\",      unit:\"A\",   icon:null },\n  { id:\"bak_c_f\",        name:\"Backup Phase C Frequency\",     topic:\"Backup_C_F_Hz\",                  dc:\"frequency\",   sc:\"measurement\",      unit:\"Hz\",  icon:null },\n  { id:\"bak_c_p\",        name:\"Backup Phase C Power\",         topic:\"Backup_C_P_W\",                   dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:null },\n  { id:\"bak_total_p\",    name:\"Total Backup Power\",           topic:\"Total_Backup_P_W\",               dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:\"mdi:power-socket\" },\n  { id:\"bak_total_p_kw\", name:\"Total Backup Active Power\",    topic:\"Total_Backup_ActiveP_kW\",        dc:\"power\",       sc:\"measurement\",      unit:\"kW\",  icon:\"mdi:power-socket\" },\n  { id:\"bat_v\",          name:\"Battery Voltage\",              topic:\"Battery_V_V\",                    dc:\"voltage\",     sc:\"measurement\",      unit:\"V\",   icon:null },\n  { id:\"bat_i\",          name:\"Battery Current\",              topic:\"Battery_I_A\",                    dc:\"current\",     sc:\"measurement\",      unit:\"A\",   icon:null },\n  { id:\"bat_mode\",       name:\"Battery Mode\",                 topic:\"Battery_Mode\",                   dc:null,          sc:null,               unit:null,  icon:\"mdi:battery-arrow-up-outline\" },\n  { id:\"bat_p\",          name:\"Battery Power\",                topic:\"Battery_P_W\",                    dc:\"power\",       sc:\"measurement\",      unit:\"W\",   icon:null },\n  { id:\"d_inj\",          name:\"Daily Grid Injection\",         topic:\"Daily_Grid_Injection_kWh\",       dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"d_pur\",          name:\"Daily Grid Purchase\",          topic:\"Daily_Grid_Purchase_kWh\",        dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"d_bak\",          name:\"Daily Backup Output\",          topic:\"Daily_Backup_Output_kWh\",        dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"d_bc\",           name:\"Daily Battery Charge\",         topic:\"Daily_Batt_Charge_kWh\",          dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"d_bd\",           name:\"Daily Battery Discharge\",      topic:\"Daily_Batt_Discharge_kWh\",       dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"d_pv\",           name:\"Daily PV Generation\",          topic:\"Daily_PV_Generation_kWh\",        dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:\"mdi:solar-panel\" },\n  { id:\"d_load\",         name:\"Daily Load Consumption\",       topic:\"Daily_Load_Consumption_kWh\",     dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"t_inj\",          name:\"Total Grid Injection\",         topic:\"Total_Grid_Injection_kWh\",       dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"t_pur\",          name:\"Total Grid Purchase\",          topic:\"Total_Grid_Purchase_kWh\",        dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"t_bak\",          name:\"Total Backup Output\",          topic:\"Total_Backup_Output_kWh\",        dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"t_bc\",           name:\"Total Battery Charge\",         topic:\"Total_Batt_Charge_kWh\",          dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"t_bd\",           name:\"Total Battery Discharge\",      topic:\"Total_Batt_Discharge_kWh\",       dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null },\n  { id:\"t_pv\",           name:\"Total PV Generation\",          topic:\"Total_PV_Generation_kWh\",        dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:\"mdi:solar-panel\" },\n  { id:\"t_load\",         name:\"Total Load Consumption\",       topic:\"Total_Load_Consumption_kWh\",     dc:\"energy\",      sc:\"total_increasing\", unit:\"kWh\", icon:null }\n];\nconst base = \"Selfa_SFH_12.1\";\nfor (const s of sensors) {\n  const cfg = {\n    name: s.name,\n    unique_id: `selfa_sfh121_${s.id}`,\n    state_topic: `${base}/${s.topic}`,\n    device: dev\n  };\n  if (s.unit) cfg.unit_of_measurement = s.unit;\n  if (s.dc)   cfg.device_class = s.dc;\n  if (s.sc)   cfg.state_class = s.sc;\n  if (s.icon) cfg.icon = s.icon;\n  node.send({\n    topic: `homeassistant/sensor/selfa_sfh121_${s.id}/config`,\n    payload: JSON.stringify(cfg),\n    qos: 1,\n    retain: true\n  });\n}\nconst selectCfg = {\n  name: \"Working Mode Set\",\n  unique_id: \"selfa_sfh121_working_mode_set\",\n  command_topic: `${base}/set/Working_Mode`,\n  state_topic: `${base}/Working_Mode`,\n  options: [\n    \"General Mode\",\n    \"Economic Mode\",\n    \"UPS Mode\",\n    \"Off Grid Mode\",\n    \"EMS: AC Control Mode\",\n    \"EMS: General Mode\",\n    \"EMS: Battery Control Mode\",\n    \"EMS: Off Grid Mode\"\n  ],\n  icon: \"mdi:cog-transfer-outline\",\n  device: dev\n};\nnode.send({\n  topic: `homeassistant/select/selfa_sfh121_working_mode_set/config`,\n  payload: JSON.stringify(selectCfg),\n  qos: 1,\n  retain: true\n});\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 480,
        "y": 60,
        "wires": [
            [
                "4157ee40d22b8d1e"
            ]
        ]
    },
    {
        "id": "5b7d748998410d40",
        "type": "inject",
        "z": "4b3cc34dbff8443d",
        "name": "Poll FAST every 2s",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "2",
        "crontab": "",
        "once": true,
        "onceDelay": 3,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 130,
        "y": 200,
        "wires": [
            [
                "3a0420f63ccfaaf6",
                "df97cd1a399d0a15",
                "40130edd32293a17",
                "da4ac8bad5619b75",
                "e63ae0192d551a66",
                "210c44b3b0f2fc4c",
                "2e7dc1f7e9b2e241"
            ]
        ]
    },
    {
        "id": "42f9eb9ff723521d",
        "type": "inject",
        "z": "4b3cc34dbff8443d",
        "name": "Poll SLOW every 60s",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "60",
        "crontab": "",
        "once": true,
        "onceDelay": 5,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 130,
        "y": 560,
        "wires": [
            [
                "32cdbe4fd4c3f580",
                "042ce3d8a21d7098",
                "bf01a38cd9b641e0",
                "c6463940ee726f59",
                "fb2d1214b67c4024"
            ]
        ]
    },
    {
        "id": "3a0420f63ccfaaf6",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read Status 10105 (qty:1)",
        "func": "msg.payload = { fc: 3, unitid: 247, address: 10105, quantity: 1 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 420,
        "y": 160,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "df97cd1a399d0a15",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read Meter+Grid 10994 (qty:28)",
        "func": "// 10994-11005 Meter (12 regs)\n// 11006-11021 Grid without GenHours (16 regs: V/I/Freq/ActivePower/EnergyToday/EnergyTotal)\n// qty:28 covers 10994..11021\nmsg.payload = { fc: 3, unitid: 247, address: 10994, quantity: 28 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 430,
        "y": 200,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "40130edd32293a17",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read PV Power+V+I 11028 (qty:14)",
        "func": "// 11028-11041: PV_InputPower(2), gap(2), Temps(4), PV1V/I/PV2V/I(4)\nmsg.payload = { fc: 3, unitid: 247, address: 11028, quantity: 14 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 430,
        "y": 240,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "da4ac8bad5619b75",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read Backup+TotalBackupP 30200 (qty:32)",
        "func": "// 30200-30231: Backup A/B/C + TotalBackupP\nmsg.payload = { fc: 3, unitid: 247, address: 30200, quantity: 32 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 440,
        "y": 280,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "e63ae0192d551a66",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read Battery 30254 (qty:6)",
        "func": "msg.payload = { fc: 3, unitid: 247, address: 30254, quantity: 6 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 420,
        "y": 320,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "210c44b3b0f2fc4c",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read BMS Core 33000 (qty:4)",
        "func": "// 33000: SOC, SOH, BMS_Status, BMS_Pack_Temp\nmsg.payload = { fc: 3, unitid: 247, address: 33000, quantity: 4 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 420,
        "y": 360,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "2e7dc1f7e9b2e241",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read Working Mode 50000 (qty:1)",
        "func": "msg.payload = { fc: 3, unitid: 247, address: 50000, quantity: 1 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 430,
        "y": 400,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "32cdbe4fd4c3f580",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read Faults 10112 (qty:10)",
        "func": "// 10112-10113 FLAG1, 10114-10121 FLAG2+3\nmsg.payload = { fc: 3, unitid: 247, address: 10112, quantity: 10 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 420,
        "y": 520,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "042ce3d8a21d7098",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read GenHours+Temp 11022 (qty:20)",
        "func": "// 11022-11023 GenerationTime_Total (2 regs)\n// 11024-11027 gap (4 regs, ignored)\n// 11028-11041 PV_InputPower+gap+Temps+PV1/PV2 (14 regs)\n// qty:20 covers 11022..11041\nmsg.payload = { fc: 3, unitid: 247, address: 11022, quantity: 20 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 430,
        "y": 560,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "bf01a38cd9b641e0",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read BMS Detail 33004 (qty:16)",
        "func": "// 33004-33019: cell temps, cell voltages, error codes\nmsg.payload = { fc: 3, unitid: 247, address: 33004, quantity: 16 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 420,
        "y": 600,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "c6463940ee726f59",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read Daily Energy 31000 (qty:9)",
        "func": "msg.payload = { fc: 3, unitid: 247, address: 31000, quantity: 9 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 420,
        "y": 640,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "fb2d1214b67c4024",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Read Total Energy 31102 (qty:18)",
        "func": "msg.payload = { fc: 3, unitid: 247, address: 31102, quantity: 18 };\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 430,
        "y": 680,
        "wires": [
            [
                "6af53a04e270d3cb"
            ]
        ]
    },
    {
        "id": "6af53a04e270d3cb",
        "type": "modbus-flex-getter",
        "z": "4b3cc34dbff8443d",
        "name": "Selfa Modbus Read",
        "showStatusActivities": true,
        "showErrors": true,
        "showWarnings": true,
        "logIOActivities": false,
        "server": "6130f85f6f241522",
        "useIOFile": false,
        "ioFile": "",
        "useIOForPayload": false,
        "emptyMsgOnFail": false,
        "keepMsgProperties": true,
        "delayOnStart": false,
        "enableDeformedMessages": false,
        "startDelayTime": "",
        "x": 720,
        "y": 420,
        "wires": [
            [
                "43d956541363ef1b"
            ],
            [
                "8197c4430127fcea"
            ]
        ]
    },
    {
        "id": "8197c4430127fcea",
        "type": "debug",
        "z": "4b3cc34dbff8443d",
        "name": "Modbus ERR",
        "active": false,
        "tosidebar": true,
        "complete": "true",
        "targetType": "full",
        "x": 920,
        "y": 540,
        "wires": []
    },
    {
        "id": "43d956541363ef1b",
        "type": "switch",
        "z": "4b3cc34dbff8443d",
        "name": "Dispatch by address",
        "property": "modbusRequest.address",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "10105",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "10994",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "11028",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "30200",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "30254",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "33000",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "50000",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "10112",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "11022",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "33004",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "31000",
                "vt": "num"
            },
            {
                "t": "eq",
                "v": "31102",
                "vt": "num"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 12,
        "x": 960,
        "y": 420,
        "wires": [
            [
                "f322eb1b228e12a9"
            ],
            [
                "f7f96f4f48b9ef0b"
            ],
            [
                "8729e49e46bcb86d"
            ],
            [
                "45a41c4e4b939c3c"
            ],
            [
                "a31e8e197bb7eb97"
            ],
            [
                "8f3a07ebc5ccc49c"
            ],
            [
                "31a21f14303dfb6e"
            ],
            [
                "c234053c41da6baa"
            ],
            [
                "e7c6aa06f7adcb7b"
            ],
            [
                "023f6d22b821af4e"
            ],
            [
                "c594267128390ec1"
            ],
            [
                "3e589b93139b843a"
            ]
        ]
    },
    {
        "id": "f322eb1b228e12a9",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse Status 10105",
        "func": "const base = \"Selfa_SFH_12.1\";\nconst raw = msg.payload[0];\nconst map = {\n  0: \"Wait for grid connection\",\n  1: \"Self-checking\",\n  2: \"On-grid generating\",\n  3: \"Device fault\",\n  4: \"Firmware upgrade\",\n  5: \"Off-grid generating\"\n};\nconst text = map.hasOwnProperty(raw) ? map[raw] : `Unknown (${raw})`;\nnode.status({ fill: \"green\", shape: \"dot\", text });\nnode.send({ topic: `${base}/status_raw`, payload: raw });\nnode.send({ topic: `${base}/status`,     payload: text });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1210,
        "y": 120,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "f7f96f4f48b9ef0b",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse Meter+Grid 10994 (qty:28)",
        "func": "// Base 10994, qty:28 => r[0..27]\n// Meter: r[0..11]  (10994-11005)\n// Grid:  r[12..27] (11006-11021) — 16 regs, no GenHours (11022-11023)\nconst base = \"Selfa_SFH_12.1\";\nconst r = msg.payload;\nfunction i32(hi, lo) { const v = ((hi >>> 0) * 65536) + (lo >>> 0); return v > 0x7FFFFFFF ? v - 0x100000000 : v; }\nfunction u32(hi, lo) { return (((hi >>> 0) * 65536) + (lo >>> 0)) >>> 0; }\n\n// Meter\nnode.send({ topic: `${base}/Pmeter_Phase_A_W`,               payload: i32(r[0],  r[1]) });\nnode.send({ topic: `${base}/Pmeter_Phase_B_W`,               payload: i32(r[2],  r[3]) });\nnode.send({ topic: `${base}/Pmeter_Phase_C_W`,               payload: i32(r[4],  r[5]) });\nnode.send({ topic: `${base}/Pmeter_Total_W`,                 payload: i32(r[6],  r[7]) });\nnode.send({ topic: `${base}/Meter_Grid_Injection_Total_kWh`, payload: u32(r[8],  r[9])  / 100 });\nnode.send({ topic: `${base}/Meter_Purchasing_Total_kWh`,     payload: u32(r[10], r[11]) / 100 });\n\n// Grid (offset 12)\nconst g = 12;\nnode.send({ topic: `${base}/Voltage_Line_AB_V`,   payload: r[g+0]  / 10 });\nnode.send({ topic: `${base}/Voltage_Line_BC_V`,   payload: r[g+1]  / 10 });\nnode.send({ topic: `${base}/Voltage_Line_CA_V`,   payload: r[g+2]  / 10 });\nnode.send({ topic: `${base}/Voltage_Phase_A_V`,   payload: r[g+3]  / 10 });\nnode.send({ topic: `${base}/Current_Phase_A_A`,   payload: r[g+4]  / 10 });\nnode.send({ topic: `${base}/Voltage_Phase_B_V`,   payload: r[g+5]  / 10 });\nnode.send({ topic: `${base}/Current_Phase_B_A`,   payload: r[g+6]  / 10 });\nnode.send({ topic: `${base}/Voltage_Phase_C_V`,   payload: r[g+7]  / 10 });\nnode.send({ topic: `${base}/Current_Phase_C_A`,   payload: r[g+8]  / 10 });\nnode.send({ topic: `${base}/Frequency_Grid_Hz`,   payload: r[g+9]  / 100 });\nnode.send({ topic: `${base}/ActivePower_Total_W`, payload: i32(r[g+10], r[g+11]) });\nnode.send({ topic: `${base}/Energy_Today_kWh`,    payload: u32(r[g+12], r[g+13]) / 10 });\nnode.send({ topic: `${base}/Energy_Total_kWh`,    payload: u32(r[g+14], r[g+15]) / 10 });\n// r[g+16], r[g+17] = GenerationTime_Total — odczytywane w slow poll\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1230,
        "y": 160,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "8729e49e46bcb86d",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse PV Power+V+I 11028 (qty:14)",
        "func": "// Base 11028, qty:14 => r[0..13]\n// r[0..1]  PV_InputPower_Total (u32)\n// r[2..3]  gap\n// r[4..7]  Temps (slow poll handles these, but we parse anyway for completeness)\n// r[10..13] PV1V, PV1I, PV2V, PV2I\nconst base = \"Selfa_SFH_12.1\";\nconst r = msg.payload;\nfunction u32(hi, lo) { return (((hi >>> 0) * 65536) + (lo >>> 0)) >>> 0; }\nconst pv1_v = r[10] / 10;\nconst pv1_i = r[11] / 10;\nconst pv2_v = r[12] / 10;\nconst pv2_i = r[13] / 10;\nnode.send({ topic: `${base}/PV_InputPower_Total_W`, payload: u32(r[0], r[1]) });\nnode.send({ topic: `${base}/Voltage_PV1_V`,         payload: pv1_v });\nnode.send({ topic: `${base}/Current_PV1_A`,         payload: pv1_i });\nnode.send({ topic: `${base}/Power_PV1_W`,           payload: Math.round(pv1_v * pv1_i * 10) / 10 });\nnode.send({ topic: `${base}/Voltage_PV2_V`,         payload: pv2_v });\nnode.send({ topic: `${base}/Current_PV2_A`,         payload: pv2_i });\nnode.send({ topic: `${base}/Power_PV2_W`,           payload: Math.round(pv2_v * pv2_i * 10) / 10 });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1230,
        "y": 200,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "45a41c4e4b939c3c",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse Backup+TotalBackupP 30200 (qty:32)",
        "func": "// Base 30200, qty:32 => r[0..31]\n// Backup A: r[0..9], B: r[10..19], C: r[20..29]\n// TotalBackupP: r[30..31]\nconst base = \"Selfa_SFH_12.1\";\nconst r = msg.payload;\nfunction i32(hi, lo) { const v = ((hi >>> 0) * 65536) + (lo >>> 0); return v > 0x7FFFFFFF ? v - 0x100000000 : v; }\nnode.send({ topic: `${base}/Backup_A_V_V`,            payload: r[0]  / 10 });\nnode.send({ topic: `${base}/Backup_A_I_A`,            payload: r[1]  / 10 });\nnode.send({ topic: `${base}/Backup_A_F_Hz`,           payload: r[2]  / 100 });\nnode.send({ topic: `${base}/Backup_A_P_W`,            payload: i32(r[4],  r[5]) });\nnode.send({ topic: `${base}/Backup_B_V_V`,            payload: r[10] / 10 });\nnode.send({ topic: `${base}/Backup_B_I_A`,            payload: r[11] / 10 });\nnode.send({ topic: `${base}/Backup_B_F_Hz`,           payload: r[12] / 100 });\nnode.send({ topic: `${base}/Backup_B_P_W`,            payload: i32(r[14], r[15]) });\nnode.send({ topic: `${base}/Backup_C_V_V`,            payload: r[20] / 10 });\nnode.send({ topic: `${base}/Backup_C_I_A`,            payload: r[21] / 10 });\nnode.send({ topic: `${base}/Backup_C_F_Hz`,           payload: r[22] / 100 });\nnode.send({ topic: `${base}/Backup_C_P_W`,            payload: i32(r[24], r[25]) });\nnode.send({ topic: `${base}/Total_Backup_P_W`,        payload: i32(r[30], r[31]) });\nnode.send({ topic: `${base}/Total_Backup_ActiveP_kW`, payload: i32(r[30], r[31]) / 1000 });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 240,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "a31e8e197bb7eb97",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse Battery 30254 (qty:6)",
        "func": "const base = \"Selfa_SFH_12.1\";\nconst r = msg.payload;\nfunction i32(hi, lo) { const v = ((hi >>> 0) * 65536) + (lo >>> 0); return v > 0x7FFFFFFF ? v - 0x100000000 : v; }\nfunction i16(v) { return v > 0x7FFF ? v - 0x10000 : v; }\nconst modeMap = { 0: \"Discharge\", 1: \"Charge\" };\nnode.send({ topic: `${base}/Battery_V_V`,  payload: r[0] / 10 });\nnode.send({ topic: `${base}/Battery_I_A`,  payload: i16(r[1]) / 10 });\nnode.send({ topic: `${base}/Battery_Mode`, payload: modeMap[r[2]] !== undefined ? modeMap[r[2]] : r[2] });\nnode.send({ topic: `${base}/Battery_P_W`,  payload: i32(r[4], r[5]) });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1220,
        "y": 280,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "8f3a07ebc5ccc49c",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse BMS Core 33000 (qty:4)",
        "func": "// r[0]=SOC, r[1]=SOH, r[2]=BMS_Status, r[3]=BMS_Pack_Temp\nconst base = \"Selfa_SFH_12.1\";\nconst r = msg.payload;\nnode.send({ topic: `${base}/SOC_pct`,                payload: r[0] / 100 });\nnode.send({ topic: `${base}/SOH_pct`,                payload: r[1] / 100 });\nnode.send({ topic: `${base}/BMS_Status`,             payload: r[2] });\nnode.send({ topic: `${base}/BMS_Pack_Temperature_C`, payload: r[3] / 10 });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1220,
        "y": 320,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "31a21f14303dfb6e",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse Working Mode 50000",
        "func": "const base = \"Selfa_SFH_12.1\";\nconst raw = msg.payload[0];\nconst hi = (raw >> 8) & 0xFF;\nconst lo = raw & 0xFF;\nlet mode;\nif      (hi === 0x01 && lo === 0x01) mode = \"General Mode\";\nelse if (hi === 0x01 && lo === 0x02) mode = \"Economic Mode\";\nelse if (hi === 0x01 && lo === 0x03) mode = \"UPS Mode\";\nelse if (hi === 0x02)                mode = \"Off Grid Mode\";\nelse if (hi === 0x03 && lo === 0x01) mode = \"EMS: AC Control Mode\";\nelse if (hi === 0x03 && lo === 0x02) mode = \"EMS: General Mode\";\nelse if (hi === 0x03 && lo === 0x03) mode = \"EMS: Battery Control Mode\";\nelse if (hi === 0x03 && lo === 0x04) mode = \"EMS: Off Grid Mode\";\nelse mode = `Unknown (0x${raw.toString(16).padStart(4,'0').toUpperCase()})`;\nnode.send({ topic: `${base}/Working_Mode_raw`, payload: raw });\nnode.send({ topic: `${base}/Working_Mode`,     payload: mode });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1220,
        "y": 360,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "c234053c41da6baa",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse Faults 10112 (qty:10)",
        "func": "// Base 10112, qty:10 => r[0..9]\n// r[0..1]  FLAG1 (10112-10113)\n// r[2..3]  FLAG2 (10114-10115)\n// r[8..9]  FLAG3 (10120-10121)\nconst base = \"Selfa_SFH_12.1\";\nconst r = msg.payload;\nconst flag1 = ((r[0] >>> 0) * 65536 + (r[1] >>> 0)) >>> 0;\nconst flag2 = ((r[2] >>> 0) * 65536 + (r[3] >>> 0)) >>> 0;\nconst flag3 = ((r[8] >>> 0) * 65536 + (r[9] >>> 0)) >>> 0;\nnode.send({ topic: `${base}/Fault_FLAG1`, payload: flag1 });\nnode.send({ topic: `${base}/Fault_FLAG2`, payload: flag2 });\nnode.send({ topic: `${base}/Fault_FLAG3`, payload: flag3 });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1220,
        "y": 480,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "e7c6aa06f7adcb7b",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse GenHours+Temp 11022 (qty:20)",
        "func": "// Base 11022, qty:20 => r[0..19]\n// r[0..1]  GenerationTime_Total (11022-11023)\n// r[2..5]  gap (11024-11027, ignored)\n// r[6..19] = 11028-11041 (PV block)\n//   r[6..7]  PV_InputPower_Total\n//   r[8..9]  gap\n//   r[10..13] Temp1..4\n//   r[16..19] PV1V, PV1I, PV2V, PV2I\nconst base = \"Selfa_SFH_12.1\";\nconst r = msg.payload;\nfunction u32(hi, lo) { return (((hi >>> 0) * 65536) + (lo >>> 0)) >>> 0; }\nfunction i16(v) { return v > 0x7FFF ? v - 0x10000 : v; }\nnode.send({ topic: `${base}/GenerationTime_Total_h`, payload: u32(r[0], r[1]) });\nnode.send({ topic: `${base}/Temperature_1_C`,        payload: i16(r[10]) / 10 });\nnode.send({ topic: `${base}/Temperature_2_C`,        payload: i16(r[11]) / 10 });\nnode.send({ topic: `${base}/Temperature_3_C`,        payload: i16(r[12]) / 10 });\nnode.send({ topic: `${base}/Temperature_4_C`,        payload: i16(r[13]) / 10 });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1230,
        "y": 520,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "023f6d22b821af4e",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse BMS Detail 33004 (qty:16)",
        "func": "// Base 33004, qty:16 => r[0..15]\n// Mapping relative to original 33000 block:\n// original r[8..15] = 33008-33015 => here r[4..11]\n// original r[16..19] = 33016-33019 => here r[12..15]\nconst base = \"Selfa_SFH_12.1\";\nconst r = msg.payload;\nfunction u32(hi, lo) { return (((hi >>> 0) * 65536) + (lo >>> 0)) >>> 0; }\n// r[4]=Max_Cell_Temp_ID, r[5]=Max_Cell_Temp_C, r[6]=Min_Cell_Temp_ID, r[7]=Min_Cell_Temp_C\n// r[8]=Max_Cell_V_ID,    r[9]=Max_Cell_V,      r[10]=Min_Cell_V_ID,   r[11]=Min_Cell_V\n// r[12..13]=BMS_ERROR_CODE, r[14..15]=BMS_WARN_CODE\nnode.send({ topic: `${base}/Max_Cell_Temperature_ID`, payload: r[4] });\nnode.send({ topic: `${base}/Max_Cell_Temperature_C`,  payload: r[5]  / 10 });\nnode.send({ topic: `${base}/Min_Cell_Temperature_ID`, payload: r[6] });\nnode.send({ topic: `${base}/Min_Cell_Temperature_C`,  payload: r[7]  / 10 });\nnode.send({ topic: `${base}/Max_Cell_Voltage_ID`,     payload: r[8] });\nnode.send({ topic: `${base}/Max_Cell_Voltage_V`,      payload: r[9]  / 1000 });\nnode.send({ topic: `${base}/Min_Cell_Voltage_ID`,     payload: r[10] });\nnode.send({ topic: `${base}/Min_Cell_Voltage_V`,      payload: r[11] / 1000 });\nnode.send({ topic: `${base}/BMS_ERROR_CODE`,          payload: u32(r[12], r[13]) });\nnode.send({ topic: `${base}/BMS_WARN_CODE`,           payload: u32(r[14], r[15]) });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1230,
        "y": 560,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "c594267128390ec1",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse Daily Energy 31000 (qty:9)",
        "func": "const base = \"Selfa_SFH_12.1\";\nconst r = msg.payload;\nnode.send({ topic: `${base}/Daily_Grid_Injection_kWh`,   payload: r[0] / 10 });\nnode.send({ topic: `${base}/Daily_Grid_Purchase_kWh`,    payload: r[1] / 10 });\nnode.send({ topic: `${base}/Daily_Backup_Output_kWh`,    payload: r[2] / 10 });\nnode.send({ topic: `${base}/Daily_Batt_Charge_kWh`,      payload: r[3] / 10 });\nnode.send({ topic: `${base}/Daily_Batt_Discharge_kWh`,   payload: r[4] / 10 });\nnode.send({ topic: `${base}/Daily_PV_Generation_kWh`,    payload: r[5] / 10 });\nnode.send({ topic: `${base}/Daily_Load_Consumption_kWh`, payload: r[6] / 10 });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1220,
        "y": 600,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "3e589b93139b843a",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Parse Total Energy 31102 (qty:18)",
        "func": "const base = \"Selfa_SFH_12.1\";\nconst r = msg.payload;\nfunction u32(hi, lo) { return (((hi >>> 0) * 65536) + (lo >>> 0)) >>> 0; }\nnode.send({ topic: `${base}/Total_Grid_Injection_kWh`,   payload: u32(r[0],  r[1])  / 10 });\nnode.send({ topic: `${base}/Total_Grid_Purchase_kWh`,    payload: u32(r[2],  r[3])  / 10 });\nnode.send({ topic: `${base}/Total_Backup_Output_kWh`,    payload: u32(r[4],  r[5])  / 10 });\nnode.send({ topic: `${base}/Total_Batt_Charge_kWh`,      payload: u32(r[6],  r[7])  / 10 });\nnode.send({ topic: `${base}/Total_Batt_Discharge_kWh`,   payload: u32(r[8],  r[9])  / 10 });\nnode.send({ topic: `${base}/Total_PV_Generation_kWh`,    payload: u32(r[10], r[11]) / 10 });\nnode.send({ topic: `${base}/Total_Load_Consumption_kWh`, payload: u32(r[12], r[13]) / 10 });\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1230,
        "y": 640,
        "wires": [
            [
                "79ab283c748ec065"
            ]
        ]
    },
    {
        "id": "83173419c9b8e16a",
        "type": "mqtt in",
        "z": "4b3cc34dbff8443d",
        "name": "Set Working Mode",
        "topic": "Selfa_SFH_12.1/set/Working_Mode",
        "qos": "1",
        "datatype": "utf8",
        "broker": "49b255e065ce7528",
        "nl": false,
        "rap": false,
        "rh": 0,
        "inputs": 0,
        "x": 110,
        "y": 780,
        "wires": [
            [
                "59464d55b466030d"
            ]
        ]
    },
    {
        "id": "59464d55b466030d",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Build FC16 Write 50000",
        "func": "const modeMap = {\n  \"General Mode\":              0x0101,\n  \"Economic Mode\":             0x0102,\n  \"UPS Mode\":                  0x0103,\n  \"Off Grid Mode\":             0x0200,\n  \"EMS: AC Control Mode\":      0x0301,\n  \"EMS: General Mode\":         0x0302,\n  \"EMS: Battery Control Mode\": 0x0303,\n  \"EMS: Off Grid Mode\":        0x0304\n};\nconst name = (msg.payload || \"\").trim();\nif (!modeMap.hasOwnProperty(name)) {\n  node.warn(`Unknown working mode: \"${name}\"`);\n  return null;\n}\nconst value = modeMap[name];\nmsg.payload = {\n  fc: 16,\n  unitid: 247,\n  address: 50000,\n  quantity: 1,\n  value: [value]\n};\nnode.status({ fill: \"blue\", shape: \"dot\", text: `Write → ${name} (0x${value.toString(16).padStart(4,'0').toUpperCase()})` });\nreturn msg;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 390,
        "y": 780,
        "wires": [
            [
                "09611b332b2fa307"
            ]
        ]
    },
    {
        "id": "09611b332b2fa307",
        "type": "modbus-flex-write",
        "z": "4b3cc34dbff8443d",
        "name": "Modbus Write 50000",
        "showStatusActivities": true,
        "showErrors": true,
        "showWarnings": true,
        "server": "6130f85f6f241522",
        "emptyMsgOnFail": false,
        "keepMsgProperties": false,
        "delayOnStart": false,
        "startDelayTime": "",
        "x": 660,
        "y": 780,
        "wires": [
            [
                "a1fc3a2b1cbd169e"
            ],
            [
                "24cbad168342fafa"
            ]
        ]
    },
    {
        "id": "a1fc3a2b1cbd169e",
        "type": "function",
        "z": "4b3cc34dbff8443d",
        "name": "Write OK → log",
        "func": "node.status({ fill: \"green\", shape: \"dot\", text: \"Write OK\" });\nnode.log(`Working Mode write OK: address=${msg.payload.address}, value=0x${msg.payload.value.toString(16).toUpperCase()}`);\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 900,
        "y": 760,
        "wires": [
            []
        ]
    },
    {
        "id": "24cbad168342fafa",
        "type": "debug",
        "z": "4b3cc34dbff8443d",
        "name": "Write ERR",
        "active": true,
        "tosidebar": true,
        "complete": "true",
        "targetType": "full",
        "x": 890,
        "y": 800,
        "wires": []
    },
    {
        "id": "79ab283c748ec065",
        "type": "mqtt out",
        "z": "4b3cc34dbff8443d",
        "name": "MQTT out",
        "topic": "",
        "qos": "0",
        "retain": "false",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "49b255e065ce7528",
        "x": 1500,
        "y": 400,
        "wires": []
    },
    {
        "id": "4157ee40d22b8d1e",
        "type": "mqtt out",
        "z": "4b3cc34dbff8443d",
        "name": "MQTT out (Discovery)",
        "topic": "",
        "qos": "1",
        "retain": "true",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "49b255e065ce7528",
        "x": 800,
        "y": 80,
        "wires": []
    },
    {
        "id": "6130f85f6f241522",
        "type": "modbus-client",
        "name": "Selfa SFH 12.1 – Waveshare",
        "clienttype": "tcp",
        "bufferCommands": true,
        "stateLogEnabled": false,
        "queueLogEnabled": false,
        "failureLogEnabled": true,
        "tcpHost": "192.168.20.85",
        "tcpPort": "9999",
        "tcpType": "TCP-RTU-BUFFERED",
        "serialPort": "/dev/ttyUSB0",
        "serialType": "RTU-BUFFERD",
        "serialBaudrate": "9600",
        "serialDatabits": "8",
        "serialStopbits": "1",
        "serialParity": "none",
        "serialConnectionDelay": "100",
        "serialAsciiResponseStartDelimiter": "",
        "unit_id": 247,
        "commandDelay": 300,
        "clientTimeout": 15000,
        "reconnectOnTimeout": true,
        "reconnectTimeout": 2000,
        "parallelUnitIdsAllowed": false,
        "showErrors": true,
        "showWarnings": true,
        "showLogs": false
    },
    {
        "id": "49b255e065ce7528",
        "type": "mqtt-broker",
        "name": "",
        "broker": "a0d7b954-emqx",
        "port": "1883",
        "clientid": "",
        "autoConnect": true,
        "usetls": false,
        "protocolVersion": "4",
        "keepalive": "60",
        "cleansession": true,
        "autoUnsubscribe": true,
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": "",
        "birthMsg": {},
        "closeTopic": "",
        "closeQos": "0",
        "closePayload": "",
        "closeMsg": {},
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "willMsg": {},
        "userProps": "",
        "sessionExpiry": ""
    },
    {
        "id": "5f742df11ae65b9b",
        "type": "global-config",
        "env": [],
        "modules": {
            "node-red-contrib-modbus": "5.45.2"
        }
    }
]