BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

Blynk - MQTT Bridge - Use Blynk app for non-Blynk devices

#1

Well, not all my devices run on Blynk. Most run on Tasmota or other software I developed. Also particularly Tasmota leaves no memory to include Blynk library on an ESP8266.
My wife likes the ease of use of the Blynk App despite its old fashioned design (I will suggest to the developer team to create some different and more exciting skins).
To combine the two requirements I run a Wemos D1 mini board to run Blynk for my non-Blynk devices. It communicates with the controlled devices through MQTT. Now I can power on or dim a light or change the scheme etc. with the Blynk GUI.
At the same time I can still operate these devices with Domoticz and other means.

My program operates as the GUI for one Arilux-LC01 and two ESP01s. As the Wemos has 127 virtual pins you may add more devices.

Arilux-LC01:
Video

Photo of Blynk App:

Program:

 Blynk to MQTT bridge
 Version 1.0     9. Feb 2018

 Funtion: Use Blynk GUI to control MQTT attached devices
 
Pin assignments:
* Wemos D1 mini

Blynk Virtual Pins: 127 pins available
1. Kitchen Top control (Arilux LC01 running Tasmota)
V0: ON OFF Button 
V1: Dimmer slider
V2: Speed slider
V3: Color select
V4: Fade switch
V5: Scheme slider

2. Kitchen top high (ESP01 running Tasmota)
V6: ON OFF Button upper row lights

3. Kitchen top low (ESP01 running Tasmota)
V7: ON OFF Button lower row lights

4. For own purposes
V13: ON OFF LED
V14: UP LED

Bill of material:
 -Wemos D1 mini
 -1000uF capacitor (I found that a capacitor around 5V and Ground increases stability of the Wemos D1)
 -5V 750mA Power Supply
*/

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

// Set ESP8266 Serial object
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
SimpleTimer timer;

// Blynk
//#define BLYNK_DEBUG
//#define BLYNK_PRINT Serial
int ONOFF_LED = V13;
int UP_LED = V14;
long int last_UP_change = millis();
bool runn = 1;
bool lamp_on;
bool lamp23_on;
bool lamp24_on;
int brightness;
int current_activity;
int standard_speed;
int counter = 0;

// Wireless settings
const char AUTH[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char SSID[] = "mmwireless"; 
const char PASSWORD[] = "xxxxxxxxxx";
IPAddress mqtt_server(192,168,178,59);
const char* mqtt_username = "mqtt";
const char* mqtt_password = "xxxx";
char* InTopic = "tele/arilux74/STATE"; //subscribe to topic to be notified about
char* InTopic1 = "tele/ESP23/STATE";
WiFiClient espClient;
PubSubClient client(espClient);


void setup() {
Serial.begin(115200);
Serial.println(F("setup start"));

//Blynk
WiFi.mode(WIFI_STA);
Blynk.begin(AUTH, SSID, PASSWORD,"192.168.178.59",8442);
  while (Blynk.connect() == false) {  // Wait until connected
    if ((millis() - last_UP_change) > 30000) { // 30s before reset
      Serial.println(F("resetting"));
      ESP.restart();
   }
 }
wait(10);
client.setServer(mqtt_server, 8883);
client.setCallback(callback);

//OTA
 // Port defaults to 8266
 // ArduinoOTA.setPort(8266);
 // Hostname defaults to esp8266-[ChipID]
 ArduinoOTA.setHostname("D1-MQTT_Bridge");
 // No authentication by default
 ArduinoOTA.setPassword((const char *)"xxx");
 ArduinoOTA.onStart([]() {
   Serial.println("Start");
 });
 ArduinoOTA.onEnd([]() {
   Serial.println("\nEnd");
 });
 ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
   Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
 });
 ArduinoOTA.onError([](ota_error_t error) {
   Serial.printf("Error[%u]: ", error);
   if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
   else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
   else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
   else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
   else if (error == OTA_END_ERROR) Serial.println("End Failed");
 });
 ArduinoOTA.begin();

 Serial.println(F("Entering loop"));
 wait(200);
 timer.setInterval(2003L, blinkonoff);
 Blynk.virtualWrite(ONOFF_LED,0); 
 Blynk.virtualWrite(UP_LED,0); 
}


void loop() {
 Blynk.run();
 if(!Blynk.connected()) {
   Serial.println(F("Resetting in loop"));
   ESP.restart();
 }
 timer.run();
 if (!client.connected()) {
   reconnect();
  }
 client.loop();
 ArduinoOTA.handle();
}


void wait (int ms) {
 long current_time = millis();
 long end_time = current_time + ms; 
 while (current_time < end_time) {
   current_time = millis();
 }
}


void blinkonoff(){
// Turn runn LED on/off
  Blynk.virtualWrite(UP_LED,runn * 255);  // turn Up off
  runn = !runn;
  last_UP_change = millis();  
}

BLYNK_WRITE(V0) { //ON Off switch
   if (param.asInt()) {
     client.publish("cmnd/arilux74/power","1");
     lamp_on = 1;
   }
   else {
     client.publish("cmnd/arilux74/power","0");
     lamp_on = 0;
   }
   Blynk.virtualWrite(ONOFF_LED,lamp_on * 255);  
}

BLYNK_WRITE(V1) { // Dimmer 0-100
   brightness = param.asInt();
   char bright[4];
   dtostrf(brightness, 3, 0, bright);
   client.publish("cmnd/arilux74/Dimmer",bright);
}

