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();
}