Help With Integrating Wifi Manager into Sketch

Hello there!
I have looked through the internet in need of an interesting project and I came across a smartwatch designed by the YouTuber Technowright. It seemed like something I can do and all of the hardware and circuitry was easy enough for me to understand, however, I completely suck at software.
The software provided with the project was good, however, it required being connected to the internet at all times. That there is no problem for me, however, I needed to integrate the wifi manager library in order to be able to actually be able to productively use this watch, allowing me to become social and leave my house without my laptop and TTL adapters. However, since this isn’t originally my code and since I really am new to this style of programming I ran into some errors.

Most notably:
The compiler stops at the line

Blynk.begin(auth);

with the error

no matching function for call to 'BlynkWifi::begin(char [33])'

I have noticed a similar forum post but I didn’t understand how it would relate to my specific example.
Also please let me know if there is something else that I completely screwed up while trying to integrate wifi manager that hasn’t yet surfaced.

Thanks for taking a look!

Full code:

//  ESP8266_SmartWatch.ino
//  Written by Shyam Ravi, the Technowright -> this isn't me, if I could've written this code, I woud've been able to probably fix this issue.
//  Visit my Youtube channel at https://www.youtube.com/thetechnowright 
  

//  Libraries needed:
//  Time.h & TimeLib.h:  https://github.com/PaulStoffregen/Time
//  Timezone.h: https://github.com/JChristensen/Timezone
//  SSD1306.h & SSD1306Wire.h:  https://github.com/squix78/esp8266-oled-ssd1306
//  NTPClient.h: https://github.com/arduino-libraries/NTPClient
//  ESP8266WiFi.h & WifiUDP.h: https://github.com/ekstrand/ESP8266wifi

//  Download latest Blynk library here: https://github.com/blynkkk/blynk-library/releases/latest

// 128x64 OLED pinout:
// GND goes to ground
// Vin goes to 3.3V
// Data to I2C SDA (GPIO 4)
// Clk to I2C SCL (GPIO 5)

#include <ESP8266WiFi.h>
#include <WifiUDP.h>
#include <String.h>
#include <Wire.h>
#include <SSD1306.h>
#include <SSD1306Wire.h>
#include <NTPClient.h>
#include <Time.h>
#include <TimeLib.h>
#include <Timezone.h>      
#include <DNSServer.h>            //Local DNS Server used for redirecting all requests to the configuration portal
#include <ESP8266WebServer.h>     //Local WebServer used to serve the configuration portal
#include <WiFiManager.h>        

#define BLYNK_PRINT Serial
#include <BlynkSimpleEsp8266.h>

const int DataDisplayButton = 14;
int RelayButtonPin1 = 12;
int RelayButtonPin2 = 13;

int Relay1Pin = 2; //Relay pin on the other ESP8266
int Relay2Pin = 0; //Relay pin on the other ESP8266

int Relay1State = HIGH;         // the current state of the output pin
int Relay2State = HIGH;         // the current state of the output pin

String RlSt = String(Relay1State, HEX);

int Relay1ButtonState;             // the current reading from the input pin
int Relay2ButtonState;             // the current reading from the input pin

int lastButtonState1 = LOW;   // the previous reading from the input pin
int lastButtonState2 = LOW;   // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime1 = 0;  // the last time the output pin was toggled
unsigned long lastDebounceTime2 = 0;  // the last time the output pin was toggled

unsigned long debounceDelay1 = 50;    // the debounce time; increase if the output flickers
unsigned long debounceDelay2 = 50;    // the debounce time; increase if the output flickers

char auth[] = "254a18667df8466c985b4938476eXXXX"; //Enter your Authentication Token
// Define NTP properties
#define NTP_OFFSET   60 * 60      // In seconds
#define NTP_INTERVAL 60 * 1000    // In miliseconds
#define NTP_ADDRESS  "pool.ntp.org"  // change this to whatever pool is closest (see ntp.org)

// Set up the NTP UDP client
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_ADDRESS, NTP_OFFSET, NTP_INTERVAL);

// Create a display object
SSD1306  display(0x3C, 4, 5); //0x3d for the Adafruit 1.3" OLED, 0x3C being the usual address of the OLED

String date;
String t;
String tempC;
const char * days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} ;
const char * months[] = {"Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"} ;
const char * ampm[] = {"AM", "PM"} ;