BLYNK_WRITE(V2) { // Speed 0-100
 standard_speed = param.asInt();
 char speed[4];
 dtostrf(standard_speed, 3, 0, speed);
 client.publish("cmnd/arilux74/speed",speed);
}

BLYNK_WRITE(V3) { //Color select 0-255 each
  char hex[7] = {0};
  sprintf(hex,"%02X%02X%02X",param[0].asInt(),param[1].asInt(),param[2].asInt()); //convert to an hexadecimal string. Lookup sprintf for what %02X means.
  client.publish("cmnd/arilux74/color",hex);
}

BLYNK_WRITE(V4) { // Fade switch
   if (param.asInt()) client.publish("cmnd/arilux74/fade","1");
   else client.publish("cmnd/arilux74/fade","0");
}

BLYNK_WRITE(V5) { //Scheme slider 0-4
  current_activity = param.asInt();
  char activity[2];
  dtostrf(current_activity, 1, 0, activity);
  client.publish("cmnd/arilux74/scheme",activity);
}


BLYNK_WRITE(V6) { //ON Off upper lights
   if (param.asInt()) {
     client.publish("cmnd/ESP23/power","1");
     lamp23_on = 1;
   }
   else {
     client.publish("cmnd/ESP23/power","0");
     lamp23_on = 0;
   }
}


BLYNK_WRITE(V7) { //ON Off lower lights
   if (param.asInt()) {
     client.publish("cmnd/ESP24/power","1");
     lamp24_on = 1;
   }
   else {
     client.publish("cmnd/ESP24/power","0");
     lamp24_on = 0;
   }
}


void reconnect() {
 // Loop until we're reconnected
 while (!client.connected()) {
   Serial.print("Attempting MQTT connection...");
   // Attempt to connect
   if (client.connect("BlinkMQTTBridge",mqtt_username,mqtt_password)) {
     Serial.println("connected");
     counter = 0;
     // ... and resubscribe
     client.subscribe(InTopic);
     client.subscribe(InTopic1);
   } else {
     Serial.print("failed, rc=");
     Serial.print(client.state());
     Serial.println(" try again in 0.3 second");
     ++counter;
     if (counter > 180) ESP.reset();
     // Wait .3 seconds before retrying
     delay(300);
   }
 }
}

void callback(char* topic, byte* payload, unsigned int length) {
 StaticJsonBuffer<450> jsonBuffer;
 //const char* json = "{"Time":"2018-02-09T14:55:30","Uptime":1,"Vcc":3.180,"POWER":"ON","Dimmer":73,"Color":"BA3E00","Scheme":0,"Fade":"OFF","Speed":1,"LedTable":"OFF","Wifi":{"AP":1,"SSId":"mmwireless","RSSI":66,"APMac":"0E:41:58:01:03:F0"}}";
 JsonObject& root = jsonBuffer.parseObject((char*)payload);
 const char* Time = root["Time"]; // "2018-02-09T14:55:30"
 int Uptime = root["Uptime"]; // 1
 float Vcc = root["Vcc"]; // 3.18
 const char* POWER = root["POWER"]; // "ON"
 int Dimmer = root["Dimmer"]; // 73
 const char* Color = root["Color"]; // "BA3E00"
 int Scheme = root["Scheme"]; // 0
 const char* Fade = root["Fade"]; // "OFF"
 int Speed = root["Speed"]; // 1

 //here you can use this information (optional)
} ```
4 Likes

SonOff T1 Uk Relais switch
How to use TASMOTA inside BLYNK and HOME ASSISTANT [Work in Progress]
Hacking the new ITEAD Studio - Sonoff S31
How to use TASMOTA inside BLYNK and HOME ASSISTANT [Work in Progress]
#2

Kind of hardware bridge. Nice!

0 Likes

#3

Interesting.
I use MQTT to control my devices but I use an RPI and Node-Red in my setup, but I’d wondered about the possibility of a more “lightweight” setup using a Wemos as a the controller.
It opens-up a different way to deploy a simple solution in a new location, which could be very handy.

I notice that you don’t have any debounce code on your button widgets - doesn’t this cause you a problem?

Pete.

0 Likes

#4

How in the name of physics does a virtual button “bounce”? And how would you "debounce’ it anyhow?

0 Likes

#5

Well, I guess i mean a virtual bounce :wink:
Tapping a switch widget connected to a virtual pin sometimes gives me the equivalent of a switch bounce in Node-Red, so I have to do a bit of debouncing to desentise the button.
I guess it may be a quirk of how Node-Red integrates with Blynk, and I don’t currently use any devices that run Blink in the ‘normal’ way, hence my interest in whether this is an issue when using this system.

Pete.

0 Likes

#6

@PeteKnight, I guess this may be due to some unwanted (or improperly handled) feedback. I had it once, exactly when combining Blynk with MQTT using Node-red. You may want to check your flows…

1 Like

#7

I see… unless the Button Widget is set to SWITCH mode, then each and every tap WILL provide two states 1 & 0 in quick succession… the BLYNK_WRITE() functions recognise that and it can be used to differentiate options or “debounced” to ignore one or the other state.

BLYNK_WRITE(vPin) {
  if (param.asInt()) { // Check state of button as integer
    // Do something here if State is 1
  }
  else {
    // Do something here if State is 0
  }
}
1 Like

#8

Yes, it’s easy to get into a loop like that, depending on how you structure the flows.
Even taking care not to get into that sort of situation, I still get the odd bounce issue - but it’s easy enough to deal with once you realise what’s happening.

Pete.

1 Like