With some help I’ve been able to get the SunPower SunVault with the Schneider XW Pro 6848 hybrid inverter inside to use excess grid tie inverter power to charge batteries instead of export to the grid. One might think this is something the inverter could do out of the box but after some talking with Schneider I don’t think it was ever programmed in! Here is a diagram of what my setup looks like:
In my scenario I wanted to make sure I wasn’t exporting any power so the first step was choosing a grid tie inverter with a zero export option. This Goodwe7600a-es inverter has a pair of CT clamps included and we turned on zero consumption and set the import wattage to 150. So while the sun shines it aims for 150W import. The Node red script is going to kick in and start charging the batteries if it sees the import move below 200 watts and aim to keep the import power at 200-250 watts. If import goes to 300 watts (no more solar coming in) then the Node Red script will switch the inverter mode to grid support and start exporting just enough power to keep the import at 300W
GRID POWER IMPORT TARGETS - UNIFIED VIEW
═══════════════════════════════════════════
Grid Power Import (Watts)
0W 150W 300W 450W 600W
│ │ │ │ │
├────────┼────────┼────────┼────────┤
│ 🟢 │ 🔵──🔵 🟠│ │
└────────┴────────┴────────┴────────┘
Legend:
🟢 GoodWe Grid Tie Inverter → 150W Target
🔵 Node Red Script → 200-250W Range
🟠 XW Pro Inverter → 300W Target
SYSTEM COMPARISON:
┌─────────────┬──────────────┬─────────────────────────────────┐
│ System │ Target │ Purpose │
├─────────────┼──────────────┼─────────────────────────────────┤
│ GoodWe │ 150W │ Minimal import, max self-use │
│ Node Red │ 200-250W │ Battery charging + controlled │
│ XW Pro │ 300W │ If no solar coming in │
└─────────────┴──────────────┴─────────────────────────────────┘
The key to making this work is loading the application Node Red on a small computer like a Raspberry Pi or Orange Pi so that it can read the current export/import power from the Schneider Insight Gateway and make adjustments to the Schneider inverter dynamically to turn on/off charging and adjust the charge rate. I’ll add the code below I’m using to do this.
Node-RED Dynamic Grid Charging Flow v22
[
{
"id": "43214d9410f9188b",
"type": "tab",
"label": "Dynamic Grid Charging v25 (Probe & Ramp Logic)",
"disabled": false,
"info": "This flow dynamically adjusts the XW Pro's EPC charge limit and Recharge SOC based on grid power usage and a timer.nnLogic:n1. Reads Grid Usage, Battery Power, EPC Limit, Recharge SOC, and Battery SOC in parallel.n2. Defines a target grid import with a dead band.n3. If surplus grid power is detected and the system is idle, it enters a 'PROBING' state, setting charge to 100W.n4. It monitors battery power (register 521). Once charging is confirmed, it switches to 'RAMPING' state.n5. In 'RAMPING' state, it adjusts charge power up or down to maintain the target grid import.n6. If grid usage is high, it ramps down charge power.n7. When battery SOC reaches 99%, limits charge power to 300W.n8. Manages Recharge SOC and Charger State with a 1-minute timer when charging stops.nn**v25 Update:**n- Removed surplus counter for faster reaction time.n- Added a 'PROBING' state to handle inverter transition delay.n- Sets initial charge to 100W.n- Changed Battery Power read to port 503, address 521 (uint32)."
},
{
"id": "cc40d59957122e31",
"type": "inject",
"z": "43214d9410f9188b",
"name": "Trigger every 2s",
"props": [
{
"p": "payload"
}
],
"repeat": "2",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 110,
"y": 280,
"wires": [
[
"3bb8f79df691b828",
"c719860029caadd7",
"4face4c7c0f5fe8e",
"3e7957edad1e0b88",
"538c21b3dd7c46a9",
"945c3779b9caaecf"
]
]
},
{
"id": "3bb8f79df691b828",
"type": "modbus-read",
"z": "43214d9410f9188b",
"name": "Read Grid Usage",
"topic": "grid",
"showStatusActivities": false,
"logIOActivities": false,
"showErrors": false,
"showWarnings": true,
"unitid": "1",
"dataType": "InputRegister",
"adr": "82",
"quantity": "2",
"rate": "2",
"rateUnit": "s",
"delayOnStart": false,
"startDelayTime": "",
"server": "cdabbb805236446d",
"useIOFile": false,
"ioFile": "",
"useIOForPayload": false,
"emptyMsgOnFail": false,
"x": 320,
"y": 150,
"wires": [
[
"fd8a3767c1a4d496"
],
[]
]
},
{
"id": "c719860029caadd7",
"type": "modbus-read",
"z": "43214d9410f9188b",
"name": "Read Current EPC Limit",
"topic": "chargeLimit",
"showStatusActivities": false,
"logIOActivities": false,
"showErrors": false,
"showWarnings": true,
"unitid": "10",
"dataType": "InputRegister",
"adr": "40210",
"quantity": "1",
"rate": "3",
"rateUnit": "s",
"delayOnStart": false,
"startDelayTime": "",
"server": "66293601c9428680",
"useIOFile": false,
"ioFile": "",
"useIOForPayload": false,
"emptyMsgOnFail": false,
"x": 340,
"y": 290,
"wires": [
[
"80a6c07b244de845"
],
[]
]
},
{
"id": "3e7957edad1e0b88",
"type": "modbus-read",
"z": "43214d9410f9188b",
"name": "Read Battery SOC",
"topic": "batterySOC",
"showStatusActivities": false,
"logIOActivities": false,
"showErrors": false,
"showWarnings": true,
"unitid": "1",
"dataType": "InputRegister",
"adr": "968",
"quantity": "2",
"rate": "3",
"rateUnit": "s",
"delayOnStart": false,
"startDelayTime": "",
"server": "cdabbb805236446d",
"useIOFile": false,
"ioFile": "",
"useIOForPayload": false,
"emptyMsgOnFail": false,
"x": 330,
"y": 430,
"wires": [
[
"bea3941f3b3ee47a"
],
[]
]
},
{
"id": "bea3941f3b3ee47a",
"type": "buffer-parser",
"z": "43214d9410f9188b",
"name": "32bit to decimal",
"data": "payload",
"dataType": "msg",
"specification": "spec",
"specificationType": "ui",
"items": [
{
"type": "uint32be",
"name": "payload",
"offset": 0,
"length": 1,
"offsetbit": 0,
"scale": "1",
"mask": ""
}
],
"swap1": "",
"swap2": "",
"swap3": "",
"swap1Type": "swap",
"swap2Type": "swap",
"swap3Type": "swap",
"msgProperty": "payload",
"msgPropertyType": "str",
"resultType": "value",
"resultTypeType": "return",
"multipleResult": false,
"fanOutMultipleResult": false,
"setTopic": true,
"outputs": 1,
"x": 540,
"y": 430,
"wires": [
[
"b60c91c1089bb46f",
"0217e2bf9d8661a6"
]
]
},
{
"id": "8fc3b76505610a19",
"type": "function",
"z": "43214d9410f9188b",
"name": "Probe & Ramp Logic",
"func": "// --- Get all data from the single payload object ---nlet gridUsage = parseInt(msg.payload.grid);nlet gridExport = parseInt(msg.payload.gridExport);nlet currentChargePower = parseInt(msg.payload.chargeLimit);nlet currentRechargeSOC = parseInt(msg.payload.rechargeSOC);nlet batterySOC = parseInt(msg.payload.batterySOC);nlet batteryPower = parseInt(msg.payload.batteryPower);nnif (n isNaN(gridUsage) ||n isNaN(gridExport) ||n isNaN(currentChargePower) ||n isNaN(currentRechargeSOC) ||n isNaN(batterySOC) ||n isNaN(batteryPower)n) {n node.warn("One or more Modbus reads failed. Inputs are NaN. Stopping.");n return null;n}nn// --- Configuration ---nconst TARGET_GRID_IMPORT = 0;nconst DEAD_BAND_TOLERANCE = 50;nconst DAMPING_FACTOR = 0.6;nconst SURPLUS_EXPORT_THRESHOLD = 50;nconst HIGH_IMPORT_THRESHOLD = 100;nconst PERIOD_THRESHOLD = 3;nconst LOW_BATTERY_TARGET = 10;nconst LOW_BATTERY_CHARGE_POWER = 100;nconst SOC_99_CHARGE_LIMIT = 300;nn// --- State Management ---nlet chargeState = flow.get("chargeState") || "GRID_SELL";nlet exportCounter = flow.get("exportCounter") || 0;nlet importCounter = flow.get("importCounter") || 0;nlet lastSentPower = flow.get("lastSentPower") || currentChargePower;nnnode.warn(n `--- START --- State: ${chargeState}, Grid In=${gridUsage}, Grid Out=${gridExport}, ChargePwr=${currentChargePower}, LastSentPwr=${lastSentPower}, BattSOC=${batterySOC}%`n);nnlet desiredPower = lastSentPower;nn// =================================================================n// --- Main State Machine Logic ---n// =================================================================nnswitch (chargeState) {n case "GRID_SELL":n desiredPower = 0;n importCounter = 0;n if (gridExport > SURPLUS_EXPORT_THRESHOLD) {n exportCounter++;n } else {n exportCounter = 0;n }n if (exportCounter >= PERIOD_THRESHOLD) {n node.warn(n `Sustained export detected. Moving to RAMPING.`n );n let initialGridPower = gridUsage - gridExport;n let error = initialGridPower - TARGET_GRID_IMPORT;n let correction = error * DAMPING_FACTOR;n desiredPower = -correction;n chargeState = "RAMPING";n exportCounter = 0;n }n break;nn case "RAMPING":n exportCounter = 0;n if (currentChargePower <= 0 && gridUsage > HIGH_IMPORT_THRESHOLD) {n importCounter++;n } else {n importCounter = 0;n }n if (importCounter >= PERIOD_THRESHOLD) {n node.warn(n `Sustained high import detected. Switching back to GRID_SELL.`n );n desiredPower = 0;n chargeState = "GRID_SELL";n importCounter = 0;n break;n }n let currentGridPower = gridUsage - gridExport;n let error = currentGridPower - TARGET_GRID_IMPORT;n if (Math.abs(error) > DEAD_BAND_TOLERANCE) {n let correction = error * DAMPING_FACTOR;n desiredPower = lastSentPower - correction;n } else {n desiredPower = lastSentPower;n }n break;nn // <<< KEY CHANGE: CATCH-ALL FOR UNKNOWN STATES >>>n default:n node.warn(n `Unknown or legacy state "${chargeState}" detected. Resetting to GRID_SELL.`n );n chargeState = "GRID_SELL";n desiredPower = 0;n break;n}nnflow.set("chargeState", chargeState);nflow.set("exportCounter", exportCounter);nflow.set("importCounter", importCounter);nn// ... (The rest of the script is the same) ...nn// =================================================================n// --- Overrides & Safety Checks (applied after main logic) ---n// =================================================================nnif (batterySOC >= 99 && desiredPower > SOC_99_CHARGE_LIMIT) {n desiredPower = SOC_99_CHARGE_LIMIT;n}nnif (batterySOC < LOW_BATTERY_TARGET) {n desiredPower = Math.max(desiredPower, LOW_BATTERY_CHARGE_POWER);n}nnconst MAX_CHARGE_POWER = 6800;nconst MIN_CHARGE_POWER = 0;nif (desiredPower > MAX_CHARGE_POWER) desiredPower = MAX_CHARGE_POWER;nif (desiredPower < MIN_CHARGE_POWER) desiredPower = MIN_CHARGE_POWER;nnlet finalPower = Math.round(desiredPower);nnif (finalPower <= 0 && chargeState === "RAMPING") {n chargeState = "GRID_SELL";n flow.set("chargeState", "GRID_SELL");n}nnflow.set("lastSentPower", finalPower);nn// =================================================================n// --- Prepare Output Messages ---n// =================================================================nnlet chargeStoppedTimestamp = flow.get("chargeStoppedTimestamp") || null;nconst ONE_MINUTE_MS = 60 * 1000;nlet desiredSOC = currentRechargeSOC;nlet chargerStatePayload = null;nnif (finalPower > 0) {n desiredSOC = 9900;n chargerStatePayload = 1;n if (chargeStoppedTimestamp !== null) {n flow.set("chargeStoppedTimestamp", null);n }n} else {n flow.set("lastSentPower", 0);n if (chargeStoppedTimestamp === null) {n flow.set("chargeStoppedTimestamp", Date.now());n } else {n let elapsed = Date.now() - chargeStoppedTimestamp;n if (elapsed > ONE_MINUTE_MS) {n desiredSOC = 600;n chargerStatePayload = 0;n }n }n}nnlet powerNeedsChange = Math.abs(finalPower - currentChargePower) > 10;nlet socNeedsChange = desiredSOC !== currentRechargeSOC;nlet chargerStateNeedsChange = chargerStatePayload !== null;nnif (!powerNeedsChange && !socNeedsChange && !chargerStateNeedsChange) {n node.warn("System state is already correct. No action needed.");n return [null, null, null];n}nnlet powerMsg = powerNeedsChange ? { payload: finalPower } : null;nlet socMsg = socNeedsChange ? { payload: desiredSOC } : null;nlet chargerStateMsg = chargerStateNeedsChangen ? { payload: chargerStatePayload }n : null;nnif (powerNeedsChange)n node.warn(n `Charge Power needs change. Current: ${currentChargePower}, Desired: ${finalPower}`n );nif (socNeedsChange)n node.warn(n `Recharge SOC needs change. Current: ${currentRechargeSOC}, Desired: ${desiredSOC}`n );nif (chargerStateNeedsChange)n node.warn(n `Charger State needs change. Desired: ${chargerStatePayload === 1 ? "ON" : "OFF"n }`n );nnreturn [powerMsg, socMsg, chargerStateMsg];",
"outputs": 3,
"timeout": "",
"noerr": 0,
"initialize": "// Set the initial state to IDLE on deploy/restartnflow.set("chargeState", "IDLE");nflow.set("chargeStoppedTimestamp", null);nnode.warn("Flow initialized. Charge state set to IDLE.");",
"finalize": "",
"libs": [],
"x": 1050,
"y": 280,
"wires": [
[
"45026b9e30844ca7",
"bb5e409e8acf37a7"
],
[
"5f0880bc7ad09082",
"5baad6d66274c89b"
],
[
"e9fc1680ed2c6d20",
"b0e551fbe9ba3cf6"
]
]
},
{
"id": "45026b9e30844ca7",
"type": "modbus-write",
"z": "43214d9410f9188b",
"name": "Set New EPC Charge Limit",
"showStatusActivities": false,
"showErrors": false,
"showWarnings": true,
"unitid": "10",
"dataType": "HoldingRegister",
"adr": "40210",
"quantity": "1",
"server": "66293601c9428680",
"emptyMsgOnFail": false,
"keepMsgProperties": false,
"delayOnStart": false,
"startDelayTime": "",
"x": 1500,
"y": 240,
"wires": [
[],
[]
]
},
{
"id": "fd8a3767c1a4d496",
"type": "buffer-parser",
"z": "43214d9410f9188b",
"name": "32bit to decimal",
"data": "payload",
"dataType": "msg",
"specification": "spec",
"specificationType": "ui",
"items": [
{
"type": "uint32be",
"name": "payload",
"offset": 0,
"length": 1,
"offsetbit": 0,
"scale": "1",
"mask": ""
}
],
"swap1": "",
"swap2": "",
"swap3": "",
"swap1Type": "swap",
"swap2Type": "swap",
"swap3Type": "swap",
"msgProperty": "payload",
"msgPropertyType": "str",
"resultType": "value",
"resultTypeType": "return",
"multipleResult": false,
"fanOutMultipleResult": false,
"setTopic": true,
"outputs": 1,
"x": 540,
"y": 150,
"wires": [
[
"b60c91c1089bb46f",
"c4272e7301b373cb"
]
]
},
{
"id": "80a6c07b244de845",
"type": "buffer-parser",
"z": "43214d9410f9188b",
"name": "16bit to decimal",
"data": "payload",
"dataType": "msg",
"specification": "spec",
"specificationType": "ui",
"items": [
{
"type": "uint16be",
"name": "item1",
"offset": 0,
"length": 1,
"offsetbit": 0,
"scale": "1",
"mask": ""
}
],
"swap1": "",
"swap2": "",
"swap3": "",
"swap1Type": "swap",
"swap2Type": "swap",
"swap3Type": "swap",
"msgProperty": "payload",
"msgPropertyType": "str",
"resultType": "value",
"resultTypeType": "return",
"multipleResult": false,
"fanOutMultipleResult": false,
"setTopic": true,
"outputs": 1,
"x": 540,
"y": 290,
"wires": [
[
"b60c91c1089bb46f",
"80b2f5969bbb426c"
]
]
},
{
"id": "5f0880bc7ad09082",
"type": "modbus-write",
"z": "43214d9410f9188b",
"name": "Set Recharge SOC",
"showStatusActivities": false,
"showErrors": false,
"showWarnings": true,
"unitid": "10",
"dataType": "HoldingRegister",
"adr": "40247",
"quantity": "1",
"server": "66293601c9428680",
"emptyMsgOnFail": false,
"keepMsgProperties": false,
"delayOnStart": false,
"startDelayTime": "",
"x": 1480,
"y": 300,
"wires": [
[],
[]
]
},
{
"id": "b60c91c1089bb46f",
"type": "join",
"z": "43214d9410f9188b",
"name": "Combine Data",
"mode": "custom",
"build": "object",
"property": "payload",
"propertyType": "msg",
"key": "topic",
"joiner": "\n",
"joinerType": "str",
"accumulate": false,
"timeout": "5",
"count": "6",
"reduceRight": false,
"reduceExp": "",
"reduceInit": "",
"reduceInitType": "num",
"reduceFixup": "",
"x": 840,
"y": 280,
"wires": [
[
"8fc3b76505610a19",
"e3a9d607660cbc42"
]
]
},
{
"id": "4face4c7c0f5fe8e",
"type": "modbus-read",
"z": "43214d9410f9188b",
"name": "Read Current Recharge SOC",
"topic": "rechargeSOC",
"showStatusActivities": false,
"logIOActivities": false,
"showErrors": false,
"showWarnings": true,
"unitid": "10",
"dataType": "HoldingRegister",
"adr": "40247",
"quantity": "1",
"rate": "3",
"rateUnit": "s",
"delayOnStart": false,
"startDelayTime": "",
"server": "66293601c9428680",
"useIOFile": false,
"ioFile": "",
"useIOForPayload": false,
"emptyMsgOnFail": false,
"x": 370,
"y": 360,
"wires": [
[
"6c7cef4d62b170e8"
],
[]
]
},
{
"id": "6c7cef4d62b170e8",
"type": "buffer-parser",
"z": "43214d9410f9188b",
"name": "16bit to decimal",
"data": "payload",
"dataType": "msg",
"specification": "spec",
"specificationType": "ui",
"items": [
{
"type": "uint16be",
"name": "item1",
"offset": 0,
"length": 1,
"offsetbit": 0,
"scale": "1",
"mask": ""
}
],
"swap1": "",
"swap2": "",
"swap3": "",
"swap1Type": "swap",
"swap2Type": "swap",
"swap3Type": "swap",
"msgProperty": "payload",
"msgPropertyType": "str",
"resultType": "value",
"resultTypeType": "return",
"multipleResult": false,
"fanOutMultipleResult": false,
"setTopic": true,
"outputs": 1,
"x": 600,
"y": 360,
"wires": [
[
"b60c91c1089bb46f",
"45e785f09462107c"
]
]
},
{
"id": "e9fc1680ed2c6d20",
"type": "modbus-write",
"z": "43214d9410f9188b",
"name": "Set Charger State",
"showStatusActivities": false,
"showErrors": true,
"showWarnings": true,
"unitid": "10",
"dataType": "HoldingRegister",
"adr": "356",
"quantity": "1",
"server": "cdabbb805236446d",
"emptyMsgOnFail": false,
"keepMsgProperties": false,
"delayOnStart": false,
"startDelayTime": "",
"x": 1480,
"y": 360,
"wires": [
[],
[]
]
},
{
"id": "e3a9d607660cbc42",
"type": "debug",
"z": "43214d9410f9188b",
"name": "Combined Modbus Inputs",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1050,
"y": 220,
"wires": []
},
{
"id": "bb5e409e8acf37a7",
"type": "debug",
"z": "43214d9410f9188b",
"name": "Setting EPC Power",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1260,
"y": 240,
"wires": []
},
{
"id": "5baad6d66274c89b",
"type": "debug",
"z": "43214d9410f9188b",
"name": "Setting Recharge SOC",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1270,
"y": 300,
"wires": []
},
{
"id": "b0e551fbe9ba3cf6",
"type": "debug",
"z": "43214d9410f9188b",
"name": "Setting Charger State",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1260,
"y": 400,
"wires": []
},
{
"id": "538c21b3dd7c46a9",
"type": "modbus-read",
"z": "43214d9410f9188b",
"name": "Read Battery Power",
"topic": "batteryPower",
"showStatusActivities": false,
"logIOActivities": false,
"showErrors": false,
"showWarnings": true,
"unitid": "1",
"dataType": "InputRegister",
"adr": "520",
"quantity": "2",
"rate": "3",
"rateUnit": "s",
"delayOnStart": false,
"startDelayTime": "",
"server": "cdabbb805236446d",
"useIOFile": false,
"ioFile": "",
"useIOForPayload": false,
"emptyMsgOnFail": false,
"x": 340,
"y": 220,
"wires": [
[
"2f881882767f0030"
],
[]
]
},
{
"id": "2f881882767f0030",
"type": "buffer-parser",
"z": "43214d9410f9188b",
"name": "32bit to decimal",
"data": "payload",
"dataType": "msg",
"specification": "spec",
"specificationType": "ui",
"items": [
{
"type": "uint32be",
"name": "payload",
"offset": 0,
"length": 1,
"offsetbit": 0,
"scale": "1",
"mask": ""
}
],
"swap1": "",
"swap2": "",
"swap3": "",
"swap1Type": "swap",
"swap2Type": "swap",
"swap3Type": "swap",
"msgProperty": "payload",
"msgPropertyType": "str",
"resultType": "value",
"resultTypeType": "return",
"multipleResult": false,
"fanOutMultipleResult": false,
"setTopic": true,
"outputs": 1,
"x": 570,
"y": 220,
"wires": [
[
"b60c91c1089bb46f",
"f1e8fe8fd2cfbe5a"
]
]
},
{
"id": "c4272e7301b373cb",
"type": "debug",
"z": "43214d9410f9188b",
"name": "Debug: Grid Usage",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 800,
"y": 150,
"wires": []
},
{
"id": "f1e8fe8fd2cfbe5a",
"type": "debug",
"z": "43214d9410f9188b",
"name": "Debug: Battery Power",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 810,
"y": 220,
"wires": []
},
{
"id": "80b2f5969bbb426c",
"type": "debug",
"z": "43214d9410f9188b",
"name": "Debug: EPC Limit",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 810,
"y": 320,
"wires": []
},
{
"id": "45e785f09462107c",
"type": "debug",
"z": "43214d9410f9188b",
"name": "Debug: Recharge SOC",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 820,
"y": 360,
"wires": []
},
{
"id": "0217e2bf9d8661a6",
"type": "debug",
"z": "43214d9410f9188b",
"name": "Debug: Battery SOC",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 810,
"y": 430,
"wires": []
},
{
"id": "945c3779b9caaecf",
"type": "modbus-read",
"z": "43214d9410f9188b",
"name": "Read Grid Export",
"topic": "gridExport",
"showStatusActivities": false,
"logIOActivities": false,
"showErrors": false,
"showWarnings": true,
"unitid": "1",
"dataType": "InputRegister",
"adr": "88",
"quantity": "2",
"rate": "2",
"rateUnit": "s",
"delayOnStart": false,
"startDelayTime": "",
"server": "cdabbb805236446d",
"useIOFile": false,
"ioFile": "",
"useIOForPayload": false,
"emptyMsgOnFail": false,
"x": 330,
"y": 80,
"wires": [
[
"1a283c626d23fc2e"
],
[]
]
},
{
"id": "1a283c626d23fc2e",
"type": "buffer-parser",
"z": "43214d9410f9188b",
"name": "32bit to decimal",
"data": "payload",
"dataType": "msg",
"specification": "spec",
"specificationType": "ui",
"items": [
{
"type": "uint32be",
"name": "payload",
"offset": 0,
"length": 1,
"offsetbit": 0,
"scale": "1",
"mask": ""
}
],
"swap1": "",
"swap2": "",
"swap3": "",
"swap1Type": "swap",
"swap2Type": "swap",
"swap3Type": "swap",
"msgProperty": "payload",
"msgPropertyType": "str",
"resultType": "value",
"resultTypeType": "return",
"multipleResult": false,
"fanOutMultipleResult": false,
"setTopic": true,
"outputs": 1,
"x": 560,
"y": 80,
"wires": [
[
"b60c91c1089bb46f"
]
]
},
{
"id": "cdabbb805236446d",
"type": "modbus-client",
"name": "Insight 503",
"clienttype": "tcp",
"bufferCommands": true,
"stateLogEnabled": false,
"queueLogEnabled": false,
"failureLogEnabled": true,
"tcpHost": "192.168.1.127",
"tcpPort": "503",
"tcpType": "DEFAULT",
"serialPort": "/dev/ttyUSB",
"serialType": "RTU-BUFFERD",
"serialBaudrate": 9600,
"serialDatabits": 8,
"serialStopbits": 1,
"serialParity": "none",
"serialConnectionDelay": 100,
"serialAsciiResponseStartDelimiter": "0x3A",
"unit_id": 1,
"commandDelay": 1,
"clientTimeout": 1000,
"reconnectOnTimeout": true,
"reconnectTimeout": 2000,
"parallelUnitIdsAllowed": true,
"showErrors": false,
"showWarnings": true,
"showLogs": true
},
{
"id": "66293601c9428680",
"type": "modbus-client",
"name": "Insight 502",
"clienttype": "tcp",
"bufferCommands": true,
"stateLogEnabled": false,
"queueLogEnabled": false,
"failureLogEnabled": true,
"tcpHost": "192.168.1.127",
"tcpPort": 502,
"tcpType": "DEFAULT",
"serialPort": "/dev/ttyUSB",
"serialBaudrate": 9600,
"serialDatabits": 8,
"serialStopbits": 1,
"serialParity": "none",
"serialConnectionDelay": 100,
"serialAsciiResponseStartDelimiter": "0x3A",
"unit_id": 1,
"commandDelay": 1,
"clientTimeout": 1000,
"reconnectOnTimeout": true,
"reconnectTimeout": 2000,
"parallelUnitIdsAllowed": true,
"showErrors": false,
"showWarnings": true,
"showLogs": true
},
{
"id": "b3d68f18732abb98",
"type": "global-config",
"env": [],
"modules": {
"node-red-contrib-modbus": "5.43.0",
"node-red-contrib-buffer-parser": "3.2.2"
}
}
]
How to Import:
- Click the “Copy” button above to copy the JSON to your clipboard
- Open Node-RED
- Go to Menu (☰) → Import
- Paste the JSON code
- Click “Import”

