Multiple Smart Shunts for SOC?

Hello,

I am quite dissatisfied with the accuracy of the SOC calculation of my three JK BMS units. Therefore, I am considering replacing the SOC calculation with three Victron SmartShunt 300A units and calculating the total SOC of my three LiFePO₄ battery packs based on these.

Due to the existing system layout, installing only one SmartShunt would require significant modification effort. Additionally, I prefer to avoid creating a single high-current “hot spot,” as this would introduce a single point of failure.

However, I understand that within the Victron system only one main shunt can be used for SOC control.

Could you recommend a solution for using three SmartShunts and calculating the combined SOC via Node-RED, then feeding this calculated total SOC back into the Victron system?

Since I am using a Multiplus-II GX, the Node-RED implementation would need to be lightweight. Node-Red on the MP2 is already in use.

Thank you very much in advance.

Easiest way would be to write a flow that collates all the data from your shunts, then use a virtual battery node and inject the relevant values into that.

2 Likes

Thanks. Do you recommend to fully disconnect the JK BMS currently connected by CAN to the system?

Or just use the new calculated SOC from Node-Red and “overwrite” the SOC from CAN?

If it isn’t set to be used as a monitor or dvcc control, then there is little harm in leaving it connected for monitoring of what it is sending, even if it’s inaccurate.

which is currently the case. So have to learn to decouple it and use the Victron monitor instead. Hope that on wednesday my first smart shunt will arive to start testing. Thanks!

Are there best practise examples?
What is the disadvantage of keeping the JK BMS via CAN for DVCC Control but for batterie monitor using the virtual battery calculated from my 3 shunts.

Thinking about using this as starting point and the set of data which has to be in the virtual battery seems to be handy: SOC, Voltage & Current

To risky and sensitive for single point of failures?

DVCC will use what the JK BMS sends to control all charging. So if it is inaccurate your system/ESS would not work effectively.
It isn’t a good idea to have different sources for information.

Agree.

I tried to avoid missing essential needed data for my virtual battery.

To get a full scope battery for monitor and DVCC I´m collecting what has to in the virtual battery:

Voltage: Shunts (Source)
Current: Shunts
SOC: Shunts
CVL: JK BMS
CCL: JK BMS
DCL: JK BMS
Temperature: JK BMS
Any error detection from JK BMS?

Anything missing?

I would, assuming you can read/write the values, send cell min/max voltages and temperatures.

1 Like

Check out the iBMS for the JK PB series BMS and the SmartShunt integration option. I think this might be a simpler solution for you. See here: iBMS for JK-BMS PB(Inverter) Series – JamesTronics

I appreciate the suggestion, but from my perspective “simple” really depends on how you look at it.
Adding extra hardware always introduces additional points of failure, more wiring, more dependencies, and significantly higher costs. A device costing €259 is roughly three times the price of a JK‑BMS — and for what ultimately amounts to functionality we can already achieve with the components we have.

My intention here is not to complicate things, but to avoid unnecessary hardware and instead create a clean, transparent, community‑driven solution. Based on the progress we’ve already made, we are very close to having a fully working setup.

If the community is open to it, I’d be more than happy to continue developing this together and shape it into a polished, reliable solution that everyone can benefit from.

I´m testing with 1 Shunt at the moment and my feeling because of many read inputs and outputs the system is getting slow and unresponsive which seems not to be a good thing for a virt battery in control.

Do you see things to do much more effective? Already tried some filters to reduce written outputs

