Help with function, please

Found it- see my next message...

I am trying to send data to a Home Assistant Call Service Node. Here is what the info tab shows for the node:

Node Help
Call a Home Assistant service
Inputs
  payload.domain 
    string
    Service domain to call
  payload.service 
    string
    Service service to call
  payload.data 
    object
    Service data to send with api call

When I put the information directly into the node, it processes perfectly, but I would rather not clutter my flow with lots of discrete nodes. I would like to put the data into the message going into the node, per the above syntax. I think it should look like this:

msg : Object
  object
  payload: object
    domain: "homeassistant"
    service: "turn_on"
    data: object
      entity_id: "switch.fios_6"

I've tried various ways to modify the msg.payload to resemble this structure with no success. Any help here would be appreciated.

Whoops, I figured it out. I thought...
This works In a function:

msg.topic="";
msg.payload.service="turn_on";
msg.payload.data={"entity_id":"switch.fios_6"}
return msg;

But in a larger function, below, it doesn't. (Look at the last case). This function is supposed to select what to do depending on the incoming MQTT payload. The first few just pass on a new MQTT message in output 1. Works fine. The last case is supposed to set new msg.payload values then send the data to output 2. It's the same code as in the test function (above), but the output is wrong. What did I do wrong?

object
_msgid: "17ea565.c99f2aa"
topic: ""
payload: "D93A4"

Here is the problem function:

var payload=msg.payload;
var newMsg;
var blankMsg="";
switch (payload){
    case "A93A4":
      newMsg = { payload: "TOGGLE",topic:"sidetable/light/cmnd/power"};
	  return [ newMsg, null ];
      break;
    case "333A2":
      newMsg = { payload: "ON",topic:"sidetable/light/cmnd/power"};
	  return [ newMsg, null ];
      break;
    case "133A4":
      newMsg = { payload: "OFF",topic:"sidetable/light/cmnd/power"};
	  return [ newMsg, null ];
      break;
    case "693A4":
      newMsg = { payload: "TOGGLE",topic:"cmnd/DeskLight/power"};
	  return [ newMsg, null ];
      break;
    case "EB3A4":
      newMsg = { payload: "ON",topic:"cmnd/DeskLight/power"};
	  return [ newMsg, null ];
      break;
    case "6B3A4":
      newMsg = { payload: "OFF",topic:"cmnd/DeskLight/power"};
	  return [ newMsg, null ];
      break;
    case "D3A4":
      newMsg = { payload: "ON",topic:"cmnd/studioheat/power"};
	  return [ newMsg, null ];
      break;
    case "8D3A4":
      newMsg = { payload: "OFF",topic:"cmnd/studioheat/power"};
	  return [ newMsg, null ];
      break;
    case "D93A4":
      msg.topic="";
      msg.payload.service="turn_on";
      msg.payload.data={"entity_id":"switch.fios_6"}
	  return [ null, msg ];
      break;
      
}
return blankMsg;

I am making progress sending data to the Home Assistant Service Node. (Node-Red).

If I put discrete data into the Domain, Service and Data fields of the node, it works.
But, I need to send the data to the node in msg.payload.

var payload=msg.payload;
var newMsg;
switch (payload){
case "D93A4":
msg.payload= {"domain":"homeassistant","service":"turn_on","data":{"entity_id":"switch.fios_6"}}
break;
case "593A4":
msg.payload= {"domain":"homeassistant","service":"turn_on","data":{"entity_id":"switch.fios_0"}}
break;
case "393A4":
msg.payload= {"domain":"homeassistant","service":"turn_on","data":{"entity_id":"switch.fios_3"}}
break;
}
return msg;

This is working, but I am getting an error from the HA Call Service node:

"Error: call service node is missing api "domain" property, not found in config or payload"

If I take out the "Domain" from my function node and put it into the "Domain" field of the HA Call Service node, I then get the error that "Service" property is missing.

What is wrong with my code?

Which home assistant node are you using? There seem to be several in the flows directory. In fact to save us installing it could you copy/paste the info for the node here so we can see what it says about the data.

I am using the Node-red installed from Home Assistant v0.72.1 (Hass.os)

This flow contains the following nodes:
inject, MQTT-in, MQTT-out, Function, Debug, Home Assistant Call Service.