const char hostname[] = "weather-ydn-yql.media.yahoo.com";
const String url = "/forecastrss?w=2442047&u=f"; //put the link to Yahoo Weather API here woeid 12761354
const int port = 80;

unsigned long timeout = 10000; //ms

WiFiClient client;

BlynkTimer timer;

WidgetBridge bridge1(V1);  // Connect the Relay module


BLYNK_CONNECTED() {
  // Place the AuthToken of the second hardware here
  bridge1.setAuthToken("6c5494cacbde42cc9bc58ccd68eXXXX"); // Enter the Auth token of the relay module(Other Esp8266 Module);
}

void setup ()
{
  Serial.begin(115200); // most ESP-01's use 115200 but this could vary
  timeClient.begin();   // Start the NTP UDP client

  Wire.pins(4, 5);  // Start the OLED with GPIO 4 and 5 on ESP-01
  Wire.begin(4, 5); // 4=sda, 5=scl
  display.init();
  display.flipScreenVertically();

  WiFiManager wifiManager;
  wifiManager.autoConnect("IOT Watch Connection Setup Tool (esp8266)", " XXXX) ");

  Blynk.begin(auth);
  // Connect to wifi
  pinMode(DataDisplayButton, INPUT);

  
  Serial.println("");
  display.drawString(0, 0, "Connected to WiFi.");
  Serial.print(WiFi.localIP());
  Serial.println("");
  display.drawString(0, 24, "Hi Blynk Forums, thanks for helping!");
  display.display();
  delay(1000);

}

void loop()
{
  int buttonState = digitalRead(DataDisplayButton);
  if (buttonState == LOW) {
    Serial.print("Button pressed");
    GetWeatherData();
    tellTime();
    delay(6000);
  }
  else {
    display.clear();
  }
  
  Blynk.run();
  timer.run();
  ControlRelays();
  
  display.display();
}

void ControlRelays(){
  // read the state of the switch into a local variable:
  int reading1 = digitalRead(RelayButtonPin1);
  int reading2 = digitalRead(RelayButtonPin2);
   
  if(reading1 == LOW || reading2 == LOW){ // Tell the state of the Lights
    display.drawRect(0, 20, 60, 40);
    display.drawRect(61, 20, 60, 40);
    display.setFont(ArialMT_Plain_10);
    display.drawString(17, 3, "Lights");
    display.drawString(84, 3, "A/C");        
    
    if(Relay1State == HIGH){
    display.setFont(ArialMT_Plain_16);
    display.drawString(18, 30, "ON");
    }
    else if(Relay1State == LOW){
    display.setFont(ArialMT_Plain_16);
    display.drawString(15, 30, "OFF");
    } 
    if(Relay2State == HIGH){
    display.setFont(ArialMT_Plain_16);
    display.drawString(78, 30, "ON");
    }
    else if(Relay2State == LOW){
    display.setFont(ArialMT_Plain_16);
    display.drawString(76, 30, "OFF");
    }   
    
}
  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading1 != lastButtonState1) {
    // reset the debouncing timer
    lastDebounceTime1 = millis();
  }
  if (reading2 != lastButtonState2) {
    // reset the debouncing timer
    lastDebounceTime2 = millis();
  }


  if ((millis() - lastDebounceTime1) > debounceDelay1) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading1 != Relay1ButtonState) {
      Relay1ButtonState = reading1;

      // only toggle the LED if the new button state is HIGH
      if (Relay1ButtonState == HIGH) {
        Relay1State = !Relay1State;
      }
    }
  }
  if ((millis() - lastDebounceTime2) > debounceDelay2) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading2 != Relay2ButtonState) {
      Relay2ButtonState = reading2;

      // only toggle the LED if the new button state is HIGH
      if (Relay2ButtonState == HIGH) {
        Relay2State = !Relay2State;
      }
    }
  }
  // set the LED:
  bridge1.digitalWrite(Relay1Pin, Relay1State);
  bridge1.digitalWrite(Relay2Pin, Relay2State);
  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastButtonState1 = reading1;
  lastButtonState2 = reading2;
}