[
    {
        "id": "e4f5e8533ac57fae",
        "type": "tab",
        "label": "Flow 2",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "0413d13423080ed7",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Dc/0/Voltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Dc/0/Voltage",
            "type": "float",
            "name": "Battery voltage (V)"
        },
        "name": "Voltage Shunt #3",
        "onlyChanges": false,
        "x": 240,
        "y": 460,
        "wires": [
            [
                "9516d1918b332043"
            ]
        ]
    },
    {
        "id": "77c3d173c4a16a55",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Dc/0/Power",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Dc/0/Power",
            "name": "/Dc/0/Power",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 990,
        "y": 600,
        "wires": []
    },
    {
        "id": "e12958100cc4e2aa",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Info/MaxChargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Info/MaxChargeCurrent",
            "name": "/Info/MaxChargeCurrent",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1030,
        "y": 760,
        "wires": []
    },
    {
        "id": "b575872270083217",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Info/MaxDischargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Info/MaxDischargeCurrent",
            "name": "/Info/MaxDischargeCurrent",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1030,
        "y": 820,
        "wires": []
    },
    {
        "id": "71ee0fe4c9a413c3",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Info/MaxChargeVoltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Info/MaxChargeVoltage",
            "name": "/Info/MaxChargeVoltage",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1030,
        "y": 880,
        "wires": []
    },
    {
        "id": "080f1cfea9732d56",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Dc/0/Current",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Dc/0/Current",
            "type": "float",
            "name": "Battery current (A)"
        },
        "name": "Current Shunt #3",
        "onlyChanges": false,
        "x": 240,
        "y": 320,
        "wires": [
            [
                "3eed14f544f8bbb1"
            ]
        ]
    },
    {
        "id": "caece4e0f918de3a",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Dc/0/Power",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Dc/0/Power",
            "type": "float",
            "name": "Battery power (W)"
        },
        "name": "Power Shunt #3",
        "onlyChanges": false,
        "x": 240,
        "y": 600,
        "wires": [
            [
                "50baab5836c6e8ce"
            ]
        ]
    },
    {
        "id": "bcbefad20fe64b99",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Soc",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Soc",
            "type": "float",
            "name": "State of charge (%)"
        },
        "name": "SOC Shunt #3",
        "onlyChanges": false,
        "x": 250,
        "y": 200,
        "wires": [
            [
                "7b2518194ffeaf8b"
            ]
        ]
    },
    {
        "id": "35755d2f9138d667",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "SOC",
        "func": "let soc = context.get(\"soc\") || {};\n\n// Neuen SOC-Wert speichern\nsoc[msg.service] = msg.payload;\ncontext.set(\"soc\", soc);\n\n// Durchschnitt aller vorhandenen SOC-Werte berechnen\nlet sum = 0;\nlet count = 0;\n\nfor (let key in soc) {\n    let value = soc[key];\n    if (value != null && typeof value === \"number\") {\n        sum += value;\n        count++;\n    }\n}\n\n// Wenn mindestens ein Wert vorhanden ist, Durchschnitt zurückgeben\nif (count > 0) {\n    let avg = sum / count;\n    return { payload: avg };\n}\n\nreturn null;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 690,
        "y": 200,
        "wires": [
            [
                "74e667e16030d291"
            ]
        ]
    },
    {
        "id": "7f902812e40b31ed",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "Current",
        "func": "let current = context.get(\"current\") || {};\n\n// Neuen Shunt-Wert speichern\ncurrent[msg.service] = msg.payload;\ncontext.set(\"current\", current);\n\n// Summe aller Shunt-Werte berechnen\nlet sum = 0;\nlet hasValue = false;\n\nfor (let key in current) {\n    let value = current[key];\n    if (value != null && typeof value === \"number\") {\n        sum += value;\n        hasValue = true;\n    }\n}\n\n// Wenn mindestens ein Wert vorhanden ist, zurückgeben\nif (hasValue) {\n    return { payload: sum };\n}\n\nreturn null;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 700,
        "y": 320,
        "wires": [
            [
                "953f20d917b4ec6d"
            ]
        ]
    },
    {
        "id": "3e745bc230da5075",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "Voltage",
        "func": "let volt = context.get(\"volt\") || {};\n\n// Wert speichern (pro Service)\nvolt[msg.service] = msg.payload;\n\ncontext.set(\"volt\", volt);\n\n// Alle vorhandenen Werte sammeln\nlet values = Object.values(volt).filter(v => v !== null && v !== undefined);\n\n// Wenn mindestens 1 Wert vorhanden → Mittelwert\nif (values.length > 0) {\n    let avg = values.reduce((a,b)=>a+b,0) / values.length;\n    return { payload: avg };\n}\n\n// Wenn keiner da → nichts senden\nreturn null;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 700,
        "y": 460,
        "wires": [
            [
                "db603f1b55d34603"
            ]
        ]
    },
    {
        "id": "bc3387b7dba1b08f",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "Power",
        "func": "let current = context.get(\"current\") || {};\n\n// Neuen Shunt-Wert speichern\ncurrent[msg.service] = msg.payload;\ncontext.set(\"current\", current);\n\n// Summe aller vorhandenen Shunt-Werte berechnen\nlet sum = 0;\nlet count = 0;\n\nfor (let key in current) {\n    let value = current[key];\n    if (value != null && typeof value === \"number\") {\n        sum += value;\n        count++;\n    }\n}\n\n// Wenn mindestens ein Wert vorhanden ist, zurückgeben\nif (count > 0) {\n    return { payload: sum };\n}\n\nreturn null;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 690,
        "y": 600,
        "wires": [
            [
                "77c3d173c4a16a55"
            ]
        ]
    },
    {
        "id": "3eed14f544f8bbb1",
        "type": "rbe",
        "z": "e4f5e8533ac57fae",
        "name": "Deadband 0,1A",
        "func": "deadband",
        "gap": "0.1",
        "start": "",
        "inout": "out",
        "septopics": true,
        "property": "payload",
        "topi": "topic",
        "x": 480,
        "y": 320,
        "wires": [
            [
                "7f902812e40b31ed"
            ]
        ]
    },
    {
        "id": "9516d1918b332043",
        "type": "rbe",
        "z": "e4f5e8533ac57fae",
        "name": "Deadband 0,1V",
        "func": "deadband",
        "gap": "0.1",
        "start": "",
        "inout": "out",
        "septopics": true,
        "property": "payload",
        "topi": "topic",
        "x": 480,
        "y": 460,
        "wires": [
            [
                "3e745bc230da5075"
            ]
        ]
    },
    {
        "id": "7b2518194ffeaf8b",
        "type": "rbe",
        "z": "e4f5e8533ac57fae",
        "name": "Deadband 0,1%",
        "func": "deadband",
        "gap": "0.1",
        "start": "",
        "inout": "out",
        "septopics": true,
        "property": "payload",
        "topi": "topic",
        "x": 480,
        "y": 200,
        "wires": [
            [
                "35755d2f9138d667"
            ]
        ]
    },
    {
        "id": "50baab5836c6e8ce",
        "type": "rbe",
        "z": "e4f5e8533ac57fae",
        "name": "Deadband 5W",
        "func": "deadband",
        "gap": "5",
        "property": "payload",
        "x": 480,
        "y": 600,
        "wires": [
            [
                "bc3387b7dba1b08f"
            ]
        ]
    },
    {
        "id": "85777564eba91aa0",
        "type": "victron-virtual",
        "z": "e4f5e8533ac57fae",
        "name": "virt.Battery",
        "device": "battery",
        "default_values": false,
        "battery_capacity": "942",
        "include_battery_temperature": true,
        "grid_nrofphases": 1,
        "include_motor_temp": false,
        "include_controller_temp": false,
        "include_coolant_temp": false,
        "include_motor_rpm": true,
        "include_motor_direction": true,
        "position": 0,
        "pvinverter_nrofphases": 1,
        "fluid_type": 0,
        "include_tank_battery": false,
        "include_tank_temperature": false,
        "tank_battery_voltage": 3.3,
        "tank_capacity": 0.2,
        "temperature_type": 2,
        "include_humidity": false,
        "include_pressure": false,
        "include_temp_battery": false,
        "temp_battery_voltage": 3.3,
        "x": 980,
        "y": 80,
        "wires": []
    },
    {
        "id": "74e667e16030d291",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Soc",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Soc",
            "name": "/Soc",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 960,
        "y": 200,
        "wires": []
    },
    {
        "id": "953f20d917b4ec6d",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Dc/0/Current",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Dc/0/Current",
            "name": "/Dc/0/Current",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 990,
        "y": 320,
        "wires": []
    },
    {
        "id": "db603f1b55d34603",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Dc/0/Voltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Dc/0/Voltage",
            "name": "/Dc/0/Voltage",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 990,
        "y": 460,
        "wires": []
    },
    {
        "id": "48cd38e59ea73c8a",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Dc/0/Temperature",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Dc/0/Temperature",
            "name": "/Dc/0/Temperature",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1010,
        "y": 700,
        "wires": []
    },
    {
        "id": "4fa7621d61c24168",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Dc/0/Temperature",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Dc/0/Temperature",
            "type": "float",
            "name": "Battery temperature (°C)"
        },
        "name": "",
        "onlyChanges": false,
        "x": 280,
        "y": 700,
        "wires": [
            [
                "48cd38e59ea73c8a"
            ]
        ]
    },
    {
        "id": "d13da215a334edd5",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Info/MaxChargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Info/MaxChargeCurrent",
            "type": "float",
            "name": "CCL - Charge Current Limit (A)"
        },
        "name": "",
        "onlyChanges": false,
        "x": 300,
        "y": 760,
        "wires": [
            [
                "e12958100cc4e2aa"
            ]
        ]
    },
    {
        "id": "19c6012e46019fe7",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Info/MaxDischargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Info/MaxDischargeCurrent",
            "type": "float",
            "name": "DCL - Discharge Current Limit (A)"
        },
        "name": "",
        "onlyChanges": false,
        "x": 310,
        "y": 820,
        "wires": [
            [
                "b575872270083217"
            ]
        ]
    },
    {
        "id": "41da1451bdc4071b",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Info/MaxChargeVoltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Info/MaxChargeVoltage",
            "type": "float",
            "name": "CVL - Charge Voltage Limit (V)"
        },
        "name": "",
        "onlyChanges": false,
        "x": 300,
        "y": 880,
        "wires": [
            [
                "71ee0fe4c9a413c3"
            ]
        ]
    }
]

