Pass integer or float to Node red

Trying to figure out Node Red (maybe I’ll come over to the dark side @PeteKnight haha!).

So I got the notify working with what I could find online. I also got a write node to send a 1 or a 0 from virtual pin 20 button. However I can’t find seem to find info on sending a value from say a variable called “temp” on a virtual pin 0.

So here is what I’m using right now. It works, but I’m wondering if there is some way to configure the write event to do this…

Repeating time stamp calls the http GET.

HTTP in settings…

Hi Dave, welcome to the dark side!

To trigger the Blynk server to send you the temperature reading from pin V0 you’ll need to add a Sync node attached to V0 and set to syncVirtual. This will then fire the Write Event node on pin V0.

Here I’ve setup a repeating Inject node to trigger the Sync every 5 seconds…

If you wanted to have some logic around when alerts are sent, and not send multiple alerts then you could do something like this:

image

You’d still need the timed sync process as well, I’ve just not included that in the screenshot.
The code in the “Alert Rules” function looks like this:

// initialise Flow level variable of msgSentFlag to false if it doesn't exist already
var msgSentFlag = flow.get('msgSentFlag')||false;

var upperTempLimit = 30 // The temperateure when over temperature alerts will be sent

if (msg.payload >= upperTempLimit && msgSentFlag===false)
{
    msg.payload = "Warning temperature is over target at " + msg.payload
    flow.set('msgSentFlag',true);  // set msgSentFlag to show that alert has been sent 
    return msg; // pass the message to the output of this node
}


if (msg.payload < upperTempLimit && msgSentFlag===true)
{
    msg.payload = "Temperature is now below target at " + msg.payload
    flow.set('msgSentFlag',false);  // un-set msgSentFlag so future alerts will be sent
    return msg; // pass the message to the output of this node 
}

A word of caution, I’ve not had my first coffee of the day yet, so this code may be total bollocks!

Pete.

Hey! It works! Of course :stuck_out_tongue_winking_eye:
So ever time you deploy again you have to click on the time input to get it going again or is there some code to plug in so it starts again every time?

Edit: My bad it looks like the timer is starting by itself. I think I just had the interval longer than I thought.

I guess I didn’t have enough coffee :grinning:

1 Like

I should also have said that I don’t use Blynk and Node-Red in this way.
In my setup, the only thing that talks to Blynk is Node-Red. No devices (NodeMCUs etc) talk direct to Blynk, they only talk to Node-Red and this is done via MQTT messages.

I realise that if you’re evaluating Node-Red then the way you are doing it makes sense, but in many ways this would have been an easier task if the temperature sensing device was sending its readings to Node-Red and the over-temperature logic was handled there, and the results just pushed out to Blynk for information and/or graphing in Superchart.
Node-Red could also push the data to other systems if desired. I send some data to Adafruit IO for example, and also to IFTTT to control some devices that I don’t have other ways to access their APIs.

Ya I get the concept of what your doing. This lock down probably ain’t long enough for me to learn mqtt :rofl::joy:. Blynk with NR this way is pretty much a user interface with a user interface.

If you have a device just running n 1 or 2 things you could PM me the code sometime and I could take a look at it to see if it’s something I can learn. I dnt have any idea of terminology to start googling even.

No problem, I’ll dig some code out in the next day or so.
I went down the route of a ‘bells and whistles’ code set that forms the basis for most of my current projects, but it’s a bit difficult to get your head around, so I’ll find some older code that’s more straightforward.

If you’ve used Blynk for a while then MQTT is pretty similar in many ways.
If your device Subscribes to a topic then it watches that topic and does something when it sees a new message. Very similar to a BLYNK_WRITE callback that triggers when a virtual pin value changes.

Writing to a topic is just like a Blynk.virtualWrite, and is your way of sending data from the device up to Node-Red. It can then be passed out to Blynk with a Write node and a few bits of spaghetti to join it all up.

I got very hung-up about what my MQTT topic structure should look like, but in the end it doesn’t really matter too much. If you structure things correctly then you could use one command to (let’s say) turn all the lights off in a room, but to be honest it’s not really much more difficult to write an ‘off’ command to multiple MQTT outputs at the same time anyway.

If you’re going to start playing with MQTT then I strongly recommend downloading a copy of MQTT Explorer, it will make life so much easier…

Pete.

1 Like

Hi Dave,
I thought I’d post the code here so that others can see/use it if they wish.

#include <PubSubClient.h>     // https://github.com/knolleary/pubsubclient
#include <ESP8266WiFi.h>
#include <SimpleTimer.h>

// Wi-Fi variables...
const char *ssid =                "REDACTED"; 
const char *pass =                "REDACTED";