void tellTime() {
  if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
  {
    date = "";  // clear the variables
    t = "";

    // update the NTP client and get the UNIX UTC timestamp
    timeClient.update();
    unsigned long epochTime =  timeClient.getEpochTime();

    // convert received time stamp to time_t object
    time_t local, utc;
    utc = epochTime;

    // Then convert the UTC UNIX timestamp to local time
    TimeChangeRule usEDT = {"EDT", Second, Sun, Mar, 2, +150};  //UTC - 5 hours - change this as needed
    TimeChangeRule usEST = {"EST", First, Sun, Nov, 2, +150};   //UTC - 6 hours - change this as needed
    Timezone usEastern(usEDT, usEST);
    local = usEastern.toLocal(utc);

    // now format the Time variables into strings with proper names for month, day etc
    date += days[weekday(local) - 1];
    date += ", ";
    date += months[month(local) - 1];
    date += " ";
    date += day(local);
    date += ", ";
    date += year(local);

    // format the time to 12-hour format with AM/PM and no seconds
    t += hourFormat12(local);
    t += ":";
    if (minute(local) < 10) // add a zero if minute is under 10
      t += "0";
    t += minute(local);
    t += " ";
    t += ampm[isPM(local)];

    // Display the date and time
    Serial.println("");
    Serial.print("Local date: ");
    Serial.print(date);
    Serial.println("");
    Serial.print("Local time: ");
    Serial.print(t);

    // print the date and time on the OLED
    display.clear();
    display.setTextAlignment(TEXT_ALIGN_CENTER);
    display.setFont(ArialMT_Plain_24);
    display.drawStringMaxWidth(64, 14, 128, t); // print time on the display
    display.setFont(ArialMT_Plain_10);
    display.drawStringMaxWidth(64, 42, 128, date); // print date on the display
    
    display.drawString(70, 0, "Temp:"); // prints the Temperature from GetWeatherData() function
    display.drawString(100, 0, tempC);  // Replace with "temp" to get temperaute in Farenheit
    display.drawString(113, 0, "C");
    display.display();
  }
  else // attempt to connect to wifi again if disconnected
  {
    display.clear();
    display.drawString(0, 18, "Disconnected. Reconnecting to Wifi.");
    display.display();
    WiFiManager wifiManager;
    wifiManager.autoConnect("IOT Watch Connection Setup Tool (esp8266)", "XXX");  
    display.drawString(0, 32, "Connected.");
    display.display();
  }
}
  void GetWeatherData(){
  
  unsigned long timestamp;
  int temp;
  // Establish TCP connection
  Serial.print("Connecting to ");
  Serial.println(hostname);
  if ( !client.connect(hostname, port) ) {
    Serial.println("Connection failed");
  }

  // Send GET request
  String req = "GET " + url + " HTTP/1.1\r\n" + 
                "Host: " + hostname + "\r\n" +
                "Connection: close\r\n" +
                "\r\n";
                "Authorization: OAuth"
                "oauth_consumer_key="dj0yJmk9SjVpN2FnVzBsVlVoJnM9Y29uc3VtZXJzZWNyZXQmc3XXX",oauth_signature_method="HMAC-SHA1",oauth_timestamp="YOUR_TIMESTAMP",oauth_nonce="YOUR_NONCE",oauth_version="1.0",oauth_signature="YOUR_GENERATED_SIGNATURE""   //awaiting these from yahoo
                "cache-control: no-cache"
  client.print(req);

  // Wait for response from server
  delay(500);
  timestamp = millis();
  while ( !client.available() && (millis() < timestamp + timeout) ) {
    delay(1);
  }

  // Parse temperature
  if ( client.find("temp\":") ) {
    temp = client.parseInt();
    tempC = (temp - 32) * 5/9 ;
    Serial.print("Local temperature: ");
    Serial.print(tempC);
    Serial.println("°C");
  }

  // Flush receive buffer
  while ( client.available() ) {
    client.readStringUntil('\r');
  }

  // Close TCP connection
  client.stop();
  Serial.println();
  Serial.println("Connection closed");
  }

  • Marton Baksa

Your void loop() shows that you haven’t read any of documents related to Blynk basics, so it’s very hard to expect that your code will work. You should also read about using delays with Blynk.

Hello,
Thanks for your prompt reply! Please understand this isn’t my code and I barely touched or altered the

void loop()

here.

I do understand that extended delays will cause drops of the blynk server but it was working in the example that I used it from. My explanation for the first

delay(6000);

is that during those calls for

GetWeatherData();
//and
tellTime();

the blynk servers aren’t used at all, however only the Yahoo weather API and the NTP server for proper time.
Also this watch doesn’t require to be connected to the blynk server at all times. All this does in terms of blynk is act as a bridge to turn on and off a couple of relays remotely. And correct me if I am wrong, it will not lose connection to the internet even if disconnected from the blynk server.

