ESP-01 bridge to Node-Red

This is my first Blynk post. I have learned so much and gotten lots of inspiration from the Blynk community. I am building a sump pump controller for dad’s basement. His house is next door, but outside WiFi. To keep things simple, I am trying to communicate with my Node-Red server over Blynk.

The ESP-01 is supposed to send relay status and water level to Node-Red. The Node-Red sends a heartbeat (because I am not aware of a Blynk feature like the last will in MQTT). When I first coded up the project, my first prototype was receiving all the messages intended for four different boards. Yes, he has four sump pumps. But that’s a different story.

Now Node-Red errors with DEVICE_NOT_IN_NETWORK, and the board never receives a message. Plus, Node-Red has never received a message from the board.

I have triple-checked my auth codes and my code. But I must still be overlooking something. Node-Red gets messages from other boards, and this board is communicating through the app just fine.

This picture shows my Node Red.


Here is my Node-Red code. I don’t think my sump pump id’s are critical, but I removed my Node-Red auth code.

    [
    {
        "id": "c6abd061.05636",
        "type": "tab",
        "label": "Sump pumps",
        "disabled": false,
        "info": ""
    },
    {
        "id": "b3d9883d.a6914",
        "type": "blynk-ws-out-bridge",
        "z": "c6abd061.05636",
        "name": "Pump - Patio II",
        "key": "BgdeAUE47G_w6swFEPE2laSHDYyTca-u",
        "bpin": "50",
        "pin": "2",
        "pinmode": 0,
        "pintype": "vw",
        "client": "4776450b.c68af4",
        "x": 600,
        "y": 360,
        "wires": []
    },
    {
        "id": "598a0a6e.129634",
        "type": "blynk-ws-in-read",
        "z": "c6abd061.05636",
        "name": "Sump - Northeast - Level - V10",
        "pin": "10",
        "pin_all": false,
        "client": "4776450b.c68af4",
        "x": 150,
        "y": 40,
        "wires": [
            [
                "b0668e1c.a519d"
            ]
        ]
    },
    {
        "id": "ab6f49f3.9084a",
        "type": "blynk-ws-in-read",
        "z": "c6abd061.05636",
        "name": "Sump - Northeast - Pump - V11",
        "pin": "11",
        "pin_all": false,
        "client": "4776450b.c68af4",
        "x": 150,
        "y": 80,
        "wires": [
            [
                "b0668e1c.a519d"
            ]
        ]
    },
    {
        "id": "3c847281.87206e",
        "type": "blynk-ws-in-read",
        "z": "c6abd061.05636",
        "name": "Sump - Bathroom - Level - V12",
        "pin": "12",
        "pin_all": false,
        "client": "4776450b.c68af4",
        "x": 150,
        "y": 120,
        "wires": [
            [
                "b0668e1c.a519d"
            ]
        ]
    },
    {
        "id": "b1e39ffe.8ac878",
        "type": "blynk-ws-in-read",
        "z": "c6abd061.05636",
        "name": "Sump - Bathroom - Pump - V13",
        "pin": "13",
        "pin_all": false,
        "client": "4776450b.c68af4",
        "x": 150,
        "y": 160,
        "wires": [
            [
                "b0668e1c.a519d"
            ]
        ]
    },
    {
        "id": "88a4169f.904448",
        "type": "blynk-ws-in-read",
        "z": "c6abd061.05636",
        "name": "Sump - Patio - Level - V14",
        "pin": "14",
        "pin_all": false,
        "client": "4776450b.c68af4",
        "x": 130,
        "y": 200,
        "wires": [
            [
                "b0668e1c.a519d"
            ]
        ]
    },
    {
        "id": "fd3d771c.231128",
        "type": "blynk-ws-in-read",
        "z": "c6abd061.05636",
        "name": "Sump - Patio - Pump - V15",
        "pin": "15",
        "pin_all": false,
        "client": "4776450b.c68af4",
        "x": 130,
        "y": 240,
        "wires": [
            [
                "b0668e1c.a519d"
            ]
        ]
    },
    {
        "id": "4d66a70e.ae2138",
        "type": "blynk-ws-in-read",
        "z": "c6abd061.05636",
        "name": "Pump - Patio - Pump II - V16",
        "pin": "16",
        "pin_all": false,
        "client": "4776450b.c68af4",
        "x": 140,
        "y": 280,
        "wires": [
            [
                "b0668e1c.a519d"
            ]
        ]
    },
    {
        "id": "47351e14.379bd",
        "type": "blynk-ws-out-bridge",
        "z": "c6abd061.05636",
        "name": "Sump - Northeast",
        "key": "eRllCRmf14MV0JdaOePTqENXnGkYUG4H",
        "bpin": "50",
        "pin": "2",
        "pinmode": 0,
        "pintype": "vw",
        "client": "4776450b.c68af4",
        "x": 610,
        "y": 480,
        "wires": []
    },
    {
        "id": "41b793b4.103af4",
        "type": "blynk-ws-out-bridge",
        "z": "c6abd061.05636",
        "name": "Sump - Bathroom",
        "key": "IfDtcnJkmvCA3_QVe05J6S24NeIbgHWX",
        "bpin": "50",
        "pin": "2",
        "pinmode": 0,
        "pintype": "vw",
        "client": "4776450b.c68af4",
        "x": 610,
        "y": 440,
        "wires": []
    },
    {
        "id": "113e3eea.507219",
        "type": "blynk-ws-out-bridge",
        "z": "c6abd061.05636",
        "name": "Sump - Patio",
        "key": "N0qQQrIL9mJ7ESgqA9aH7h6baDpDUdU6",
        "bpin": "50",
        "pin": "2",
        "pinmode": 0,
        "pintype": "vw",
        "client": "4776450b.c68af4",
        "x": 590,
        "y": 400,
        "wires": []
    },
    {
        "id": "8b7d5fd6.b53298",
        "type": "inject",
        "z": "c6abd061.05636",
        "name": "Node Red heartbeat - 1 min",
        "topic": "",
        "payload": "true",
        "payloadType": "bool",
        "repeat": "60",
        "crontab": "",
        "once": true,
        "onceDelay": ".1",
        "x": 240,
        "y": 420,
        "wires": [
            [
                "b3d9883d.a6914",
                "113e3eea.507219",
                "41b793b4.103af4",
                "47351e14.379bd"
            ]
        ]
    },
    {
        "id": "b0668e1c.a519d",
        "type": "debug",
        "z": "c6abd061.05636",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 480,
        "y": 80,
        "wires": []
    },
    {
        "id": "4776450b.c68af4",
        "type": "blynk-ws-client",
        "z": "",
        "name": "Home",
        "path": "ws://blynk-cloud.com/websockets",
        "key": "nr",
        "dbg_all": false,
        "dbg_read": false,
        "dbg_write": false,
        "dbg_notify": false,
        "dbg_mail": false,
        "dbg_prop": false,
        "dbg_sync": false,
        "dbg_bridge": false,
        "dbg_low": true,
        "dbg_pins": "",
        "multi_cmd": false,
        "proxy_type": "no",
        "proxy_url": "",
        "enabled": true
    }
]