// MQTT Server Setting variables...
IPAddress mqtt_server_ip          (192,168,xxx,xxx);                     // IP Address for the MQTT Server...
const int mqtt_port =             1883;                                  // Port for the MQTT Server...
const char* mqtt_username =       "REDACTED";                            // MQTT Server username...
const char* mqtt_password =       "REDACTED";                            // MQTT Server password...
String base_mqtt_topic =          "My_MQTT_Test/NodeMCU_Test_Device";    // Start of the MQTT Topic name used by this device
String mqtt_client_id;                                                   // Will hold unique ID, so use ChipID will be assigned in void setup


// Create instances of the Wi-Fi, MQTT and SimpleTimer objects...
WiFiClient My_WiFi_Client;
PubSubClient MQTTclient(My_WiFi_Client);
SimpleTimer timer;


void connect_to_Wifi()
{
  if (WiFi.status() != WL_CONNECTED)
  {
    Serial.print("Connecting to ");
    Serial.print(ssid);
    Serial.println("...");
    WiFi.begin(ssid, pass);

    if (WiFi.waitForConnectResult() != WL_CONNECTED)
    {
      return;
    }
    Serial.println("WiFi Connected");
  }  
  WiFi.mode(WIFI_STA);  
  Serial.print("IP Address = ");
  Serial.println(WiFi.localIP());
} 

void connect_to_MQTT()
{
  Serial.println("Connecting to MQTT...");
  if(MQTTclient.connect(mqtt_client_id.c_str(), mqtt_username, mqtt_password, (base_mqtt_topic + "/Status").c_str(),0, 1, "Dead"))
  {
    // We get here if the connection was successful... 
    Serial.println("MQTT Connected");
    // We can update the /Status topic to "Alive" now...   
    MQTTclient.publish((base_mqtt_topic + "/Status").c_str(),"Alive",true);
    
    // ... and then re/subscribe to the watched topics
    MQTTclient.subscribe((base_mqtt_topic + "/LED").c_str());   // Watch the .../LED topic for incoming MQTT messages
    // Add other watched topics in here...  <--------------------- THIS IS THE BIT THAT YOU'LL FORGET TO DO!!
    
  } 
  else
  {
    // We get here if the connection failed...   
    Serial.print(F("MQTT Connection FAILED, Return Code = "));
    Serial.println(MQTTclient.state());
    Serial.println(); 
    /*
    MQTTclient.state return code meanings...
    -4 : MQTT_CONNECTION_TIMEOUT - the server didn't respond within the keepalive time
    -3 : MQTT_CONNECTION_LOST - the network connection was broken
    -2 : MQTT_CONNECT_FAILED - the network connection failed
    -1 : MQTT_DISCONNECTED - the client is disconnected cleanly
     0 : MQTT_CONNECTED - the client is connected
     1 : MQTT_CONNECT_BAD_PROTOCOL - the server doesn't support the requested version of MQTT
     2 : MQTT_CONNECT_BAD_CLIENT_ID - the server rejected the client identifier
     3 : MQTT_CONNECT_UNAVAILABLE - the server was unable to accept the connection
     4 : MQTT_CONNECT_BAD_CREDENTIALS - the username/password were rejected
     5 : MQTT_CONNECT_UNAUTHORIZED - the client was not authorized to connect * 
     */
  }

}

