How to access MQTT topic/status in Function if(topic/status =

Hi,
I’m new to HA, migrating from OpenHAB, I have MQTT and many other integrations working.
Using Nodered (NR) my AC Heater turns on based on Solar panel output value. AC heater is operated via a Tuya IR blaster. Solar output value and AC heating status is stored in MQTT.

The issue is the automation sends a signal to the AC regardless of the AC’s current setting (to be expected). So if AC is ON, solar says it should be ON, it turns is ON (again). This occurs based on the poll interval of the solar output test (currently 1 min.).
The real issue is the AC beeps everytime it receives an IR signal (1 minute) LOL. Houshold is getting annoyed at the regular beeping (no surprise).

How can you check a MQTT topic\value from within a function. I’ve not been able to find any examples of this. e.g.

if (topic/HeaterState == “on” && topic/SolarOutput >= 900)
{
return “off”;
}

I fiddled with a boolean function but could not get the correct results for one state. So I’ve reverted to a simple IF to get a solution in, keep the house happy.

Any suggestions would be greatly apprecaited, I’m sure it’s a common problem.

Have a separate flow that listens to the MQTT topic and stores the value in a flow or global context then check that value in the function node.

https://nodered.org/docs/user-guide/context

Many thanks, gave that a go, getting values in is ok.
image

Using a 4 output function, with this code.
image

var msg1 = {payload:‘1’};
var msg2 = {payload:‘2’};
var msg3 = {payload:‘3’};
var msg4 = {payload:‘4’};

if ((flow.SolarOutput >= 900) && (flow.AC_Heater == ‘false’ )) {
msg1 = {payload:‘ON’};
};

if (( flow.SolarOutput >= 900) && (flow.AC_Heater == ‘true’)) {
msg2 = {payload:‘xx’};
};

if (( flow.SolarOutput < 900) && (flow.AC_Heater == ‘false’)) {
msg3 = {payload:‘xx’};
};

if (( flow.SolarOutput < 900) && (flow.AC_Heater == ‘true’)) {
msg4 = {payload:‘OFF’};
};
return [msg1, msg2, msg3, msg4];

I’ve missed something, as the function just passes the trigger time, and seems to ignore the if statement !
Any suggestions or examples would be very welcome.

Apologies for the newbie question.

https://nodered.org/docs/user-guide/writing-functions#storing-data

Thanks, read a few times ( even before the suggestion) but nothing really caught my attention.

The flow variable should be good for the entire flow as its set up front, and just referred to.

You need to use flow.get("variable name") to get a flow variable inside a function node. Is the value of AC_Heater a string or boolean? As you have it, it’s comparing strings.

let msg1 = { payload: "1" };
let msg2 = { payload: "2" };
let msg3 = { payload: "3" };
let msg4 = { payload: "4" };

const solarOutput = flow.get("SolarOutput");
const acHeater = flow.get("AC_Heater");

if (solarOutput >= 900) {
  if (acHeater == "false") {
    msg1 = { payload: "ON" };
  } else if (acHeater == "true") {
    msg2 = { payload: "xx" };
  }
} else if (solarOutput < 900) {
  if (acHeater == "false") {
    msg3 = { payload: "xx" };
  } else if (acHeater == "true") {
    msg4 = { payload: "OFF" };
  }
}

return [msg1, msg2, msg3, msg4];

Many thanks,
“You need to use flow.get("variable name") to get a flow variable inside a function node.” Thats the bit I was missing.

Your IF is way more elegant than mine.
Thanks for the AC_Heater point, it is a boolean

Many thanks for taking the time to help, it is greatly appreciated.

After the function there is a HA service node that triggers a scene in Tuya to control the AC.
While the function correctly sends on/off based on input. Both service nodes receive input, which causes them to trigger together. As msg.payload always has a value.

How can you set msg.payload to no value/content so there is no output, so it wont trigger both service node.
or is there a better way to do this.

With the current setup sending null in place of a message will stop the function node from outputting on that output.

const solarOutput = flow.get("SolarOutput");
const acHeater = flow.get("AC_Heater");

if (solarOutput >= 900) {
  if (acHeater == "false") {
      msg.payload = "ON";
      return [msg];
  } else if (acHeater == "true") {
    msg.payload = "xx";
    return [null, msg];
  }
} else {
  if (acHeater == "false") {
    msg.payload = "xx";
    return [null, null, msg];
  } else if (acHeater == "true") {
    msg.payload = "OFF";
    return [null, null, null, msg];
  }
}

The call-service node accepts config parameters via the input. https://zachowj.github.io/node-red-contrib-home-assistant-websocket/node/call-service.html#input

So a better approach would be to form that payload in the function and send that out to a single call-service node.

image

const solarOutput = flow.get("SolarOutput");
const acHeater = flow.get("AC_Heater");

if (solarOutput >= 900) {
  if (acHeater === false) {
      msg.payload = {
        domain: "scene",
        service: "turn_on",
        target: {
          entity_id: scene.ac
        }
      }
  } else {
    msg.payload = "xx";
  }
} else {
  if (acHeater === false) {
    msg.payload = "xx";
  } else {
    msg.payload = {
      domain: "scene",
      service: "turn_on",
      target: {
        entity_id: scene.ac
      }
    }
  }
}

return msg;

Moving from a single return, to one after each check is a great idea.

I consolidated the function into 2 outputs, but could not see how to do it into a single. A single output to service call is great.

Many thanks for taking the time and making the effort to help.