The obvious things are to restrict how often updates are triggered. The victron nodes can be set to send updates only.
Where this isn’t possible filters are best as you have stated.
For larger flows I do prefer writing a single function, this can be more efficient.

1 Like

Thanks. Adjusted to build in update only function.
For most beneficial data points like CVL, DCL, CCL which are not often changing this creates a problem for initial one shot data transfer to DBus Output at start (of the flow or reboot).
Bringing a simple delay in, helps to have DBus ready for writing.

Looks good and I can go on:

[
    {
        "id": "e4f5e8533ac57fae",
        "type": "tab",
        "label": "virt.Battery",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "0413d13423080ed7",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Dc/0/Voltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Dc/0/Voltage",
            "type": "float",
            "name": "Battery voltage (V)"
        },
        "name": "Voltage Shunt #3",
        "onlyChanges": true,
        "roundValues": "2",
        "x": 220,
        "y": 460,
        "wires": [
            [
                "3e745bc230da5075"
            ]
        ]
    },
    {
        "id": "77c3d173c4a16a55",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Dc/0/Power",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Dc/0/Power",
            "name": "/Dc/0/Power",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 990,
        "y": 600,
        "wires": []
    },
    {
        "id": "e12958100cc4e2aa",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Info/MaxChargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Info/MaxChargeCurrent",
            "name": "/Info/MaxChargeCurrent",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1030,
        "y": 840,
        "wires": []
    },
    {
        "id": "b575872270083217",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Info/MaxDischargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Info/MaxDischargeCurrent",
            "name": "/Info/MaxDischargeCurrent",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1030,
        "y": 900,
        "wires": []
    },
    {
        "id": "71ee0fe4c9a413c3",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Info/MaxChargeVoltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Info/MaxChargeVoltage",
            "name": "/Info/MaxChargeVoltage",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1030,
        "y": 960,
        "wires": []
    },
    {
        "id": "080f1cfea9732d56",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Dc/0/Current",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Dc/0/Current",
            "type": "float",
            "name": "Battery current (A)"
        },
        "name": "Current Shunt #3",
        "onlyChanges": true,
        "roundValues": "1",
        "x": 220,
        "y": 320,
        "wires": [
            [
                "7f902812e40b31ed"
            ]
        ]
    },
    {
        "id": "caece4e0f918de3a",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Dc/0/Power",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Dc/0/Power",
            "type": "float",
            "name": "Battery power (W)"
        },
        "name": "Power Shunt #3",
        "onlyChanges": true,
        "roundValues": "0",
        "x": 220,
        "y": 600,
        "wires": [
            [
                "bc3387b7dba1b08f"
            ]
        ]
    },
    {
        "id": "bcbefad20fe64b99",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Soc",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Soc",
            "type": "float",
            "name": "State of charge (%)"
        },
        "name": "SOC Shunt #3",
        "onlyChanges": true,
        "roundValues": "1",
        "x": 210,
        "y": 200,
        "wires": [
            [
                "35755d2f9138d667"
            ]
        ]
    },
    {
        "id": "35755d2f9138d667",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "SOC",
        "func": "let soc = context.get(\"soc\") || {};\n\n// Neuen SOC-Wert speichern\nsoc[msg.service] = msg.payload;\ncontext.set(\"soc\", soc);\n\n// Durchschnitt aller vorhandenen SOC-Werte berechnen\nlet sum = 0;\nlet count = 0;\n\nfor (let key in soc) {\n    let value = soc[key];\n    if (value != null && typeof value === \"number\") {\n        sum += value;\n        count++;\n    }\n}\n\n// Wenn mindestens ein Wert vorhanden ist, Durchschnitt zurückgeben\nif (count > 0) {\n    let avg = sum / count;\n    return { payload: avg };\n}\n\nreturn null;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 650,
        "y": 200,
        "wires": [
            [
                "74e667e16030d291"
            ]
        ]
    },
    {
        "id": "7f902812e40b31ed",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "Current",
        "func": "let current = context.get(\"current\") || {};\n\n// Neuen Shunt-Wert speichern\ncurrent[msg.service] = msg.payload;\ncontext.set(\"current\", current);\n\n// Summe aller Shunt-Werte berechnen\nlet sum = 0;\nlet hasValue = false;\n\nfor (let key in current) {\n    let value = current[key];\n    if (value != null && typeof value === \"number\") {\n        sum += value;\n        hasValue = true;\n    }\n}\n\n// Wenn mindestens ein Wert vorhanden ist, zurückgeben\nif (hasValue) {\n    return { payload: sum };\n}\n\nreturn null;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 660,
        "y": 320,
        "wires": [
            [
                "953f20d917b4ec6d"
            ]
        ]
    },
    {
        "id": "3e745bc230da5075",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "Voltage",
        "func": "let volt = context.get(\"volt\") || {};\n\n// Wert speichern (pro Service)\nvolt[msg.service] = msg.payload;\n\ncontext.set(\"volt\", volt);\n\n// Alle vorhandenen Werte sammeln\nlet values = Object.values(volt).filter(v => v !== null && v !== undefined);\n\n// Wenn mindestens 1 Wert vorhanden → Mittelwert\nif (values.length > 0) {\n    let avg = values.reduce((a,b)=>a+b,0) / values.length;\n    return { payload: avg };\n}\n\n// Wenn keiner da → nichts senden\nreturn null;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 660,
        "y": 460,
        "wires": [
            [
                "db603f1b55d34603"
            ]
        ]
    },
    {
        "id": "bc3387b7dba1b08f",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "Power",
        "func": "let current = context.get(\"current\") || {};\n\n// Neuen Shunt-Wert speichern\ncurrent[msg.service] = msg.payload;\ncontext.set(\"current\", current);\n\n// Summe aller vorhandenen Shunt-Werte berechnen\nlet sum = 0;\nlet count = 0;\n\nfor (let key in current) {\n    let value = current[key];\n    if (value != null && typeof value === \"number\") {\n        sum += value;\n        count++;\n    }\n}\n\n// Wenn mindestens ein Wert vorhanden ist, zurückgeben\nif (count > 0) {\n    return { payload: sum };\n}\n\nreturn null;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 650,
        "y": 600,
        "wires": [
            [
                "77c3d173c4a16a55"
            ]
        ]
    },
    {
        "id": "85777564eba91aa0",
        "type": "victron-virtual",
        "z": "e4f5e8533ac57fae",
        "name": "virt.Battery",
        "device": "battery",
        "default_values": false,
        "battery_capacity": "942",
        "include_battery_temperature": true,
        "grid_nrofphases": 1,
        "include_motor_temp": false,
        "include_controller_temp": false,
        "include_coolant_temp": false,
        "include_motor_rpm": true,
        "include_motor_direction": true,
        "position": 0,
        "pvinverter_nrofphases": 1,
        "fluid_type": 0,
        "include_tank_battery": false,
        "include_tank_temperature": false,
        "tank_battery_voltage": 3.3,
        "tank_capacity": 0.2,
        "temperature_type": 2,
        "include_humidity": false,
        "include_pressure": false,
        "include_temp_battery": false,
        "temp_battery_voltage": 3.3,
        "x": 980,
        "y": 80,
        "wires": []
    },
    {
        "id": "74e667e16030d291",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Soc",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Soc",
            "name": "/Soc",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 960,
        "y": 200,
        "wires": []
    },
    {
        "id": "953f20d917b4ec6d",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Dc/0/Current",
        "pathObj": {
            "path": "/Dc/0/Current",
            "name": "/Dc/0/Current",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 940,
        "y": 320,
        "wires": []
    },
    {
        "id": "db603f1b55d34603",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Dc/0/Voltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Dc/0/Voltage",
            "name": "/Dc/0/Voltage",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 990,
        "y": 460,
        "wires": []
    },
    {
        "id": "48cd38e59ea73c8a",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/101",
        "path": "/Dc/0/Temperature",
        "serviceObj": {
            "service": "com.victronenergy.battery/101",
            "name": "virt.Battery (101)"
        },
        "pathObj": {
            "path": "/Dc/0/Temperature",
            "name": "/Dc/0/Temperature",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1010,
        "y": 780,
        "wires": []
    },
    {
        "id": "4fa7621d61c24168",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Dc/0/Temperature",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Dc/0/Temperature",
            "type": "float",
            "name": "Battery temperature (°C)"
        },
        "name": "",
        "onlyChanges": true,
        "roundValues": "1",
        "x": 280,
        "y": 780,
        "wires": [
            [
                "dca27bac0b3b8b66"
            ]
        ]
    },
    {
        "id": "d13da215a334edd5",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Info/MaxChargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Info/MaxChargeCurrent",
            "type": "float",
            "name": "CCL - Charge Current Limit (A)"
        },
        "name": "",
        "onlyChanges": true,
        "roundValues": "0",
        "x": 300,
        "y": 840,
        "wires": [
            [
                "4a83a5e3434f41df"
            ]
        ]
    },
    {
        "id": "19c6012e46019fe7",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Info/MaxDischargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Info/MaxDischargeCurrent",
            "type": "float",
            "name": "DCL - Discharge Current Limit (A)"
        },
        "name": "",
        "onlyChanges": true,
        "roundValues": "0",
        "x": 310,
        "y": 900,
        "wires": [
            [
                "7524d3e4e9fced6e"
            ]
        ]
    },
    {
        "id": "41da1451bdc4071b",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Info/MaxChargeVoltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Info/MaxChargeVoltage",
            "type": "float",
            "name": "CVL - Charge Voltage Limit (V)"
        },
        "name": "",
        "onlyChanges": true,
        "roundValues": "2",
        "x": 300,
        "y": 960,
        "wires": [
            [
                "b35e0cdecdc24c80"
            ]
        ]
    },
    {
        "id": "4a83a5e3434f41df",
        "type": "delay",
        "z": "e4f5e8533ac57fae",
        "name": "Delay 3s",
        "pauseType": "delay",
        "timeout": "3",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 660,
        "y": 840,
        "wires": [
            [
                "e12958100cc4e2aa"
            ]
        ]
    },
    {
        "id": "7524d3e4e9fced6e",
        "type": "delay",
        "z": "e4f5e8533ac57fae",
        "name": "Delay 3s",
        "pauseType": "delay",
        "timeout": "3",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 660,
        "y": 900,
        "wires": [
            [
                "b575872270083217"
            ]
        ]
    },
    {
        "id": "b35e0cdecdc24c80",
        "type": "delay",
        "z": "e4f5e8533ac57fae",
        "name": "Delay 3s",
        "pauseType": "delay",
        "timeout": "3",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 660,
        "y": 960,
        "wires": [
            [
                "71ee0fe4c9a413c3"
            ]
        ]
    },
    {
        "id": "dca27bac0b3b8b66",
        "type": "delay",
        "z": "e4f5e8533ac57fae",
        "name": "Delay 3s",
        "pauseType": "delay",
        "timeout": "3",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 660,
        "y": 780,
        "wires": [
            [
                "48cd38e59ea73c8a"
            ]
        ]
    }
]

