Hi everyone,
I’m looking for some advice regarding Node-RED performance on my Victron MultiPlus-II 5000 GX.
I’m running Node-RED directly on the GX device (yes, I know it’s officially more of a community solution). My setup is very small and simple:
- 3 flows polling three Shelly 1PM Mini devices
[
{
"id": "80d79748e7015c78",
"type": "tab",
"label": "Shelly BKW Garage",
"disabled": false,
"info": "",
"env": []
},
{
"id": "988f909b2b264292",
"type": "victron-virtual",
"z": "80d79748e7015c78",
"name": "Shelly 1PM Mini Garage",
"device": "pvinverter",
"default_values": false,
"battery_capacity": 25,
"include_battery_temperature": false,
"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": "3",
"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": 190,
"y": 120,
"wires": []
},
{
"id": "c98e64e99eda263b",
"type": "victron-output-custom",
"z": "80d79748e7015c78",
"service": "com.victronenergy.pvinverter/100",
"path": "/Ac/Power",
"serviceObj": {
"service": "com.victronenergy.pvinverter/100",
"name": "Shelly 1PM Mini Garage (100)"
},
"pathObj": {
"path": "/Ac/Power",
"name": "/Ac/Power",
"type": "object",
"value": null
},
"name": "",
"onlyChanges": false,
"x": 1040,
"y": 260,
"wires": []
},
{
"id": "031241b23e58dee8",
"type": "inject",
"z": "80d79748e7015c78",
"name": "2s",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "2",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "num",
"x": 130,
"y": 280,
"wires": [
[
"b004a4eb164c3191"
]
]
},
{
"id": "b004a4eb164c3191",
"type": "shelly-gen2",
"z": "80d79748e7015c78",
"hostname": "192.168.7.154",
"description": "Shelly Garage BKW",
"mode": "none",
"verbose": false,
"server": "",
"outputmode": "event",
"uploadretryinterval": 5000,
"pollinginterval": 5000,
"pollstatus": false,
"getstatusoncommand": true,
"devicetype": "S3SW-001P8EU",
"devicetypemustmatchexactly": true,
"captureblutooth": false,
"outputs": 1,
"x": 320,
"y": 280,
"wires": [
[
"93c6b5c3b67fef60",
"efc547032f6e8ff2",
"ff02152d270a5ec9",
"687cb0a1c859739a"
]
]
},
{
"id": "93c6b5c3b67fef60",
"type": "change",
"z": "80d79748e7015c78",
"name": "Power",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.switch0.apower",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 570,
"y": 260,
"wires": [
[
"cdf8f4da62f264e2"
]
]
},
{
"id": "a2bda360f9d446ab",
"type": "victron-output-custom",
"z": "80d79748e7015c78",
"service": "com.victronenergy.pvinverter/100",
"path": "/Ac/L2/Power",
"serviceObj": {
"service": "com.victronenergy.pvinverter/100",
"name": "Shelly 1PM Mini Garage (100)"
},
"pathObj": {
"path": "/Ac/L2/Power",
"name": "/Ac/L2/Power",
"type": "number",
"value": 0
},
"name": "",
"onlyChanges": false,
"x": 1050,
"y": 320,
"wires": []
},
{
"id": "9dbe5908301e23a4",
"type": "victron-output-custom",
"z": "80d79748e7015c78",
"service": "com.victronenergy.pvinverter/100",
"path": "/Ac/L2/Voltage",
"serviceObj": {
"service": "com.victronenergy.pvinverter/100",
"name": "Shelly 1PM Mini Garage (100)"
},
"pathObj": {
"path": "/Ac/L2/Voltage",
"name": "/Ac/L2/Voltage",
"type": "number",
"value": 0
},
"name": "",
"onlyChanges": false,
"x": 1060,
"y": 140,
"wires": []
},
{
"id": "efc547032f6e8ff2",
"type": "change",
"z": "80d79748e7015c78",
"name": "Voltage",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.switch0.voltage",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 580,
"y": 140,
"wires": [
[
"9dbe5908301e23a4"
]
]
},
{
"id": "ff02152d270a5ec9",
"type": "change",
"z": "80d79748e7015c78",
"name": "Current",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.switch0.current",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 580,
"y": 200,
"wires": [
[
"2fead3ef3f1b3d37"
]
]
},
{
"id": "2fead3ef3f1b3d37",
"type": "victron-output-custom",
"z": "80d79748e7015c78",
"service": "com.victronenergy.pvinverter/100",
"path": "/Ac/L2/Current",
"serviceObj": {
"service": "com.victronenergy.pvinverter/100",
"name": "Shelly 1PM Mini Garage (100)"
},
"pathObj": {
"path": "/Ac/L2/Current",
"name": "/Ac/L2/Current",
"type": "number",
"value": 0
},
"name": "",
"onlyChanges": false,
"x": 1060,
"y": 200,
"wires": []
},
{
"id": "ad0a80fbc7423c68",
"type": "comment",
"z": "80d79748e7015c78",
"name": "Leistungsmessung BKW Garage",
"info": "Messung des BKW zur Anzeige in Victron",
"x": 210,
"y": 60,
"wires": []
},
{
"id": "687cb0a1c859739a",
"type": "change",
"z": "80d79748e7015c78",
"name": "Energy",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.switch0.aenergy.total",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 580,
"y": 380,
"wires": [
[
"4b294629fc3ebb1c"
]
]
},
{
"id": "895f8206a488df80",
"type": "victron-output-custom",
"z": "80d79748e7015c78",
"service": "com.victronenergy.pvinverter/100",
"path": "/Ac/Energy/Forward",
"serviceObj": {
"service": "com.victronenergy.pvinverter/100",
"name": "Shelly 1PM Mini Garage (100)"
},
"pathObj": {
"path": "/Ac/Energy/Forward",
"name": "/Ac/Energy/Forward",
"type": "object",
"value": null
},
"name": "",
"onlyChanges": false,
"x": 1070,
"y": 380,
"wires": []
},
{
"id": "e2933c7016fc5476",
"type": "victron-output-custom",
"z": "80d79748e7015c78",
"service": "com.victronenergy.pvinverter/100",
"path": "/Ac/L2/Energy/Forward",
"serviceObj": {
"service": "com.victronenergy.pvinverter/100",
"name": "Shelly 1PM Mini Garage (100)"
},
"pathObj": {
"path": "/Ac/L2/Energy/Forward",
"name": "/Ac/L2/Energy/Forward",
"type": "number",
"value": 0
},
"name": "",
"onlyChanges": false,
"x": 1080,
"y": 440,
"wires": []
},
{
"id": "4b294629fc3ebb1c",
"type": "function",
"z": "80d79748e7015c78",
"name": "Wh to kWh",
"func": "msg.payload = msg.payload / 1000;\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 750,
"y": 380,
"wires": [
[
"895f8206a488df80",
"e2933c7016fc5476"
]
]
},
{
"id": "cdf8f4da62f264e2",
"type": "function",
"z": "80d79748e7015c78",
"name": "Positive Power",
"func": "msg.payload = msg.payload * (-1);\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 740,
"y": 280,
"wires": [
[
"c98e64e99eda263b",
"a2bda360f9d446ab"
]
]
}
]
- 1 additional flow that performs a small check and applies a charge voltage limit
[
{
"id": "flow_volladung",
"type": "tab",
"label": "Volladung Flow (Victron) mit History",
"disabled": false,
"info": ""
},
{
"id": "victron_input_cvl",
"type": "victron-input-battery",
"z": "flow_volladung",
"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": "CVL vom JK-BMS",
"onlyChanges": false,
"x": 110,
"y": 180,
"wires": [
[
"function_volladung"
]
]
},
{
"id": "inject_manual",
"type": "inject",
"z": "flow_volladung",
"name": "Manuelle Volladung",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"payload": "manual",
"payloadType": "str",
"x": 290,
"y": 280,
"wires": [
[
"function_volladung"
]
]
},
{
"id": "inject_bulk",
"type": "inject",
"z": "flow_volladung",
"name": "Bulk / Schonladung",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"payload": "bulk",
"payloadType": "str",
"x": 290,
"y": 340,
"wires": [
[
"function_volladung"
]
]
},
{
"id": "inject_auto",
"type": "inject",
"z": "flow_volladung",
"name": "Automatikbetrieb",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": false,
"payload": "auto",
"payloadType": "str",
"x": 280,
"y": 400,
"wires": [
[
"function_volladung"
]
]
},
{
"id": "inject_cvl_56",
"type": "inject",
"z": "flow_volladung",
"name": "Simulierter CVL 56V",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"payload": "56",
"payloadType": "num",
"x": 310,
"y": 60,
"wires": [
[
"function_volladung"
]
]
},
{
"id": "inject_cvl_55",
"type": "inject",
"z": "flow_volladung",
"name": "Simulierter CVL 55V",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"payload": "55",
"payloadType": "num",
"x": 310,
"y": 120,
"wires": [
[
"function_volladung"
]
]
},
{
"id": "load_history_inject",
"type": "inject",
"z": "flow_volladung",
"name": "Load History Start",
"props": [
{
"p": "payload"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.5,
"payload": "",
"payloadType": "str",
"x": 210,
"y": 520,
"wires": [
[
"read_volladung_history"
]
]
},
{
"id": "read_volladung_history",
"type": "file in",
"z": "flow_volladung",
"name": "Read Volladung History",
"filename": "/data/home/nodered/.node-red/history/volladung_history.json",
"format": "utf8",
"chunk": false,
"sendError": true,
"encoding": "none",
"x": 430,
"y": 520,
"wires": [
[
"load_history_context"
]
]
},
{
"id": "load_history_context",
"type": "function",
"z": "flow_volladung",
"name": "Load History into Context",
"func": "try {\n var history = JSON.parse(msg.payload);\n flow.set('volladung_history', history);\n node.status({fill:'green', shape:'dot', text:'History loaded (' + history.length + ' entries)'});\n} catch (e) {\n node.status({fill:'red', shape:'ring', text:'History file empty or invalid'});\n flow.set('volladung_history', []);\n}\nreturn null;\n",
"outputs": 0,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 670,
"y": 520,
"wires": []
},
{
"id": "write_volladung_history",
"type": "file",
"z": "flow_volladung",
"name": "Write Volladung History",
"filename": "/data/home/nodered/.node-red/history/volladung_history.json",
"filenameType": "str",
"appendNewline": false,
"createDir": true,
"overwriteFile": true,
"encoding": "utf8",
"x": 1010,
"y": 420,
"wires": [
[]
]
},
{
"id": "rbe_node",
"type": "rbe",
"z": "flow_volladung",
"name": "RBE Filter",
"func": "rbe",
"gap": "",
"start": "",
"inout": "out",
"property": "payload",
"x": 930,
"y": 260,
"wires": [
[
"victron_output_dvcc"
]
]
},
{
"id": "victron_output_dvcc",
"type": "victron-output-custom",
"z": "flow_volladung",
"service": "com.victronenergy.settings",
"path": "/Settings/SystemSetup/MaxChargeVoltage",
"serviceObj": {
"service": "com.victronenergy.settings",
"name": "com.victronenergy.settings"
},
"pathObj": {
"path": "/Settings/SystemSetup/MaxChargeVoltage",
"name": "/Settings/SystemSetup/MaxChargeVoltage",
"type": "number",
"value": 0
},
"name": "DVCC MaxChargeVoltage",
"onlyChanges": false,
"x": 1150,
"y": 260,
"wires": []
},
{
"id": "comment_function",
"type": "comment",
"z": "flow_volladung",
"name": "Funktion",
"info": "Volladung Logic Node (Victron / DVCC)\n\nSteuert die DVCC-Ladespannung eines Victron-Batteriesystems.\n\nBetriebsmodi:\nauto: max. 1 Volladung pro Kalenderwoche\nmanual: erzwingt sofort Volladung (DVCC=0V)\nbulk: Dauerhafte Schonladung (Float 55.2V)\n\nFunktionslogik:\n- CVL vom BMS einlesen\n- Spannungsabfall DELTA_V detektieren -> Volladung\n- History File aktualisieren\n- DVCC entsprechend setzen\n\nKontext:\n- letzte Volladung (KW + Datum)\n- letzter Max-CVL\n- Modus\n\nStatus zeigt Modus, letzte Volladung, aktuell gesetzte DVCC-Spannung\n\nParameter: DELTA_V, FLOAT_VOLTAGE, INIT_KW, INIT_DATE",
"x": 100,
"y": 40,
"wires": []
},
{
"id": "function_volladung",
"type": "function",
"z": "flow_volladung",
"name": "Volladung Logic (Victron)",
"func": "// =====================\n// Volladung Logic (Victron)\n// Output 1: DVCC Spannung\n// Output 2: History schreiben (nur bei Volladung)\n// =====================\n\nvar DELTA_V = 0.5;\nvar FLOAT_VOLTAGE = 55.2;\nvar INIT_KW = 1;\nvar INIT_DATE = \"2026-01-01\";\n\nfunction getKW(date) {\n var d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));\n var dayNum = d.getUTCDay() || 7;\n d.setUTCDate(d.getUTCDate() + 4 - dayNum);\n var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));\n return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);\n}\n\nvar now = new Date();\nvar currentKW = getKW(now);\nvar currentDateStr = now.toISOString().slice(0,10);\n\n// ----- History laden -----\nvar history = flow.get('volladung_history');\nif (!history) history = [];\n\n// Letzten Eintrag bestimmen\nvar lastFullKW = history.length > 0 ? history[history.length-1].kw : INIT_KW;\nvar lastFullDate = history.length > 0 ? history[history.length-1].date : INIT_DATE;\n\nvar lastMaxCVL = context.get('lastMaxCVL');\nvar modus = context.get('modus');\nif (!modus) modus = \"auto\";\n\n// ----- Modus Inject -----\nif (typeof msg.payload === \"string\") {\n if ([\"manual\",\"bulk\",\"auto\"].indexOf(msg.payload) !== -1) {\n modus = msg.payload;\n context.set(\"modus\", modus);\n\n node.status({\n fill:\"blue\",\n shape:\"dot\",\n text:\"Modus: \"+modus+\n \" | LetzteKW:\"+lastFullKW+\n \" (\"+lastFullDate+\")\"+\n \" | AktKW:\"+currentKW\n });\n }\n return null;\n}\n\n// ----- CVL Input -----\nif (typeof msg.payload !== \"number\") return null;\nvar currentCVL = msg.payload;\n\nif (lastMaxCVL === undefined) lastMaxCVL = currentCVL;\n\nvar dvccVoltage;\nvar fullChargeDetected = false;\n\n// ----- Logik -----\nif (modus === \"manual\") {\n dvccVoltage = 0;\n}\nelse if (modus === \"bulk\") {\n dvccVoltage = FLOAT_VOLTAGE;\n}\nelse {\n\n // Volladung erkennen (Spannungsabfall)\n if ((lastMaxCVL - currentCVL) >= DELTA_V) {\n\n if (lastFullKW !== currentKW) {\n\n fullChargeDetected = true;\n\n var entry = {\n kw: currentKW,\n date: currentDateStr\n };\n\n history.push(entry);\n flow.set(\"volladung_history\", history);\n\n // WICHTIG: sofort lokale Variablen aktualisieren\n lastFullKW = currentKW;\n lastFullDate = currentDateStr;\n }\n\n lastMaxCVL = currentCVL;\n }\n\n if (currentCVL > lastMaxCVL) {\n lastMaxCVL = currentCVL;\n }\n\n dvccVoltage = (lastFullKW !== currentKW) ? 0 : FLOAT_VOLTAGE;\n}\n\n// ----- Context speichern -----\ncontext.set(\"lastMaxCVL\", lastMaxCVL);\ncontext.set(\"modus\", modus);\n\n// ----- Statusanzeige (eindeutig) -----\nnode.status({\n fill: fullChargeDetected ? \"green\" : \"blue\",\n shape: \"dot\",\n text:\n \"Modus:\"+modus+\n \" | LetzteKW:\"+lastFullKW+\n \" (\"+lastFullDate+\")\"+\n \" | AktKW:\"+currentKW+\n \" | DVCC:\"+dvccVoltage+\"V\"\n});\n\n// ----- Output 1: DVCC -----\nvar msgDVCC = { payload: dvccVoltage };\n\n// ----- Output 2: History nur bei echter Volladung -----\nvar msgHistory = null;\n\nif (fullChargeDetected) {\n msgHistory = {\n payload: JSON.stringify(history, null, 2)\n };\n}\n\nreturn [msgDVCC, msgHistory];\n",
"outputs": 2,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 570,
"y": 260,
"wires": [
[
"rbe_node"
],
[
"write_volladung_history"
]
]
}
]
Functionally, everything works perfectly. The flows continue to run reliably and the charge limitation works as expected.
However, after about 2–3 days of uptime, the Node-RED web interface becomes extremely slow.
-
The editor loads very slowly
-
Deployments take much longer
-
Navigating between tabs is very sluggish
Important: The flows themselves keep running correctly. It’s mainly the UI that becomes almost unusable.
After restarting Node-RED, everything is fast and responsive again — but only for a couple of days.


