Virtual AC Load node: example of parameters to inject

In another topic the question was raised on how to use the Virtual AC Load node.
I grabbed (most of) the fields with MQTT Explorer and made this example to inject them into the node.

Hopefully someone can use this to their benefit :slight_smile:

[{"id":"e4a02e8dd8f25f92","type":"victron-virtual","z":"9f95e47b9a8d70a1","name":"","outputs":1,"device":"acload","default_values":false,"acload_nrofphases":1,"enable_s2support":false,"battery_capacity":25,"include_battery_temperature":false,"battery_voltage_preset":"24","battery_voltage_custom":24,"generator_type":"ac","generator_nrofphases":1,"include_engine_hours":false,"include_starter_voltage":false,"include_history_energy":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":1,"switch_1_type":1,"switch_1_min":0,"switch_1_max":"","switch_1_initial":0,"switch_1_label":"","switch_1_unit":"","switch_1_step":1,"switch_1_customname":"","switch_1_group":"","switch_1_include_measurement":false,"switch_1_rgb_color_wheel":false,"switch_1_cct_wheel":false,"switch_1_rgb_white_dimmer":false,"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":320,"y":460,"wires":[["93fa80a7081fa9ab"]]},{"id":"93fa80a7081fa9ab","type":"debug","z":"9f95e47b9a8d70a1","name":"debug 7","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"auto","x":520,"y":460,"wires":[]},{"id":"f0a888d88d7bfdd8","type":"inject","z":"9f95e47b9a8d70a1","name":"","props":[{"p":"topic","v":"0","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":350,"y":400,"wires":[["5bd91fdac60b4e2a"]]},{"id":"5bd91fdac60b4e2a","type":"function","z":"9f95e47b9a8d70a1","name":"AC Load","func":"msg.payload = {\n    \"/Serial\": 1,\n    \"/Ac/L1/Voltage\": 235,\n    \"/Ac/L1/Current\": 1,\n    \"/Ac/L1/Power\": 200,\n    \"/Ac/L1/PowerFactor\": 1,\n    \"/Ac/L1/Energy/Forward\": 1000,\n    \"/Ac/L1/Energy/Reverse\": 0,\n/*\n    \"Ac/L2/Voltage\": 235,\n    \"/Ac/L2/Current\": 1,\n    \"/Ac/L2/Power\": 200,\n    \"/Ac/L2/PowerFactor\": 1,\n    \"/Ac/L2/Energy/Forward\": 1000,\n    \"/Ac/L2/Energy/Reverse\": 0,\n    \"/Ac/L3/Voltage\": 235,\n    \"/Ac/L3/Current\": 1,\n    \"/Ac/L3/Power\": 200,\n    \"/Ac/L3/PowerFactor\": 1,\n    \"/Ac/L3/Energy/Forward\": 1000,\n    \"/Ac/L3/Energy/Reverse\": 0,\n*/\n    \"/Ac/Power\": 200,\n    \"/Ac/Energy/Forward\": 1000,\n    \"/Ac/Energy/Reverse\": 0,\n};\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":400,"wires":[["e4a02e8dd8f25f92"]]},{"id":"13da2462149302af","type":"global-config","env":[],"modules":{"@victronenergy/node-red-contrib-victron":"1.6.56"}}]
1 Like

Thanks Bart, I was still using custom inputs and just reconfigured everything based on your post. I am using HomeWizard meters and sockets to measure my PV. It currently looks like this:

[
    {
        "id": "c638519ca3f162f8",
        "type": "group",
        "z": "b51fc0718e9c7f9d",
        "style": {
            "stroke": "#999999",
            "stroke-opacity": "1",
            "fill": "none",
            "fill-opacity": "1",
            "label": true,
            "label-position": "nw",
            "color": "#a4a4a4"
        },
        "nodes": [
            "c942bad4ad7105fd",
            "8116ebb3ac362090",
            "8f65547a34d2b35f",
            "8519a23a0f847c60",
            "a01c2d5855f30b8d",
            "a008613031afeb37",
            "811096c848896695",
            "1aa0d1b15a78f3be",
            "2ee0b636cdba77fa"
        ],
        "x": 54,
        "y": 2139,
        "w": 1272,
        "h": 202
    },
    {
        "id": "c942bad4ad7105fd",
        "type": "victron-virtual",
        "z": "b51fc0718e9c7f9d",
        "g": "c638519ca3f162f8",
        "name": "PV Veranda",
        "outputs": 1,
        "device": "pvinverter",
        "default_values": false,
        "enable_s2support": false,
        "battery_capacity": 25,
        "include_battery_temperature": false,
        "battery_voltage_custom": "",
        "include_engine_hours": false,
        "include_starter_voltage": false,
        "include_history_energy": 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": "1",
        "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": 1010,
        "y": 2240,
        "wires": [
            [
                "2ee0b636cdba77fa"
            ]
        ]
    },
    {
        "id": "8116ebb3ac362090",
        "type": "inject",
        "z": "b51fc0718e9c7f9d",
        "g": "c638519ca3f162f8",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "5",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 170,
        "y": 2220,
        "wires": [
            [
                "8f65547a34d2b35f"
            ]
        ]
    },
    {
        "id": "8f65547a34d2b35f",
        "type": "http request",
        "z": "b51fc0718e9c7f9d",
        "g": "c638519ca3f162f8",
        "name": "PV - HomeWizard Measurements",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "http://192.168.88.170/api/v1/data",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 460,
        "y": 2220,
        "wires": [
            [
                "1aa0d1b15a78f3be"
            ]
        ]
    },
    {
        "id": "8519a23a0f847c60",
        "type": "inject",
        "z": "b51fc0718e9c7f9d",
        "g": "c638519ca3f162f8",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "5",
        "topic": "/Ac/MaxPower",
        "payload": "4",
        "payloadType": "num",
        "x": 510,
        "y": 2180,
        "wires": [
            [
                "1aa0d1b15a78f3be"
            ]
        ]
    },
    {
        "id": "a01c2d5855f30b8d",
        "type": "http request",
        "z": "b51fc0718e9c7f9d",
        "g": "c638519ca3f162f8",
        "name": "PV - HomeWizard Information",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "http://192.168.88.170/api",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 470,
        "y": 2260,
        "wires": [
            [
                "1aa0d1b15a78f3be"
            ]
        ]
    },
    {
        "id": "a008613031afeb37",
        "type": "inject",
        "z": "b51fc0718e9c7f9d",
        "g": "c638519ca3f162f8",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 170,
        "y": 2260,
        "wires": [
            [
                "a01c2d5855f30b8d"
            ]
        ]
    },
    {
        "id": "811096c848896695",
        "type": "link in",
        "z": "b51fc0718e9c7f9d",
        "g": "c638519ca3f162f8",
        "name": "Throttle",
        "links": [
            "7a1d5ae47e397e2e"
        ],
        "x": 585,
        "y": 2300,
        "wires": [
            [
                "1aa0d1b15a78f3be"
            ]
        ]
    },
    {
        "id": "1aa0d1b15a78f3be",
        "type": "function",
        "z": "b51fc0718e9c7f9d",
        "g": "c638519ca3f162f8",
        "name": "Parse & Route PV Data",
        "func": "const data = msg.payload;\n\nlet payload = {};\nlet statusCode = null;\n\n// --- Throttling (optional): if you send msg.topic=\"throttling\" ---\nif (msg.topic === \"throttling\" && (data === true || data === false)) {\n    context.set(\"isThrottling\", data);\n    return null;\n}\nconst isThrottling = context.get(\"isThrottling\") === true;\nif (isThrottling) statusCode = 12;\n\n// --- One-time inject: /Ac/MaxPower ---\nif (msg.topic === \"/Ac/MaxPower\") {\n    payload[\"/Ac/MaxPower\"] = Number(data);\n    msg.payload = payload;\n    return msg;\n}\n\n// --- Determine phase mode from product_type (when available) ---\n// HWE-KWH3 => 3-phase\n// HWE-KWH1, HWE-SKT, unknown => 1-phase\nlet phaseMode = null; // 1 or 3\n\nif (typeof data === \"object\" && data && data.product_type) {\n    payload[\"/ProductName\"] = String(data.product_type);\n    if (data.serial) payload[\"/Serial\"] = String(data.serial);\n\n    if (data.product_type === \"HWE-KWH3\") phaseMode = 3;\n    else phaseMode = 1; // includes HWE-KWH1, HWE-SKT, and any unknown types\n\n    // Save mode so measurement messages can use it\n    context.set(\"phaseMode\", phaseMode);\n\n    msg.payload = payload;\n    return msg;\n}\n\n// If no product_type in this msg, fall back to last known mode (default 1)\nphaseMode = context.get(\"phaseMode\") || 1;\n\n// --- Measurement handling ---\nif (typeof data === \"object\" && data && (\"wifi_ssid\" in data)) {\n\n    if (phaseMode === 3) {\n        // Voltage\n        payload[\"/Ac/L1/Voltage\"] = Number(data.active_voltage_l1_v);\n        payload[\"/Ac/L2/Voltage\"] = Number(data.active_voltage_l2_v);\n        payload[\"/Ac/L3/Voltage\"] = Number(data.active_voltage_l3_v);\n\n        // Current\n        payload[\"/Ac/L1/Current\"] = Number(data.active_current_l1_a);\n        payload[\"/Ac/L2/Current\"] = Number(data.active_current_l2_a);\n        payload[\"/Ac/L3/Current\"] = Number(data.active_current_l3_a);\n\n        // Power (negated for PV export display)\n        payload[\"/Ac/L1/Power\"] = -1 * Number(data.active_power_l1_w);\n        payload[\"/Ac/L2/Power\"] = -1 * Number(data.active_power_l2_w);\n        payload[\"/Ac/L3/Power\"] = -1 * Number(data.active_power_l3_w);\n        payload[\"/Ac/Power\"]    = -1 * Number(data.active_power_w);\n\n        // Energy\n        if (\"total_power_export_kwh\" in data) {\n            const total = Number(data.total_power_export_kwh);\n            payload[\"/Ac/Energy/Forward\"] = total;\n\n            const perPhase = total / 3;\n            payload[\"/Ac/L1/Energy/Forward\"] = perPhase;\n            payload[\"/Ac/L2/Energy/Forward\"] = perPhase;\n            payload[\"/Ac/L3/Energy/Forward\"] = perPhase;\n        }\n\n        // StatusCode fallback (if not throttling)\n        if (statusCode === null) {\n            statusCode = Math.abs(Number(data.active_power_w)) > 0 ? 7 : 8;\n        }\n\n    } else {\n        // 1-phase (L1 only)\n        payload[\"/Ac/L1/Voltage\"] = Number(data.active_voltage_v);\n        payload[\"/Ac/L1/Current\"] = Number(data.active_current_a);\n\n        // Power (negated for PV export display)\n        payload[\"/Ac/L1/Power\"] = -1 * Number(data.active_power_l1_w);\n        payload[\"/Ac/Power\"]    = -1 * Number(data.active_power_w);\n\n        // Energy\n        if (\"total_power_export_kwh\" in data) {\n            const total = Number(data.total_power_export_kwh);\n            payload[\"/Ac/Energy/Forward\"]    = total;\n            payload[\"/Ac/L1/Energy/Forward\"] = total;\n        }\n\n        // StatusCode fallback (if not throttling)\n        if (statusCode === null) {\n            statusCode = Math.abs(Number(data.active_power_w)) > 0 ? 7 : 8;\n        }\n    }\n\n    if (statusCode !== null) payload[\"/StatusCode\"] = statusCode;\n\n    msg.payload = payload;\n    return msg;\n}\n\nreturn null;\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 770,
        "y": 2240,
        "wires": [
            [
                "c942bad4ad7105fd"
            ]
        ]
    },
    {
        "id": "2ee0b636cdba77fa",
        "type": "debug",
        "z": "b51fc0718e9c7f9d",
        "g": "c638519ca3f162f8",
        "name": "debug 12",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1220,
        "y": 2240,
        "wires": []
    },
    {
        "id": "f26b4f5c6c83d546",
        "type": "global-config",
        "env": [],
        "modules": {
            "@victronenergy/node-red-contrib-victron": "1.6.56"
        }
    }
]

And this is what it looks like for an AC Load:

[
    {
        "id": "ac5c81226c76d6e8",
        "type": "group",
        "z": "b51fc0718e9c7f9d",
        "style": {
            "stroke": "#999999",
            "stroke-opacity": "1",
            "fill": "none",
            "fill-opacity": "1",
            "label": true,
            "label-position": "nw",
            "color": "#a4a4a4"
        },
        "nodes": [
            "c5c969651cadb2e7",
            "c016a63ac04337a5",
            "30111398d9e167ce",
            "0910ad649486a7a7",
            "fdb30a6c6fbb023d",
            "e59be2c46b7c12b9",
            "5015e22747103914"
        ],
        "x": 34,
        "y": 1119,
        "w": 1252,
        "h": 142
    },
    {
        "id": "c5c969651cadb2e7",
        "type": "victron-virtual",
        "z": "b51fc0718e9c7f9d",
        "g": "ac5c81226c76d6e8",
        "name": "Heatpump",
        "outputs": 1,
        "device": "acload",
        "default_values": false,
        "acload_nrofphases": 1,
        "enable_s2support": false,
        "battery_capacity": 25,
        "include_battery_temperature": false,
        "battery_voltage_preset": "24",
        "battery_voltage_custom": 24,
        "generator_type": "ac",
        "generator_nrofphases": 1,
        "include_engine_hours": false,
        "include_starter_voltage": false,
        "include_history_energy": 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": 1,
        "switch_1_type": 1,
        "switch_1_min": 0,
        "switch_1_max": "",
        "switch_1_initial": 0,
        "switch_1_label": "",
        "switch_1_unit": "",
        "switch_1_step": 1,
        "switch_1_customname": "",
        "switch_1_group": "",
        "switch_1_include_measurement": false,
        "switch_1_rgb_color_wheel": false,
        "switch_1_cct_wheel": false,
        "switch_1_rgb_white_dimmer": false,
        "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": 970,
        "y": 1180,
        "wires": [
            [
                "5015e22747103914"
            ]
        ]
    },
    {
        "id": "c016a63ac04337a5",
        "type": "inject",
        "z": "b51fc0718e9c7f9d",
        "g": "ac5c81226c76d6e8",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "5",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 150,
        "y": 1160,
        "wires": [
            [
                "fdb30a6c6fbb023d"
            ]
        ]
    },
    {
        "id": "30111398d9e167ce",
        "type": "inject",
        "z": "b51fc0718e9c7f9d",
        "g": "ac5c81226c76d6e8",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 150,
        "y": 1220,
        "wires": [
            [
                "0910ad649486a7a7"
            ]
        ]
    },
    {
        "id": "0910ad649486a7a7",
        "type": "http request",
        "z": "b51fc0718e9c7f9d",
        "g": "ac5c81226c76d6e8",
        "name": "AC - HomeWizard Information",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "http://192.168.88.59/api",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 390,
        "y": 1220,
        "wires": [
            [
                "e59be2c46b7c12b9"
            ]
        ]
    },
    {
        "id": "fdb30a6c6fbb023d",
        "type": "http request",
        "z": "b51fc0718e9c7f9d",
        "g": "ac5c81226c76d6e8",
        "name": "AC - HomeWizard Measurements",
        "method": "GET",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "http://192.168.88.59/api/v1/data",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 400,
        "y": 1160,
        "wires": [
            [
                "e59be2c46b7c12b9"
            ]
        ]
    },
    {
        "id": "e59be2c46b7c12b9",
        "type": "function",
        "z": "b51fc0718e9c7f9d",
        "g": "ac5c81226c76d6e8",
        "name": "Parse & Route AC Data",
        "func": "const data = msg.payload;\n\n// Load last-known state so we can merge /api + /api/v1/data updates\nconst state = flow.get(\"device_stats\") || {};\nlet payload = { ...state };\n\nlet changed = false;\n\n// --- Power Data Handling ---\nif (typeof data === \"object\" && data && (\"wifi_ssid\" in data)) {\n    payload[\"/Ac/L1/Voltage\"]        = data.active_voltage_v;\n    payload[\"/Ac/L1/Current\"]        = data.active_current_a;\n    payload[\"/Ac/L1/Power\"]          = Number(data.active_power_l1_w);\n    payload[\"/Ac/L1/PowerFactor\"]    = data.active_power_factor;\n    payload[\"/Ac/L1/Energy/Forward\"] = data.total_power_import_kwh;\n    payload[\"/Ac/L1/Energy/Reverse\"] = 0;\n\n    payload[\"/Ac/Power\"]             = Number(data.active_power_w);\n    payload[\"/Ac/Energy/Forward\"]    = data.total_power_import_kwh;\n    payload[\"/Ac/Energy/Reverse\"]    = 0;\n\n    changed = true;\n}\n\n// --- Product Info Handling ---\nif (typeof data === \"object\" && data && (\"product_type\" in data) && (\"serial\" in data)) {\n    payload[\"/ProductName\"] = data.product_type;\n    payload[\"/Serial\"]      = data.serial;\n\n    changed = true;\n}\n\n// If neither block matched, don't send anything\nif (!changed) return null;\n\n// Save merged state\nflow.set(\"device_stats\", payload);\n\n// Output to victron-virtual\nmsg.payload = payload;\nreturn msg;\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 730,
        "y": 1180,
        "wires": [
            [
                "c5c969651cadb2e7"
            ]
        ]
    },
    {
        "id": "5015e22747103914",
        "type": "debug",
        "z": "b51fc0718e9c7f9d",
        "g": "ac5c81226c76d6e8",
        "name": "debug 2",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1180,
        "y": 1180,
        "wires": []
    },
    {
        "id": "bd417682b346c63b",
        "type": "global-config",
        "env": [],
        "modules": {
            "@victronenergy/node-red-contrib-victron": "1.6.56"
        }
    }
]
1 Like