On filters you can set them to initial update and then only subsequent changes so values are pushed at restarts.
For victron nodes if you have issues with update only, then rather choose rate limiting - 1 per 5 seconds or so. The filters can do the rest.

If I understood correct this is also the case for victron nodes but the reason why this does not work for me. During initial push at start the DBus Output is not ready to be written and therefore gets lost.

If you are using inject nodes to trigger any of this, you can select the “inject once after x seconds then..” option to delay the initial trigger.

Sure but it would be necessary to make the initial data information available from source to injet or a following logic function. This is not a fix value. The injet has no input to connect, so it was getting to complex out of my view.

No I simply modified the function node for e.g. SOC calculation which is now only delaying first initial trigger. Rest will be transfer without delay. works good.

[
    {
        "id": "e4f5e8533ac57fae",
        "type": "tab",
        "label": "virt.Battery",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "0413d13423080ed7",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Dc/0/Voltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Dc/0/Voltage",
            "type": "float",
            "name": "Battery voltage (V)"
        },
        "name": "Voltage Shunt #3",
        "onlyChanges": true,
        "roundValues": "2",
        "x": 220,
        "y": 460,
        "wires": [
            [
                "voltage_delay_first_only"
            ]
        ]
    },
    {
        "id": "77c3d173c4a16a55",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/100",
        "path": "/Dc/0/Power",
        "serviceObj": {
            "service": "com.victronenergy.battery/100",
            "name": "virt.Battery (100)"
        },
        "pathObj": {
            "path": "/Dc/0/Power",
            "name": "/Dc/0/Power",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 990,
        "y": 600,
        "wires": []
    },
    {
        "id": "e12958100cc4e2aa",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/100",
        "path": "/Info/MaxChargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/100",
            "name": "virt.Battery (100)"
        },
        "pathObj": {
            "path": "/Info/MaxChargeCurrent",
            "name": "/Info/MaxChargeCurrent",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1030,
        "y": 840,
        "wires": []
    },
    {
        "id": "b575872270083217",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/100",
        "path": "/Info/MaxDischargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/100",
            "name": "virt.Battery (100)"
        },
        "pathObj": {
            "path": "/Info/MaxDischargeCurrent",
            "name": "/Info/MaxDischargeCurrent",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1030,
        "y": 900,
        "wires": []
    },
    {
        "id": "71ee0fe4c9a413c3",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/100",
        "path": "/Info/MaxChargeVoltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/100",
            "name": "virt.Battery (100)"
        },
        "pathObj": {
            "path": "/Info/MaxChargeVoltage",
            "name": "/Info/MaxChargeVoltage",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1030,
        "y": 960,
        "wires": []
    },
    {
        "id": "080f1cfea9732d56",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Dc/0/Current",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Dc/0/Current",
            "type": "float",
            "name": "Battery current (A)"
        },
        "name": "Current Shunt #3",
        "onlyChanges": true,
        "roundValues": "1",
        "x": 220,
        "y": 320,
        "wires": [
            [
                "current_delay_first_only"
            ]
        ]
    },
    {
        "id": "caece4e0f918de3a",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Dc/0/Power",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Dc/0/Power",
            "type": "float",
            "name": "Battery power (W)"
        },
        "name": "Power Shunt #3",
        "onlyChanges": true,
        "roundValues": "0",
        "x": 220,
        "y": 600,
        "wires": [
            [
                "bc3387b7dba1b08f"
            ]
        ]
    },
    {
        "id": "bcbefad20fe64b99",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/290",
        "path": "/Soc",
        "serviceObj": {
            "service": "com.victronenergy.battery/290",
            "name": "YiXiang #3"
        },
        "pathObj": {
            "path": "/Soc",
            "type": "float",
            "name": "State of charge (%)"
        },
        "name": "SOC Shunt #3",
        "onlyChanges": true,
        "roundValues": "1",
        "x": 210,
        "y": 200,
        "wires": [
            [
                "soc_delay_first_only"
            ]
        ]
    },
    {
        "id": "bc3387b7dba1b08f",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "Power (delay first message only)",
        "func": "// Prüfen, ob der erste Wert schon gesendet wurde\nlet initialized = context.get('initialized') || false;\n\nif (!initialized) {\n    // ersten Wert verzögern\n    context.set('initialized', true);\n    let firstMsg = RED.util.cloneMessage(msg); // Nachricht klonen\n\n    setTimeout(function() {\n        node.send(firstMsg);\n    }, 3000); // Verzögerung in ms (hier 3 Sekunden)\n\n    // ersten Wert noch nicht sofort weitergeben\n    return null;\n}\n\n// danach Original-Code für alle folgenden Werte\nlet current = context.get(\"current\") || {};\n\n// Neuen Shunt-Wert speichern\ncurrent[msg.service] = msg.payload;\ncontext.set(\"current\", current);\n\n// Summe aller vorhandenen Shunt-Werte berechnen\nlet sum = 0;\nlet count = 0;\n\nfor (let key in current) {\n    let value = current[key];\n    if (value != null && typeof value === \"number\") {\n        sum += value;\n        count++;\n    }\n}\n\n// Wenn mindestens ein Wert vorhanden ist, zurückgeben\nif (count > 0) {\n    return { payload: sum };\n}\n\nreturn null;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 590,
        "y": 600,
        "wires": [
            [
                "77c3d173c4a16a55"
            ]
        ]
    },
    {
        "id": "85777564eba91aa0",
        "type": "victron-virtual",
        "z": "e4f5e8533ac57fae",
        "name": "virt.Battery",
        "device": "battery",
        "default_values": false,
        "battery_capacity": "942",
        "include_battery_temperature": true,
        "grid_nrofphases": 1,
        "include_motor_temp": false,
        "include_controller_temp": false,
        "include_coolant_temp": false,
        "include_motor_rpm": true,
        "include_motor_direction": true,
        "position": 0,
        "pvinverter_nrofphases": 1,
        "fluid_type": 0,
        "include_tank_battery": false,
        "include_tank_temperature": false,
        "tank_battery_voltage": 3.3,
        "tank_capacity": 0.2,
        "temperature_type": 2,
        "include_humidity": false,
        "include_pressure": false,
        "include_temp_battery": false,
        "temp_battery_voltage": 3.3,
        "x": 980,
        "y": 80,
        "wires": []
    },
    {
        "id": "74e667e16030d291",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/100",
        "path": "/Soc",
        "serviceObj": {
            "service": "com.victronenergy.battery/100",
            "name": "virt.Battery (100)"
        },
        "pathObj": {
            "path": "/Soc",
            "name": "/Soc",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 960,
        "y": 200,
        "wires": []
    },
    {
        "id": "953f20d917b4ec6d",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/100",
        "path": "/Dc/0/Current",
        "serviceObj": {
            "service": "com.victronenergy.battery/100",
            "name": "virt.Battery (100)"
        },
        "pathObj": {
            "path": "/Dc/0/Current",
            "name": "/Dc/0/Current",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 990,
        "y": 320,
        "wires": []
    },
    {
        "id": "db603f1b55d34603",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/100",
        "path": "/Dc/0/Voltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/100",
            "name": "virt.Battery (100)"
        },
        "pathObj": {
            "path": "/Dc/0/Voltage",
            "name": "/Dc/0/Voltage",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 990,
        "y": 460,
        "wires": []
    },
    {
        "id": "48cd38e59ea73c8a",
        "type": "victron-output-custom",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/100",
        "path": "/Dc/0/Temperature",
        "serviceObj": {
            "service": "com.victronenergy.battery/100",
            "name": "virt.Battery (100)"
        },
        "pathObj": {
            "path": "/Dc/0/Temperature",
            "name": "/Dc/0/Temperature",
            "type": "object",
            "value": null
        },
        "name": "",
        "onlyChanges": false,
        "x": 1010,
        "y": 780,
        "wires": []
    },
    {
        "id": "4fa7621d61c24168",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Dc/0/Temperature",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Dc/0/Temperature",
            "type": "float",
            "name": "Battery temperature (°C)"
        },
        "name": "",
        "onlyChanges": true,
        "roundValues": "1",
        "x": 280,
        "y": 780,
        "wires": [
            [
                "temperature_delayed"
            ]
        ]
    },
    {
        "id": "d13da215a334edd5",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Info/MaxChargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Info/MaxChargeCurrent",
            "type": "float",
            "name": "CCL - Charge Current Limit (A)"
        },
        "name": "",
        "onlyChanges": true,
        "roundValues": "0",
        "x": 300,
        "y": 840,
        "wires": [
            [
                "maxchargecurrent_delayed"
            ]
        ]
    },
    {
        "id": "19c6012e46019fe7",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Info/MaxDischargeCurrent",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Info/MaxDischargeCurrent",
            "type": "float",
            "name": "DCL - Discharge Current Limit (A)"
        },
        "name": "",
        "onlyChanges": true,
        "roundValues": "0",
        "x": 310,
        "y": 900,
        "wires": [
            [
                "maxdischargecurrent_delayed"
            ]
        ]
    },
    {
        "id": "41da1451bdc4071b",
        "type": "victron-input-battery",
        "z": "e4f5e8533ac57fae",
        "service": "com.victronenergy.battery/512",
        "path": "/Info/MaxChargeVoltage",
        "serviceObj": {
            "service": "com.victronenergy.battery/512",
            "name": "JK-BMS"
        },
        "pathObj": {
            "path": "/Info/MaxChargeVoltage",
            "type": "float",
            "name": "CVL - Charge Voltage Limit (V)"
        },
        "name": "",
        "onlyChanges": true,
        "roundValues": "2",
        "x": 300,
        "y": 960,
        "wires": [
            [
                "maxchargevoltage_delayed"
            ]
        ]
    },
    {
        "id": "soc_delay_first_only",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "SOC (delay first message only)",
        "func": "let initialized = context.get('initialized');\n\n// Wenn noch nicht initialisiert → ersten Wert verzögern\nif (!initialized) {\n    context.set('initialized', true);\n    \n    let firstMsg = RED.util.cloneMessage(msg);\n    \n    setTimeout(function() {\n        node.send(firstMsg);\n    }, 3000);\n    \n    return null;\n}\n\n// Danach alles direkt durchlassen\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 590,
        "y": 200,
        "wires": [
            [
                "74e667e16030d291"
            ]
        ]
    },
    {
        "id": "current_delay_first_only",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "Current (delay first message only)",
        "func": "let initialized = context.get('initialized');\n\n// Wenn noch nicht initialisiert → ersten Wert verzögern\nif (!initialized) {\n    context.set('initialized', true);\n    let firstMsg = RED.util.cloneMessage(msg);\n\n    setTimeout(function() {\n        node.send(firstMsg);\n    }, 3000); // 3 Sekunden Verzögerung\n\n    return null;\n}\n\n// Danach Original-Current-Code\nlet current = context.get(\"current\") || {};\n\n// Neuen Shunt-Wert speichern\ncurrent[msg.service] = msg.payload;\ncontext.set(\"current\", current);\n\n// Summe aller Shunt-Werte berechnen\nlet sum = 0;\nlet hasValue = false;\nfor (let key in current) {\n    let value = current[key];\n    if (value != null && typeof value === \"number\") {\n        sum += value;\n        hasValue = true;\n    }\n}\n\nif (hasValue) {\n    return { payload: sum };\n}\n\nreturn null;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 600,
        "y": 320,
        "wires": [
            [
                "953f20d917b4ec6d"
            ]
        ]
    },
    {
        "id": "voltage_delay_first_only",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "Voltage (delay first message only)",
        "func": "let initialized = context.get('initialized');\n\n// Wenn noch nicht initialisiert → ersten Wert verzögern\nif (!initialized) {\n    context.set('initialized', true);\n    let firstMsg = RED.util.cloneMessage(msg);\n\n    setTimeout(function() {\n        node.send(firstMsg);\n    }, 3000); // 3 Sekunden Verzögerung\n\n    return null;\n}\n\n// Danach Original-Voltage-Code\nlet volt = context.get(\"volt\") || {};\n\n// Wert speichern (pro Service)\nvolt[msg.service] = msg.payload;\ncontext.set(\"volt\", volt);\n\n// Alle vorhandenen Werte sammeln\nlet values = Object.values(volt).filter(v => v !== null && v !== undefined);\n\n// Wenn mindestens 1 Wert vorhanden → Mittelwert\nif (values.length > 0) {\n    let avg = values.reduce((a,b)=>a+b,0) / values.length;\n    return { payload: avg };\n}\n\nreturn null;",
        "outputs": 1,
        "timeout": "",
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 600,
        "y": 460,
        "wires": [
            [
                "db603f1b55d34603"
            ]
        ]
    },
    {
        "id": "maxchargecurrent_delayed",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "MaxChargeCurrent Delay",
        "func": "// Prüfen, ob erster Wert schon gesendet wurde\nlet initialized = context.get('initialized_MaxChargeCurrent') || false;\n\nif (!initialized) {\n    context.set('initialized_MaxChargeCurrent', true);\n    let firstMsg = RED.util.cloneMessage(msg);\n    setTimeout(() => { node.send(firstMsg); }, 3000);\n    return null;\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 650,
        "y": 840,
        "wires": [
            [
                "e12958100cc4e2aa"
            ]
        ]
    },
    {
        "id": "maxdischargecurrent_delayed",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "MaxDischargeCurrent Delay",
        "func": "// Prüfen, ob erster Wert schon gesendet wurde\nlet initialized = context.get('initialized_MaxDischargeCurrent') || false;\n\nif (!initialized) {\n    context.set('initialized_MaxDischargeCurrent', true);\n    let firstMsg = RED.util.cloneMessage(msg);\n    setTimeout(() => { node.send(firstMsg); }, 3000);\n    return null;\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 660,
        "y": 900,
        "wires": [
            [
                "b575872270083217"
            ]
        ]
    },
    {
        "id": "maxchargevoltage_delayed",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "MaxChargeVoltage Delay",
        "func": "// Prüfen, ob erster Wert schon gesendet wurde\nlet initialized = context.get('initialized_MaxChargeVoltage') || false;\n\nif (!initialized) {\n    context.set('initialized_MaxChargeVoltage', true);\n    let firstMsg = RED.util.cloneMessage(msg);\n    setTimeout(() => { node.send(firstMsg); }, 3000);\n    return null;\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 650,
        "y": 960,
        "wires": [
            [
                "71ee0fe4c9a413c3"
            ]
        ]
    },
    {
        "id": "temperature_delayed",
        "type": "function",
        "z": "e4f5e8533ac57fae",
        "name": "Temperature Delay",
        "func": "// Prüfen, ob erster Wert schon gesendet wurde\nlet initialized = context.get('initialized_Temperature') || false;\n\nif (!initialized) {\n    context.set('initialized_Temperature', true);\n    let firstMsg = RED.util.cloneMessage(msg);\n    setTimeout(() => { node.send(firstMsg); }, 3000);\n    return null;\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 650,
        "y": 780,
        "wires": [
            [
                "48cd38e59ea73c8a"
            ]
        ]
    }
]

