Function node Reference Error: msg is not defined

i am setting up an automation in node red for home assistant. i have a 20 amp circuit with three energy-monitoring smart plugs having three devices plugged into them. the 20 amps are not enough to run all three devices oat the same time. in other words, the total current used by the devices when they are running at the same time is more than 20 amps. so i need an automation that will turn off a smart plug/device if, when the device turns on and reports the amount of current needed to the flow, the flow will turn it off if it determines that the combined amount of current used by the two or more devices is more than 20 amps. the device that will be turned off is the one that took the number of amps over 20 amps. the flow should be able to turn the device that was turned off back on when enough current is available again. the flow will know that there is enough current for that specific device because it learned how much current the device uses when it tried to turn on but was shut off. Some specifics: the smart plugs are ESPhome plugs (Kauf brand); in node red, an events:state node can be used to receive and report the value of current used by each device.; and a call service node can be used to turn off and on the smart plugs/devices. I know this is a complicated task so we can solve this in multiple steps.

The function node I have that does the bulk of the work is giving me a "ReferenceError: msg is not defined" when i deploy the flow. I haven't been able to figure it out. Any help would be appreciated.

(function() {
  // Parse the message object
  var deviceCurrent = msg.payload; // Current usage reported by the device
  var deviceToTurnOn = context.get('deviceToTurnOn');
  var totalCurrent = context.get('totalCurrent') || 0;

  // Calculate total current usage
  totalCurrent += deviceCurrent;

  // Check for overload condition
  if (totalCurrent > 20) {
    var deviceToTurnOff = msg.device;
    var currentNeeded = deviceCurrent;

    // Turn off the device
    msg.payload = {
      domain: 'switch',
      service: 'turn_off',
      data: {
        entity_id: deviceToTurnOff
      }
    };

    // Include overload information in the message
    msg.overload = true;
    msg.offendingDevice = deviceToTurnOff;
  } else {
    // Reset deviceToTurnOff and currentNeeded if no overload
    deviceToTurnOff = null;
    currentNeeded = null;

    // Include copacetic information in the message
    msg.overload = false;
  }

  // Track current usage for each device
  context.set(msg.device, deviceCurrent);

  // Restore power to the device
  if (deviceToTurnOn && totalCurrent >= deviceToTurnOn) {
    msg.payload = {
      domain: 'switch',
      service: 'turn_on',
      data: {
        entity_id: deviceToTurnOn
      }
    };
    deviceToTurnOn = null; // Reset the device to turn on
  }

  // Include total current in the message
  msg.totalCurrent = totalCurrent;

  // Store variables in context
  context.set('deviceToTurnOn', deviceToTurnOn);
  context.set('totalCurrent', totalCurrent);

  return msg; // Output the message
})();

type or paste code here

Hello @anoueiry & welcome to this forum!

You don't need to embrace the logic in the function node with a

(function() {
 ...
})();

structure. In fact, I'd consider this as wrong.
Have you tried to go without it?

Thank you for the response. I did try that and still same error message. Full disclosure: I know very little coding. I'm figuring things out as I go, but here I'm working with chatGPT.

The rest of your code looks quite ok. If you export the flow & share it here (please format it as preformatted text!), we could check if there's sth else creating issues.

For standard topics (like yours), the chatty usually creates acceptable code. Thus it's definitely a way to learn things...

EDIT: I should have kept reading. The code is from ChatGPT. It seems like always ChatGPT lives up to my expectations... garbage. It produces something well looking but unusable.

Forgive me this question, but where did you get this code from? I doubt that it will produce any meaningful output. For example deviceToTurnOn is nowhere defined. totalCurrent >= deviceToTurnOn compares Amps with a device?
It would be good if you posted an export from a flow that shows inputs and outputs.

Thank you. You confirmed my suspicion that it's garbage. Again, I know next to nothing about coding. I'm a virologist by trade. I used chatGPT for a much simpler flow before and it worked. Thought I'd try something harder.

An export of the flow is below. Maybe that flow or function might be handy for others as a template? Maybe that's asking for too much but any help there would be appreciated.