The second delay is very similar as it is in the

GetWeatherData();

which is not related to the blynk servers making to my knowledge the delay not a problem.

Please let me know if I misspoke anywhere here and let me know if you have any ideas about the first issue that I described.

Thanks again for your help.

  • Marton Baksa

Every command you put in void loop() is executed thousands of times per second. Everything in your void loop() except blynk.run and timer.run should not be there. And again, reading docs section can help a lot:

http://docs.blynk.cc/

Putting lots of blocking code in the void loop is bad programming practice. People do it, but that doesn’t make it right, and it’s not just a ‘purist’ thing, having a bad void loop is bad practice for many reasons.

If you want to use the Blynk functionality within your code then you’d be better-off using API calls to the Blynk server rather than keep allowing Blynk to disconnect disgracefully because you’ve started the Blunk.run process of processor time with blocking delays.
If you do use the Blynk API then you may want to hard-code the IP address of the Blynk server where your project lives. you can get this by pinging blynk-cloud.com from your PC. This isn’t normally necessary, but as you may travel whilst wearing your watch, you may connect to a different geographic Blynk server and you’ll get an ‘Invalid token’ response to your API call because your project isn’t on that server.

One other thing - I have an issue that you’ve come to this forum looking for advice, but when it’s offered you don’t like the answers, so you want to be able to ignore it. What happens in this situation is that the regulars, who want to help you, simply take a step backwards and let you get on with it yourself.
If you do genuinely want advice from users who have years of experience in using Blynk then I’d suggest taking a different approach when advice is offered. But, that’s just my opinion and my approach.

Pete.

Hello,

I reread my first response and I do realize that my tone was as if I didn’t want to accept the feedback. I would like to apologize for that as that wasn’t how I intended it to be and I was really glad that people of the community did respond very quickly to my help request. Also, I didn’t understand that this was more than just a ‘purist’ thing. I also had this belief that it was acceptable as I have seen it in other example sketches, most notably here, in the code I was editing and felt like it would cause no difference, hence why I slightly brushed it off and I apologize for that again.

Back to the code.

So, I have pinged the server from cmd and it reads the following.

Microsoft Windows [Version 10.0.17763.195]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Users\XXX>ping blynk-cloud.com

Pinging blynk-cloud.com [45.55.96.146] with 32 bytes of data:
Reply from 45.55.96.146: bytes=32 time=22ms TTL=55
Reply from 45.55.96.146: bytes=32 time=15ms TTL=55
Reply from 45.55.96.146: bytes=32 time=14ms TTL=55
Reply from 45.55.96.146: bytes=32 time=13ms TTL=55

Ping statistics for 45.55.96.146:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 13ms, Maximum = 22ms, Average = 16ms

C:\Users\XXX

I believe when you said, “blynk api” you might have been referring to this: https://blynkapi.docs.apiary.io/#reference/0/ am I correct in this assumption? I don’t know how I would implement the IP address from above in the examples described here: https://blynkapi.docs.apiary.io/#reference/0/write-pin-value-via-put/write-pin-value-via-put. How would you do this?

On an unrelated note, I read the https://docs.blynk.cc/ and I noticed that my original error was due to using:

 blynk.config(auth);
//rather than
 blynk.begin(auth, ssid, password, port)

Do you believe this switch is a good solution?

Thanks again for all of your help and I look forward to hearing from y’all.
Best,

  • Marton Baksa

Yes.

You’d replace http://Blynk-cloud.com with 45.55.96.146

If you use the API then you don’t need either.
However, if you’re going to do normal Blynk processing (which doesn’t sound like you are) then be careful with Blynk.begin as it’s a blocking command, so your whole program execution will stop until you connect to Blynk. This might make your watch unusable in some situations.

Pete.

Oh yeah, I won’t need that.

I will update my code and get it back sometime tomorrow with these changes implemented.

Unfortunately, I still am waiting on some parts and I am just trying to make sure that the sketch compiles with no errors and warnings so I should be all ready to go when they arrive. That should be by the end of January and I will post updates then.

Is there anything else you notice in my sketch that has issues?

Thanks again for all of your help!

Best,

  • Marton Baksa

I’ve not studied it in much detail. I notice it doesn’t include OTA updates, which you would find handy if you put the watch in a proper case (unlike the Technowright dude). With OTA you could re-flash the code without having to take the watch apart and connect it to an FTDI progremmer.

Pete.