void MQTTcallback(char* topic, byte* payload, unsigned int length)
{
  Serial.print(F("Message arrived ["));
  Serial.print(topic);
  Serial.print(F("] ["));
  for (int i=0;i<length;i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println(F("]"));    
  
  String msg_topic = String((char *)topic);
  String msg_payload = String((char *)payload);
  msg_payload.remove(length); // Trim any unwanted characters off the end of the string
  // We now have two string variables, 'msg_topic' and 'msg_payload' that we can use in 'if' statements below... 

  if (msg_topic==base_mqtt_topic + "/LED")
  {
    if (msg_payload == "ON")
    {
      digitalWrite (2,LOW);
    }
    else if (msg_payload == "OFF")
    {
      digitalWrite (2,HIGH);           
    }
  }

  // Handle messages from other topics in here,
  // DON'T FORGET to subscribe to the topic in void MQTT_Connect()

} // End of void MQTTcallback


void MQTT_Heartbeat()
{
    MQTTclient.publish((base_mqtt_topic + "/RSSI").c_str(),String(WiFi.RSSI()).c_str(),true);         // Publish RSSI
    MQTTclient.publish((base_mqtt_topic + "/Uptime").c_str(),String(millis()/1000).c_str(),true);     // Uptime in seconds     
}
  


void setup()
{
  Serial.begin(74880);
  pinMode(2,OUTPUT); // Internal LED on NodeMCU is connected to GPIO2 - Active LOW
  mqtt_client_id = String(ESP.getChipId());
  MQTTclient.setServer(mqtt_server_ip, mqtt_port);
  MQTTclient.setCallback(MQTTcallback);           // This function is called automatically whenever a message arrives on a subscribed topic
  connect_to_Wifi();
  connect_to_MQTT();
  timer.setInterval(5000, MQTT_Heartbeat);
}

void loop()
{
  if(WiFi.status() != WL_CONNECTED)
  {
  connect_to_Wifi();
  connect_to_MQTT();
  }  
  
  if (!MQTTclient.connected())     // Note that MQTTclient.connected() will still return 'true' until the MQTT keepalive timeout has expired (around 35 seconds for my setup) 
  {
  connect_to_MQTT();
  }
    
  timer.run();
  MQTTclient.loop();
}

I couldn’t find anything I liked from my old code, so I put this together from parts of my ‘bells and whistles’ code.
It does two things:

  • Pushes RSSI and Uptime data to out in MQTT messages every 5 seconds
  • Toggles the onboard LED on and off when it receives instructions via MQTT messages

This should give you the bare bones that can be used to push things like temperature and humidity data out as MQTT messages, and allow you to send MQTT instructions to the device as you would from any Blynk widget.

The code allows you to define the “base” MQTT topic structure for your device, which I’ve found works very well when you want to have a slightly different structure for each device you are running. It means you don’t have to do a lot of find and replace within the code.
In this example I’ve defined the base topic as “My_MQTT_Test/NodeMCU_Test_Device”. Think of the topics as being like a Windows folder structure and organise you devices in a similar way to how you might structure photos or documents within your folders.
This might be on a room by room basis if you’re doing home automation, but it’s up to you.
in MQTT explorer, the output looks like this:

image

The Status message uses something called “Last Will and Testament” and is a way of the device telling the MQTT server what to do when it dies. In this case it changes the “Status” topic to “Dead” and this change will occur about 40 seconds after the device drops off the servers radar.

Sending (Publishing) an MQTT message that will make the NodeMCU turn its built in LED on or off can be done from MQTT Explorer like this:

or in Node-Red like this:
image

The MQTT message body (Payload) has to be “ON” or “OFF” in uppercase - simply because that’s how I’ve coded it. You could easily change to 1 and 0, true and false etc. Going for 1 and 0 makes sense because you can then turn that string into an integer and use it directly in your digitalWrite command (although you have to ! (NOT) it because the LED is active LOW.

Some things to watch out for. If your messages start to get truncated (because you’ve gone OTT with the topic name structure) then you have to manually edit the PubSubClient.h file and increase the MQTT_MAX_PACKET_SIZE value.

If you want to add new topics that the device will watch for commands then it’s a two step process:

  • Add the logic to MQTTcallback
  • Subscribe to the topic once the MQTT connection is established. This is done in 1connect_to_MQTT` - This is the bit I always forget. Looking at the serial monitor when you’re trying to debug these problems is handy, because iot will tell you when a new message has arrived and what its contents is. If you don’t see the message then either you’re publishing to the wrong topic, or you haven’t subscribed to the topic.

PubSubClient uses character (char) variable types. I hate working with these (mostly because I don’t understand them, but also because most system variables or sensor data is in the form of strings or float/integers). This means you’ll see a lot of things like this: String(WiFi.RSSI()).c_str() where the RSSI value is turned into a String, then a character string.
I also take the char data that comes from the inbound MQTT messages and turn it into strings so that I can work with it more easily, like this:

  String msg_topic = String((char *)topic);
  String msg_payload = String((char *)payload);

I’m sure there are much better ways of doing this, but this old dog probably isn’t going to take them onboard!

The code looks quite bulky and daunting, but it’s a good basis for doing some testing, and it’s very easy to then add-in your own to send sensor data to the server and respond to commands on the topics that you’ve subscribed to.

Give me a shout if you have any problems or when you want to do more challenging stuff.

Pete.

1 Like

Wow thanks @PeteKnight ! Got it working. The RSSI and the uptime added example helped me figure out how things were put together.

I guess you still run a token on the device so you have access to the virtual pins on the app?

For others who will try it my gauges were going to zero whenever a “nan” came along so I put a function in line with the following code in it.

var temp = msg.payload
if (temp === "nan") {
   return [ null, msg ];
}
return msg;


This seems to work…

Great!

No, not at all. The only place the token goes is in the Node-Red connection setup. Data coming in to Node-Red is via a Write Event node and the payload is what you’d normally get as param.asInt() value. This is then translated into whatever I want to send to the device as an MQTT command. Obviously, as Blynk sends 0/1 from a switch widget by default then having your subscribed topic payload looking for a 1/0 as well means that you don’t have to do any translation in Node-Red.

Does this make sense?

Pete.

Ok that makes sense. At one point in my testing it seemed like I need a device on line with the active token, but after you said that I unplugged that device and the project is working.