Comin now more into details. What´s confusing me is the device ID from the virtual battery. This was automatically adressed to e.g. ID 101
This confuses me because i thought the device ID is unique. But I have also a shelly device (pv-Inverter) in the system with device ID 101.

Now it happened during modifications that after a deploy the victron outputs (all) showed a connection error. Reason for this was a change of the virtual device ( ID). The ID was now newly assigned to 100, which is also already in my system by the way. After adjusting device id in the victron outputs everthing is working fine again. But this happened already twice. I´m afraid this will also happen during a reboot or whatever and then the full virt.battery will bring the full system out of service.

Currently I´m not very impressed because during execution over several days it comes to often to unexplainable laggy situations.
So I´m still monitoring the virt. battery and using it for control etc.

Sometimes the SOC of the virtual Battery is eg much to low and only updated afters hours.
Also the detection of Online modules (BMS) was not stable and I assume because of no online modules detected it reduced the DVCC charge power to Zero. And this was not once it was stuck for hours.

Puh, not sure if this should be used for real life control?

Do you have recommendation to use sth. like this: GitHub - pulquero/BatteryAggregator · GitHub

In addition, I´m still Using OS v3.6 will an update to v3.7 help? Cannot see improvements mentioned regarding Node Red.

After some more testing, I unfortunately have to confirm my initial concerns – maybe this helps others who are considering using such a setup in a productive environment.

In the meantime, I updated to OS 3.70. Subjectively, the system initially felt smoother and more stable. However, this morning it became clear that the underlying issues are still present.

The system suddenly turned sluggish again, and I could already see several input nodes (5 s polling) running into errors or “exceeded” states. Shortly after that, things became critical:

During the charging phase, the battery was already being charged above CVL, even though the system should have switched to absorption phase long before. The corresponding setpoints (e.g. float voltage) were correctly available externally, but were apparently not processed in time due to the laggy system behavior.

What I find particularly concerning:
It’s not just that state transitions are delayed — even known limits like CVL, which were previously respected, are exceeded under these conditions. For me, this is no longer just a performance issue, but a safety-relevant behavior.

This strongly reinforces my conclusion:
A Node-RED–based virtual battery system, in this form, is not suitable for actively controlling or interfering with the charging logic.

The BMS is still present as a last line of defense, but that should not be used as justification to accept such risks beforehand. On the contrary, situations like this should already be reliably prevented at system level.

I will continue using the virtual system for testing and monitoring, but no longer for active control.

Maybe this helps others to better assess how much trust to place in such setups in real-world operation.