OTA seems to be good proposal, it’s just few lines of the code, but can save you lots of nervs and time. And here is another exception, in this case your void loop() will have ArduinoOTA.handle() line included beside Blynk.run and timer.run.

OTA updates are a good idea.

After searching the web for some example sketches, I noticed an example and I changed the serial.println’s to display.drawStrings to make them appear onscreen.

 ArduinoOTA.onStart([]() {
    display.clear();
    display.drawString(0, 0, "Start");
    display.display();
  });
  ArduinoOTA.onEnd([]() {
    display.clear();
    display.drawString(0, 0, "End");
    diplay.display();
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    display.clear();
    display.drawString(0, 0, "Progress: %u%%\r", (progress / (total / 100)));
    display.display();
  });
  ArduinoOTA.onError([](ota_error_t error) {
    display.clear();
    display.drawString(50, 0, "Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR)display.drawString(50, 50, "Auth Failed");
    else if (error == OTA_BEGIN_ERROR) display.drawString(50, 50, "Begin Failed");
    else if (error == OTA_CONNECT_ERROR)display.drawString(50, 50, "Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) display.drawString(50, 50, "Receive Failed");
    else if (error == OTA_END_ERROR) display.drawString(50, 50, "End Failed");
    display.display();
  });
  ArduinoOTA.begin();
    display.clear();
    display.drawString(0, 0,"Ready");
    display.drawString(50, 0, "IP address: ");
    display.drawString(50, 75, WiFi.localIP());
    display.display();
}

in the

void setup();

and simply a

ArduinoOTA.handle();

in the

void loop();

Is that all I would need to add for the OTA support to work?

Best,

  • Marton Baksa

edit: forgot to add my name

Too much code, if you ask me.

#include <ArduinoOTA.h>

In void setup:

ArduinoOTA.setHostname(yourhostname);
ArduinoOTA.begin();

In void loop:

ArduinoOTA.handle();

That’s about it.

Sorry for the silly question, what would ‘yourhostname’ be?

Best,

  • Marton Baksa

It’s up to you. It will be the name of device shown in your Arduino IDE together with the IP address in Ports section.

Or if it is easier this way, add:

char yourhostname[] = “marton”;

and leave sethostname line as it is.

That makes a lot of sense. Thank you!

I will go back and make sure all of the stuff we talked about today will be integrated and post my “final” code sometime tomorrow.

Thanks to both of y’all for all of your help!

Best,

  • Marton Baksa
1 Like

Hello,
I’ve been looking through the documentation for the Blynk restful API and I am hung up on how I could acomplish something like this.

if ((get "http://45.55.96.146/my_auth_key/get/D0") == 0) {
    put "http://45.55.96.146/my_auth_key/put/D0/1";
}
else if ((get "http://45.55.96.146/my_auth_key/get/D0") == 1){
    put "http://45.55.96.146/my_auth_key/put/D0/0";
}

I don’t know how I could write this as I couldn’t find any example outputs for the API and their example tester doesn’t work for me as I don’t yet have the relay board yet as I have described earlier. Basically all this does is if it notices the pin on it turns it off and visa versa. Do any of y’all have any idea for accomplishing this?
This would all be so much easier if I had that hardware here, in front of me, but unfortunately, it’s still somewhere between here and China.

Thanks again for your help,

  • Marton Baksa

edit: I can’t spell…

You don"t need PUT, Blynk has coded GET to do a PUT. Look for a Webhook widget example. Check the returned String and then add the if else statement.

This I will have to wait a while for. I will implement this into my code the first day that I get the parts for my relay board. (sometime within 2 weeks) Until then, I will be silent on this thread I guess.

Best,

  • Marton Baksa

Yes without the hardware you can’t do String comparisons but while you are waiting there are quite a few widgets you can use.

I have a project called “MCUless” and as the name suggests it is a sample of widgets that require no hardware at all.

It includes a video stream as a security camera.

A map and GPS settings.

PUSH and Email notifications triggered by the proximity widget and combined with the Eventor (also writes text to the Terminal).

So Granny just puts her hand over the top of her Android phone when she has an intruder and you will receive a PUSH message and be able to see the intruder.

Webhook also works without any hardware.

So in Webhook on V7 a GET (no body):

http:/blynk-cloud.com/[token]/update/D14?value=/pin/

Also V7 button in switch mode and button on gp14 (D14) also in switch mode.

As you press V7 on and off it will send the API call to switch gp14 (D14) on and off.