Here is my sketch:

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#define BLYNK_PRINT Serial
// device specific configuration 
static const bool dbg = true; // disables pins used for TX/RX and enable serial
//const char* Wssid = "Koch"; // fill in here your router or wifi SSID
//const char* Wpassword = "p"; // fill in here your router or wifi password
const char* Wssid = "KWest"; // fill in here your router or wifi SSID
const char* Wpassword = "p"; // fill in here your router or wifi password
//const char* netname = "Pump - Patio II";
//const char* auth = "BgdeAUE47G_w6swFEPE2laSHDYyTca-u";
//const char* netname = "Sump - Patio";
//const char* auth = "N0qQQrIL9mJ7ESgqA9aH7h6baDpDUdU6";
//const char* netname = "Sump - Bathroom";
//const char* auth = "IfDtcnJkmvCA3_QVe05J6S24NeIbgHWX";
const char* netname = "Sump - Northeast";
char auth[] = "eRllCRmf14MV0JdaOePTqENXnGkYUG4H";
// device group configuration
const int RELAYPIN1 = 0; // relay connected to  GPIO0
const int LevelSensorPin1 = 2; // 12 bits ADC pin 34 senses the voltage level of the waterlevel sensor (values 0 - 4095)
const int LevelSensorPin2 = 3;
const int LevelSensorPin3 = 1;
// blynk pins
const int VLevel = 0;
const int VRelay = 1;
const int VNodeRed = 2;
const int VBridge = 3;
// global variables
long uptime_ms = 0; // Current uptime in ms
static long ctlNodeRed; // Local ms when Node Red has control
int timer_wifi; // timer id for wifi connection management timer
int timer_blynk; // timer id for Blynk connection management timer
// global objects
BlynkTimer timer;
WiFiClient espClient;
//WidgetBridge bridge1(VBridge);

BLYNK_CONNECTED() {
  // Place the AuthToken of the second hardware here
  bridge1.setAuthToken("nr"); 
}