What I am building is an IR-MQTT bridge where the hardware (an ESP8266-01) receives IR from any remote and publishes the IR Code (in Hex).

Any MQTT client can subscribe to the IRCode topic and handle codes as needed. In this case, this Node-Red flow is going to work as a remote for my Family Room Fios PVR. (We have a monitor in the basement that displays the A/V from the PVR. It's cheaper than renting another STB). The Home Assistant Call Service nodes are sending Turn_on service to a Broadlink Mini in the Family Room.

As I said before, I have a workaround where I put the Domain and Service in the Home Assistant Service Call node, then decide in the first Function node which Call Service node to send the flow to. I should be able to put the domain and service data into msg.payload going into the Home Assistant Call Service node, but I just can't figure that out.

[{"id":"bbc57818.901578","type":"mqtt in","z":"4820e6f6.309498","name":"","topic":"IRData","qos":"0","broker":"a5f4b39c.527e6","x":180,"y":160,"wires":[["436ad5bb.3c4eec","808b664a.f9b3a8"]]},{"id":"60705f51.0fb36","type":"mqtt out","z":"4820e6f6.309498","name":"","topic":"","qos":"1","retain":"","broker":"a5f4b39c.527e6","x":750,"y":220,"wires":[]},{"id":"436ad5bb.3c4eec","type":"debug","z":"4820e6f6.309498","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":430,"y":140,"wires":[]},{"id":"47eff4ce.7140fc","type":"inject","z":"4820e6f6.309498","name":"Toggle Sidelight","topic":"","payload":"A93A4","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":260,"wires":[["808b664a.f9b3a8"]]},{"id":"808b664a.f9b3a8","type":"function","z":"4820e6f6.309498","name":"Process the MQTT payload (2a)","func":"// This function routes the incoming MQTT messages containing an IR Code.\n// Output 1 goes to an MQTT-Out node.\n// Output 2 goes to a Home Assistant Call Service node for turn_on\n// Output 3 goes to a Home Assistant Call Service node for turn_off\n\nvar payload=msg.payload;\nvar newMsg;\nswitch (payload){\n // MQTT outputs\n case \"A93A4\":\n msg = { payload: \"TOGGLE\",topic:\"sidetable/light/cmnd/power\"};\n return [ msg, null, null ];\n case \"333A2\":\n msg = { payload: \"ON\",topic:\"sidetable/light/cmnd/power\"};\n return [ msg, null, null ];\n\n case \"133A4\":\n msg = { payload: \"OFF\",topic:\"sidetable/light/cmnd/power\"};\n return [ msg, null, null ];\n\n case \"693A4\":\n msg = { payload: \"TOGGLE\",topic:\"cmnd/DeskLight/power\"};\n return [ msg, null, null ];\n\n case \"EB3A4\":\n msg = { payload: \"ON\",topic:\"cmnd/DeskLight/power\"};\n return [ msg, null, null ];\n\n case \"6B3A4\":\n msg = { payload: \"OFF\",topic:\"cmnd/DeskLight/power\"};\n return [ msg, null, null ];\n\n case \"D3A4\":\n msg = { payload: \"ON\",topic:\"cmnd/studioheat/power\"};\n return [ msg, null, null ];\n\n case \"8D3A4\":\n msg = { payload: \"OFF\",topic:\"cmnd/studioheat/power\"};\n return [ msg, null, null ];\n\n\n // Home Assistant Call Service, Turn_on \n //FIOS 6\n case \"D93A4\":\n msg.payload= {\"data\":{\"entity_id\":\"switch.fios_6\"}};\n\t return [ null, msg, null ];\n //FIOS 0\n case \"593A4\":\n msg.payload= {\"data\":{\"entity_id\":\"switch.fios_0\"}};\n\t return [ null, msg, null ];\n //FIOS 3\n case \"393A4\":\n msg.payload= {\"data\":{\"entity_id\":\"switch.fios_3\"}};\n\t return [ null, msg, null ];\n\n\n}\nreturn \"\";\n","outputs":3,"noerr":0,"x":450,"y":280,"wires":[["60705f51.0fb36"],["27cfafaf.92275"],[]]},{"id":"d3d713fd.65f78","type":"inject","z":"4820e6f6.309498","name":"FIOS 6","topic":"","payload":"D93A4","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":340,"wires":[["808b664a.f9b3a8"]]},{"id":"27cfafaf.92275","type":"api-call-service","z":"4820e6f6.309498","name":"","server":"1a3c51f6.4b493e","service_domain":"homeassistant","service":"turn_on","data":"","mergecontext":"","x":920,"y":300,"wires":[[]]},{"id":"2f4e8c8e.f3c3c4","type":"inject","z":"4820e6f6.309498","name":"FIOS 0","topic":"","payload":"593A4","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":380,"wires":[["808b664a.f9b3a8"]]},{"id":"47384cba.c02e74","type":"inject","z":"4820e6f6.309498","name":"FIOS 3","topic":"","payload":"393A4","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":420,"wires":[["808b664a.f9b3a8"]]},{"id":"a5f4b39c.527e6","type":"mqtt-broker","z":"","name":"Marvin","broker":"192.168.1.124","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"1a3c51f6.4b493e","type":"server","z":"","name":"Home Assistant- Raspberry","url":"http://localhost:8123","pass":"raspberry"}]

Since I can't tell which node you are using please copy/paste the readme or info panel for the node here so we can see what it says about passing the data.

Further to this, do you mean you know what you need to put in the payload but don't know how to do it, or you believe you are setting up the payload correctly (and have checked in a debug node that it looks right) but that is not having the right effect in the HA node?

It's basically, string, string, object:

I can make the object OK, but when I try to put payload.domain and payload.service into the message, the node complains that those variables are missing.

If I put this into a function, the node works just fine:

msg.topic="";
msg.payload.domain="homeassistant";
msg.payload.service="turn_on";
msg.payload.data={"entity_id":"switch.fios_6"}
return msg;

This is the result:

HA-Dbg

When I put the same logic in my function where I decide what to do with an incoming IR-Code, the domain and service data are missing and I get an error from the HA Call Service node:

HA-dbg2

It might be easier to see whats going wrong if you post the function thats not working rather than the function that is working.

Agreed... The problem is in the last three case statements.

// This function routes the incoming MQTT messages containing an IR Code.
// Output 1 goes to an MQTT-Out node.
// Output 2 goes to a Home Assistant Call Service node for turn_on
// Output 3 goes to a Home Assistant Call Service node for turn_off

var payload=msg.payload;
switch (payload){
    // MQTT outputs
    case "A93A4":
        msg = { payload: "TOGGLE",topic:"sidetable/light/cmnd/power"};
        return [ msg, null, null ];
    case "333A2":
        msg = { payload: "ON",topic:"sidetable/light/cmnd/power"};
        return [ msg, null, null ];
    case "133A4":
        msg = { payload: "OFF",topic:"sidetable/light/cmnd/power"};
        return [ msg, null, null ];
    case "693A4":
        msg = { payload: "TOGGLE",topic:"cmnd/DeskLight/power"};
        return [ msg, null, null ];


    // Home Assistant Call Service, Turn_on (Second output)       
    //FIOS 6
    case "D93A4":
        msg.topic="";
        msg.payload.domain="homeassistant";
        msg.payload.service="turn_on";
        msg.payload.data={"entity_id":"switch.fios_6"}
       return [ null, msg, null ];
    //FIOS 0
    case "593A4":
        msg.topic="";
        msg.payload.domain="homeassistant";
        msg.payload.service="turn_on";
        msg.payload.data={"entity_id":"switch.fios_6"}
        return [ null, msg, null ];
    //FIOS 3
    case "393A4":
        msg.topic="";
        msg.payload.domain="homeassistant";
        msg.payload.service="turn_on";
        msg.payload.data={"entity_id":"switch.fios_6"}
        return [ null, msg, null ];
}
return ""

Put a debug node on the output of the function and see what it shows. Do the same with the function that works and see what that shows. If you can't see the difference then post them here.
My guess is that it is not executing the lines you think.

msg.payload isn't previously an object so you need to define it as one, eg:

case "D93A4":
        msg.topic="";
        msg.payload={domain:"homeassistant", service:"turn_on", data:{"entity_id":"switch.fios_6"}};
       
       return [ null, msg, null ];
1 Like

From above:

That was it. Many thanks.

@SteveMann can you share your flow? Please