[
    {
        "id": "a97346c8eca08538",
        "type": "tab",
        "label": "Based on timestamp",
        "disabled": false,
        "info": "event:state (Device 1) --> Function node 1\nevent:state (Device 2) --> Function node 1\nevent:state (Device 3) --> Function node 1\nevent:state (Device 4) --> Function node 1\nevent:state (Device 5) --> Function node 1\nFunction node 1 --> Function node 1.5\nFunction node 1.5 --> Function node 2\n",
        "env": []
    },
    {
        "id": "547dcf8b572a2d08",
        "type": "server-state-changed",
        "z": "a97346c8eca08538",
        "name": "SPA2",
        "server": "a7b15a72.3e9048",
        "version": 4,
        "exposeToHomeAssistant": false,
        "haConfig": [
            {
                "property": "name",
                "value": ""
            },
            {
                "property": "icon",
                "value": ""
            }
        ],
        "entityidfilter": "sensor.kauf_plug_current_2",
        "entityidfiltertype": "exact",
        "outputinitially": false,
        "state_type": "num",
        "haltifstate": "",
        "halt_if_type": "num",
        "halt_if_compare": "is",
        "outputs": 1,
        "output_only_on_state_change": true,
        "for": "",
        "forType": "num",
        "forUnits": "minutes",
        "ignorePrevStateNull": false,
        "ignorePrevStateUnknown": false,
        "ignorePrevStateUnavailable": false,
        "ignoreCurrentStateUnknown": false,
        "ignoreCurrentStateUnavailable": false,
        "outputProperties": [
            {
                "property": "payload",
                "propertyType": "msg",
                "value": "",
                "valueType": "entityState"
            },
            {
                "property": "device",
                "propertyType": "msg",
                "value": "SPA2",
                "valueType": "str"
            }
        ],
        "x": 90,
        "y": 100,
        "wires": [
            [
                "13301a4b3ff36bcd"
            ]
        ]
    },
    {
        "id": "4a81f00ee9ef624f",
        "type": "server-state-changed",
        "z": "a97346c8eca08538",
        "name": "SPA1",
        "server": "a7b15a72.3e9048",
        "version": 4,
        "exposeToHomeAssistant": false,
        "haConfig": [
            {
                "property": "name",
                "value": ""
            },
            {
                "property": "icon",
                "value": ""
            }
        ],
        "entityidfilter": "sensor.kauf_plug_current",
        "entityidfiltertype": "exact",
        "outputinitially": false,
        "state_type": "num",
        "haltifstate": "",
        "halt_if_type": "str",
        "halt_if_compare": "is",
        "outputs": 1,
        "output_only_on_state_change": true,
        "for": "",
        "forType": "num",
        "forUnits": "minutes",
        "ignorePrevStateNull": false,
        "ignorePrevStateUnknown": false,
        "ignorePrevStateUnavailable": false,
        "ignoreCurrentStateUnknown": false,
        "ignoreCurrentStateUnavailable": false,
        "outputProperties": [
            {
                "property": "payload",
                "propertyType": "msg",
                "value": "",
                "valueType": "entityState"
            },
            {
                "property": "device",
                "propertyType": "msg",
                "value": "SPA1",
                "valueType": "str"
            }
        ],
        "x": 90,
        "y": 40,
        "wires": [
            [
                "13301a4b3ff36bcd"
            ]
        ]
    },
    {
        "id": "13301a4b3ff36bcd",
        "type": "function",
        "z": "a97346c8eca08538",
        "name": "Identify offending device",
        "func": "// Check if msg object exists\nif (msg) {\n    // Parse the message object\n    var deviceCurrent = msg.payload; // Current usage reported by the device\n    var deviceToTurnOn = context.get('deviceToTurnOn');\n    var totalCurrent = context.get('totalCurrent') || 0;\n\n    // Calculate total current usage\n    totalCurrent += deviceCurrent;\n\n    // Check for overload condition\n    if (totalCurrent > 20) {\n        var deviceToTurnOff = msg.device;\n        var currentNeeded = deviceCurrent;\n\n        // Turn off the device\n        msg.payload = {\n            domain: 'switch',\n            service: 'toggle',\n            data: {\n                entity_id: deviceToTurnOff\n            }\n        };\n\n        // Include overload information in the message\n        msg.overload = true;\n        msg.offendingDevice = deviceToTurnOff;\n    } else {\n        // Reset deviceToTurnOff and currentNeeded if no overload\n        deviceToTurnOff = null;\n        currentNeeded = null;\n\n        // Include copacetic information in the message\n        msg.overload = false;\n    }\n\n    // Track current usage for each device\n    context.set(msg.device, deviceCurrent);\n\n    // Restore power to the device\n    if (deviceToTurnOn && totalCurrent >= deviceToTurnOn) {\n        msg.payload = {\n            domain: 'switch',\n            service: 'toggle',\n            data: {\n                entity_id: deviceToTurnOn\n            }\n        };\n        deviceToTurnOn = null; // Reset the device to turn on\n    }\n\n    // Include total current in the message\n    msg.totalCurrent = totalCurrent;\n\n    // Store variables in context\n    context.set('deviceToTurnOn', deviceToTurnOn);\n    context.set('totalCurrent', totalCurrent);\n}\n\nreturn msg; // Output the message\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "// Step 4: Calculate total current usage\nvar totalCurrent = context.get('totalCurrent') || 0;\nvar deviceCurrent = msg.payload; // Current usage reported by the device\ntotalCurrent += deviceCurrent;\n\n// Step 5: Check for overload condition\nif (totalCurrent > 20) {\n    var deviceToTurnOff = msg.device;\n    var currentNeeded = deviceCurrent;\n\n    // Step 6: Turn off the device\n    msg.payload = {\n        domain: 'switch',\n        service: 'turn_off',\n        data: {\n            entity_id: deviceToTurnOff\n        }\n    };\n\n    // Include overload information in the message\n    msg.overload = true;\n    msg.offendingDevice = deviceToTurnOff;\n} else {\n    // Reset deviceToTurnOff and currentNeeded if no overload\n    context.set('deviceToTurnOff', null);\n    context.set('currentNeeded', null);\n\n    // Include copacetic information in the message\n    msg.overload = false;\n}\n\n// Step 7: Track current usage for each device\ncontext.set(msg.device, deviceCurrent);\n\n// Step 8: Restore power to the device\nvar deviceToTurnOn = context.get('deviceToTurnOn');\nif (deviceToTurnOn && totalCurrent >= deviceToTurnOn) {\n    msg.payload = {\n        domain: 'switch',\n        service: 'turn_on',\n        data: {\n            entity_id: deviceToTurnOn\n        }\n    };\n    context.set('deviceToTurnOn', null); // Reset the device to turn on\n}\n\n// Include total current in the message\nmsg.totalCurrent = totalCurrent;\n\nreturn msg; // Output the message\n",
        "finalize": "",
        "libs": [],
        "x": 430,
        "y": 180,
        "wires": [
            [
                "87c348af35da8e64"
            ]
        ]
    },
    {
        "id": "69dc4d741b0ed124",
        "type": "api-call-service",
        "z": "a97346c8eca08538",
        "name": "Toggle SPA1",
        "server": "7f820507.34c1cc",
        "version": 5,
        "debugenabled": false,
        "domain": "switch",
        "service": "toggle",
        "areaId": [],
        "deviceId": [
            "4f28887c7842dfba82c9c8bad769438f"
        ],
        "entityId": [
            "switch.kauf_plug"
        ],
        "data": "",
        "dataType": "jsonata",
        "mergeContext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 590,
        "y": 280,
        "wires": [
            []
        ]
    },
    {
        "id": "87c348af35da8e64",
        "type": "switch",
        "z": "a97346c8eca08538",
        "name": "",
        "property": "device",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "SPA1",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "SPA2",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "SPA3",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 3,
        "x": 390,
        "y": 340,
        "wires": [
            [
                "69dc4d741b0ed124"
            ],
            [
                "5b1f69d8ef405e85"
            ],
            [
                "f3fbc2431fa2e4b8"
            ]
        ]
    },
    {
        "id": "5b1f69d8ef405e85",
        "type": "api-call-service",
        "z": "a97346c8eca08538",
        "name": "Toggle SPA1",
        "server": "7f820507.34c1cc",
        "version": 5,
        "debugenabled": false,
        "domain": "switch",
        "service": "toggle",
        "areaId": [],
        "deviceId": [
            "811926f05efcc93f9f2e9f21dbb95efe"
        ],
        "entityId": [
            "switch.kauf_plug_2"
        ],
        "data": "",
        "dataType": "jsonata",
        "mergeContext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 590,
        "y": 340,
        "wires": [
            []
        ]
    },
    {
        "id": "2059234c12c52fec",
        "type": "server-state-changed",
        "z": "a97346c8eca08538",
        "name": "SPA3.  Not configured yet.",
        "server": "7f820507.34c1cc",
        "version": 4,
        "exposeToHomeAssistant": false,
        "haConfig": [
            {
                "property": "name",
                "value": ""
            },
            {
                "property": "icon",
                "value": ""
            }
        ],
        "entityidfilter": "",
        "entityidfiltertype": "exact",
        "outputinitially": false,
        "state_type": "str",
        "haltifstate": "",
        "halt_if_type": "str",
        "halt_if_compare": "is",
        "outputs": 1,
        "output_only_on_state_change": true,
        "for": "0",
        "forType": "num",
        "forUnits": "minutes",
        "ignorePrevStateNull": false,
        "ignorePrevStateUnknown": false,
        "ignorePrevStateUnavailable": false,
        "ignoreCurrentStateUnknown": false,
        "ignoreCurrentStateUnavailable": false,
        "outputProperties": [
            {
                "property": "payload",
                "propertyType": "msg",
                "value": "",
                "valueType": "entityState"
            },
            {
                "property": "data",
                "propertyType": "msg",
                "value": "",
                "valueType": "eventData"
            },
            {
                "property": "topic",
                "propertyType": "msg",
                "value": "",
                "valueType": "triggerId"
            }
        ],
        "x": 130,
        "y": 200,
        "wires": [
            [
                "13301a4b3ff36bcd"
            ]
        ]
    },
    {
        "id": "f3fbc2431fa2e4b8",
        "type": "api-call-service",
        "z": "a97346c8eca08538",
        "name": "SPA3.  not configured yet",
        "server": "7f820507.34c1cc",
        "version": 5,
        "debugenabled": false,
        "domain": "",
        "service": "",
        "areaId": [],
        "deviceId": [],
        "entityId": [],
        "data": "",
        "dataType": "jsonata",
        "mergeContext": "",
        "mustacheAltTags": false,
        "outputProperties": [],
        "queue": "none",
        "x": 630,
        "y": 400,
        "wires": [
            []
        ]
    },
    {
        "id": "a7b15a72.3e9048",
        "type": "server",
        "name": "Home Assistant",
        "version": 5,
        "addon": true,
        "rejectUnauthorizedCerts": true,
        "ha_boolean": "y|yes|true|on|home|open",
        "connectionDelay": true,
        "cacheJson": true,
        "heartbeat": false,
        "heartbeatInterval": 30,
        "areaSelector": "friendlyName",
        "deviceSelector": "friendlyName",
        "entitySelector": "friendlyName",
        "statusSeparator": "at: ",
        "statusYear": "hidden",
        "statusMonth": "short",
        "statusDay": "numeric",
        "statusHourCycle": "h23",
        "statusTimeFormat": "h:m",
        "enableGlobalContextStore": true
    },
    {
        "id": "7f820507.34c1cc",
        "type": "server",
        "name": "Home Assistant",
        "addon": true
    }
]

I removed the "blue" nodes - as I don't have them installed. The flow then deploys fine; no error referencing msg.

EDIT & surprise: There is an error indication - at the command line:

20 May 17:23:50 - [error] [function:Identify offending device] ReferenceError: msg is not defined

This is caused by the fact that you have additional (& not neccessary) code in the Start tab of the fuction node. If you remove this, the node launches without raising an error; there might be logical issues though (as indicated above).

Putting the code to one side for a moment, I think you need to clarify the problem you are trying to solve

As you have described it, I can see a number of possible issues, you might not have considered.

  1. I assume there is there no way to increase the available current to more than 20A ?
  2. How is the current limited to 20A eg is it a 20A fuse ?
  3. Do you already know how much current each device uses, and is this constant when switched on ?
  4. How are the devices turned on, some automatic process, a timer, a switch on the device etc ?
  5. Do any of the devices have "precedence" over others eg is one more important ?
  6. If a device starts running and the logic turns of the smart plug, could this cause harm to the device or something relying on it ?
  7. Can you tell us what the devices are / what they are doing ?
1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.