// onRly interprets commands based on default relay position
bool onRly(int id, bool set) {
static const bool onO = false; // relay is "on" when open
static const bool onC = true; // relay is "on" when closed

  bool val = true; // default return value
  
  // should the specified relay be "on" when it is closed?
  switch (id) {
    case RELAYPIN1:
      val = onO;
      break;
  }

  if (!val) set = !set; // flip the value if relay is "on" when open
  return set;
}
// pub sends data to Blynk
void pub(int VPin, int val){
  Serial.println("Publishing - id: " + String(VPin) + "; val: " + String(val));
//Serial.println("netname: " + String(netname) + " match: " + String(netname == "Sump - Northeast"));
  // send to app
  Blynk.virtualWrite(VPin, val);
  // translate to node red pins
  if (netname == "Pump - Patio II"){
    if (VPin == VRelay) VPin = 16;
  }else if (netname == "Sump - Patio"){
    if (VPin == VRelay) VPin = 15;
    if (VPin == VLevel) VPin = 14;
  }else if (netname == "Sump - Bathroom"){
    if (VPin == VRelay) VPin = 13;
    if (VPin == VLevel) VPin = 12;
  }else if (netname == "Sump - Northeast"){
    if (VPin == VRelay) VPin = 11;
    if (VPin == VLevel) VPin = 10;
  }
  // send to node red
  bridge1.virtualWrite(VPin, val);
  Serial.println("To node red - pin: " + String(VPin) + ", val: " + String(val));
}
// relayCtl controls relays and publishes results; returns true for success, false for fail
bool relayCtl(int id, bool set) {
  static bool startup;
  if (!startup){
    pinMode(RELAYPIN1, OUTPUT);
    digitalWrite(RELAYPIN1, !onRly(RELAYPIN1, false)); // Relays are active LOW, so invert signal
    startup = true;
  }
  Serial.println("relayCtl: " + String(id) + " - " + String(set));
  bool ret = false; // defaults to operation failed
  String smsg = "";
//  Serial.println("id: " + String(id) + " and RELAYPIN1: " + String(RELAYPIN1) + ": " + String(id == RELAYPIN1));
  // Accept only these pins for relays
  if (!(id == RELAYPIN1)) return false;
  
  digitalWrite(id, !(onRly(id, set))); // Write the value; our relays needs HIGH (true) when off (false)
  // Check the value
  ret = !(onRly(id, digitalRead(id)));
//  Serial.println("Raw relay id " + String(id) + ": " + String(digitalRead(id)));
  // Publish the result
  if (id == RELAYPIN1) {
    Serial.print(F("Changing relay one to "));
  }

  // Return success or not
  if (set) smsg += "on"; else smsg += "off";
  if (set == ret) {
    smsg += ": ok";
  }
  else {
    smsg += ": failed, set to ";
    smsg += ret ? "on" : "off";
  }
  Serial.println(smsg);
  id = VRelay;
  pub(id, ret);
  
  return ret;
}

 BLYNK_WRITE_DEFAULT() { // commands from web
  int id = request.pin; // determines what vPin is triggering this response
  bool rslt;
  BLYNK_LOG("BLYNK_WRITE_DEFAULT(%u) - %s", request.pin, param.asStr()); // using 'id' variable didn't work
  if (id == VRelay) id = RELAYPIN1;
  relayCtl(id, (bool) param.asInt()); // controls local relays & publishes result
  if (id == VNodeRed) {
    ctlNodeRed = uptime_ms;
    Serial.println("Node Red heartbeat at: " + String(ctlNodeRed));
  }
  delay(1);
}
// If connected to wifi and Blynk not connected, con_blynk attemtps to connect to blynk once; returns true if connected
void con_blynk(void) {
  // first run?
  static bool startup;

  if (!startup){
    // set up timer
    timer_blynk = timer.setInterval(2000L, con_blynk);
    startup = true;
  }
  // stop if no wifi
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print(F("Blynk: no wifi"));
    return;
  } else if (!Blynk.connected()) {
    Serial.println("*** Connecting to Blynk server... ***");
    Blynk.config(auth);
    Blynk.connect();
    delay(100);
    if (Blynk.connected()){
      Serial.println(F("Blynk: Connected"));
      timer.disable(timer_blynk);
    }else{
      Serial.println(F("Blynk: Connect failed"));
      timer.enable(timer_blynk);
    }
  }
 
}
// If not connected to wifi, attempts to connect to wifi for a few seconds; returns true if connected
void setup_wifi(void) {
  // Serial message builder string
  String smsg = "";
  // first run?
  static bool startup;

  if (!startup){
    // setup the timer
    // check Wifi every minute
    timer_wifi = timer.setInterval(60000L, setup_wifi);
    startup = true;
  }
  // Wifi not connected? proceed.
  if (WiFi.status() != WL_CONNECTED) {
    delay(10);
    smsg = "\r\nConnecting to ";
    smsg += Wssid;
    Serial.print(smsg);
    smsg = "";
//    WiFi.config(ipAddy, ipDNS, ipGwy, ipMask);
    WiFi.begin(Wssid, Wpassword);

    // try to connect for a few seconds
    for (uint8_t i = 0; i < 30; i++){
    if (WiFi.status() == WL_CONNECTED) break;
    delay(500);
    Serial.print(".");
    }

    // Report results
    if (WiFi.status() == WL_CONNECTED) {
      smsg = "\r\nWiFi connected - ESP IP address: ";
      smsg += WiFi.localIP().toString();
      smsg += "\r\n";
      // launch the timer
      timer.disable(timer_wifi);
    } else {
      smsg = "\r\nWiFi connection failed";
      // disable the timer
      timer.enable(timer_wifi);  
    }
  Serial.println(smsg);
  }
  
}  

int MeasureLevel(void)  {
  static bool startup;
  if (!startup){
    pinMode(LevelSensorPin1, INPUT_PULLUP);               // Initializes the water level sensorpin
    if (!dbg) {
      pinMode(LevelSensorPin2, INPUT_PULLUP);
      pinMode(LevelSensorPin3, INPUT_PULLUP);
    }
    startup = true;
  }
  int level = 0;                                  // Variable of the WaterLevel
    
  if (dbg){
    Serial.println("Digital pin " + String(LevelSensorPin1) + ": " + String(digitalRead(LevelSensorPin1)));
//  Can't see these when debug is off and can't read them when debug is on
//    Serial.println("Digital pin " + String(LevelSensorPin2) + ": " + String(digitalRead(LevelSensorPin2)));
//    Serial.println("Digital pin " + String(LevelSensorPin3) + ": " + String(digitalRead(LevelSensorPin3)));
    if (!digitalRead(LevelSensorPin1)) level = 1;
  }else{
    if (!digitalRead(LevelSensorPin3)){
      level = 3;
    }else if (!digitalRead(LevelSensorPin2)){
      level = 2;
    }else if (!digitalRead(LevelSensorPin1)){
      level = 1;
    } 
  }
  pub(VLevel, level);
  return level;
  }

void setup() {
  if (dbg) Serial.begin(115200);; // must be same baudrate with the Serial Monitor
  Serial.println("");
  Serial.println("Hello!");
}
 
void loop() {
  static long lastMeasure = 0;
  const long interval = 15000; // XX,000 sec,000
  int level; // current measured water level
  bool rslt;

  uptime_ms = millis();
  if ((uptime_ms - lastMeasure > interval) || (lastMeasure < 2)) {
    Serial.println(uptime_ms);
    // Monitor level
    level = MeasureLevel();
    // Relay decision
    if (((uptime_ms - ctlNodeRed) > (1.25*60*1000)) || (ctlNodeRed == 0)) { /* skip if node red heartbeat received less than 1.25 min ago */
      // on if one or more; otherwise, off
      rslt = relayCtl(RELAYPIN1, (level >= 1));
      Serial.println("Relay locally set to: " + String(rslt));
    }else{
      Serial.println("Relay controlled by Node Red.");
    }
    // try wifi and blink. If connected, re-run
  setup_wifi();
  con_blynk();
  if  ((WiFi.status() == WL_CONNECTED) && (Blynk.connected())){
      if (lastMeasure == 0){
        // shows inital setup ok, forces re-run
        lastMeasure = 1;
      }else if (lastMeasure == 1){
        // stops setup loops
        lastMeasure = 2;
      }else{
        lastMeasure = uptime_ms;
      }
    }else{
      lastMeasure = uptime_ms;
    }
  }
  //  Run Blynk
  if (WiFi.status() == WL_CONNECTED) Blynk.run();
  // run timers
  timer.run();
}

I’ve never come across the “DEVICE_NOT_IN_NETWORK” message in Node-Red, but I never bother using the Bridge node either and I guess that’s where it’s coming from.

Instead of Bridge nodes, why don’t you just use Blynk write nodes to the 4 different devices?

Also, I rarely ever use Blynk code on my devices, i just use MQTT and handle the Blynk stuff in Node-Red. I guess that your dad’s lack of WiFi connectivity to your network is the reason for this, but I think I’d use service like NoIP to allow you to send MQTT data to your server and back rather than using Blynk.

Pete.

Thanks for the quick reply, sir. I’ve been a fan of your blog and your demonstrations helped me grasp the capabilities of this technology.

I overlooked that I was using read nodes. When I changed to write nodes, the input side started working. But I understand that you were talking about the bridge nodes.

For the bridges, I’m not sure what happened. I turned on all the debug options for the config node. I also tried changing the virtual port on node red. All of a sudden it started working and still is with the debug options off.

It does appear that DEVICE_NOT_IN_NETWORK may appear when the device has never connected to the network after being newly created.

1 Like