Connect your existing RF devices to the internet with Blynk

Dear friends,
this is a working Code / Sketch sample for anyone that looking for something like this.
In this version ( 0.5 ) I have incorporated the excellent tip that @krzyspx gave us { Blynk.virtualWrite(V1, LOW); // state LOW or HIGH } a few days ago.
I am still waiting for proposals in order to improve the sketch…

Thanks and Best Regards,
Mike Kranidis

*** PLEASE SEE MY LATEST SKETCH ***

Dear friends,
I have a special need and I am not sure how can deal with. More precisely, as you can see in my sketch above, in order to control (on/off) my RF outlets, I use virtual buttons at Blynk app. I keep the state of the buttons at boolean variables. The problem come up after a random reset of any reason (power outage for example) at my WeMos. I thing the solution will be to keep these variables at EEPROM of ESP8266. What do you think? In this case, can you show me simple code snip that can store and retrieve variables at EEPROM of ESP8266? Is there any other way to keep these variables during reset, power on-off-on?

Thanks and Best Regards,
Mike Kranidis

You can write them to a Value Display widget and when you do a syncAll the variables will be refreshed.

@Costas hello Costas. How are you today? The lovely Cyprus?

According your suggestion (that seems that fit the bill) and because I am not sure that I understood your idea, can you show me a concrete example?

Thanks and Best Regards,
Mike Kranidis

Hot and sunny, as ever at this time of year.

A guide rather than a sketch for you:

Think about the binary representation of decimal 0 to 255 as 00000000 to 11111111, which has 8 digits.
Each digit can represent the true or false status of 8 variables.
So if all 8 variables were true you do:

Blynk.virtualWrite(V0, “11111111”);

If your hardware resets and you lose the variable a syncAll would give you back the “11111111”. You can then do String manipulation or convert string to binary and do binary maths to reinstate the true or false status of your 8 variables.

Please show us what you come up with from this.

1 Like

Nice tip! I will implement in a few days and I will let you know the full sketch!

1 Like

Dear Sirs,
This is the version 0.6 using outlets sync that lives after the reset of WeMos or power outage and so on. This idea (how can be done) is belong to @Costas that always he contribute in this forum (among others!) thanks Costas.
I did not tested extensively so try with care!
In case that you need to see every time the value of V14 (outletsStatus integer variable that keeps the status of 4 outlets in bit wise operation bit0 <-> outletA bit1 <-> outletB bit2 <-> outletC bit3 <-> outletD), please put at my Blynk apps GUI, a small value display widget of course associated with V14 virtual pin.

That’s all folks, test it and let me know!

Thanks and Best Regards,
Mike Kranidis

*** PLEASE SEE MY LATEST SKETCH ***

Morning @mikekgr

The bitwise stuff works fine and looks very neat despite you indicating you are not a programmer. I’m not sure what a programmer really is. I wrote my first programs for the ZX Spectrum over 30 years ago and have been coding on and off, more off, ever since. As I have never had a full time job as a coder I wouldn’t consider myself a programmer either and there is a lot I don’t know. I can write programs but equally I can clean windows but I wouldn’t class myself as window cleaner.

You are missing a break for case 1: in BLYNK_CONNECTED(). I recently missed a break and it took me 2 days to work out why the sketch wasn’t doing what I thought I had told it to do.

I think switching all the bits around might be a good idea so ZoneA ON (alone) is 8 ( binary 1000) rather than 1 (binary 0001). See image below where I added another Visual Display (V13) with a slightly more visual representation of the status of the 4 sockets.

The [1101] is Status 13 (A, C and D ON) but I have had to show the buttons across the app as D, C, B, A rather than A, B, C, D.

As you have a Timer Widget plus buttons to control the RF sockets then the code for V13 and maybe some of your pins is perhaps better with SimpleTimer. It saves you having to add the same code over and over again or calling functions as a “programmer” would do.

So something like this:

in setup()

timer.setInterval(1000L, bitwise);

Add V14 code

BLYNK_WRITE(V14) // status of sockets as an integer from 0 to 15 { outletsStatus = param.asInt(); // Get value as integer }

Add bitwise function

void bitwise(){
  Blynk.syncVirtual(V14);
    switch (outletsStatus)
    {
      case 0:
      {
        /// do all outlets{A..D}off ///
        Blynk.virtualWrite(V13, "[0000]");
        break;
      }
      case 1:
      {
        /// do outletA only on ///
        Blynk.virtualWrite(V13, "[0001]");
        break;
      }
      case 2:
      {
        /// do outletB only on ///
        Blynk.virtualWrite(V13, "[0010]");
        break;
      }
      case 3:
      {
        /// do outlets A & B only on ///
        Blynk.virtualWrite(V13, "[0011]");
        break;
      }
      case 4:
      {
        /// do outletC only on ///
        Blynk.virtualWrite(V13, "[0100]");
        break;
      }
      case 5:
      {
        /// do outlets A & C only on ///
        Blynk.virtualWrite(V13, "[0101]");
        break;
      }
      case 6:
      {
        /// do outlets B & C only on ///
        Blynk.virtualWrite(V13, "[0110]");
        break;
      }
      case 7:
      {
        /// do outlets A & B & C only on ///
        Blynk.virtualWrite(V13, "[0111]");
        break;
      }
      case 8:
      {
        /// do outletD only on ///
        Blynk.virtualWrite(V13, "[1000]");
        break;
      }
      case 9:
      {
        /// do outlets A & D only on ///
        Blynk.virtualWrite(V13, "[1001]");
        break;
      }
      case 10:
      {
        /// do outlets B & D only on ///
        Blynk.virtualWrite(V13, "[1010]");
        break;
      }
      case 11:
      {
        /// do outlets A & B & D only on ///
        Blynk.virtualWrite(V13, "[1011]");
        break;
      }
      case 12:
      {
        /// do outlets C & D only on ///
        Blynk.virtualWrite(V13, "[1100]");
        break;
      }
      case 13:
      {
        /// do outlets A & C & D only on ///
        Blynk.virtualWrite(V13, "[1101]");
        break;
      }
      case 14:
      {
        /// do outlets B & C & D only on ///
        Blynk.virtualWrite(V13, "[1110]");
        break;
      }
      case 15:
      {
        /// do all outlets{A..D}on ///
        Blynk.virtualWrite(V13, "[1111]");
        break;
      }
      default: 
      {
        
      }
    }  
  //Serial.println(V14value); // testing only
}

Dear @Costas,

good morning at first.

thanks for code correction, I have put the “break;” in both my running version as well as above here.

I love to code when my time permitted so and I start coding at “Spectrum +” period (!) when I code pure assembly language WITHOUT assembler, using peek and poke (IIRC) commands to put my code byte by byte in the spectrum memory and to system call/execute afterwards…
I am hardware engineer and usually I don’t write code, even small sketches, but I would like, maybe in my other life I will choose to be programmer!!!
Regarding bitwise operations etc because of my profession, I have very good knowledge for low hardware operations and how things works etc …

Now I have started to think, how can I install “something, hardware” to the outlets to get a true “talk-back” from them… I know this is a rather complicated step and my design constraints will be: 1) Very cheap 2) Reliable 3) Part of two way communication
I don’t know if I will succeed but I will let you know… Of Course this will take time, at the working days I am full of my official job… engineering you know!

Thanks for all Costas !

Best Regards,
Mike Kranidis

@Costas
Dear Costas,
I have a question regarding your proposed way to retain ( store ) values that can survive a WeMos reset, restart, power circle etc.
Well to save a value I do: Blynk.virtualWrite(V??, integer_value); correct?
Then, how can I get back this stored value, in the example, integer_value?
I mean, after the Blynk.syncAll(); command, how to get back my stored value???
Is there a command like: stored_value = virtualRead(V??); ???
Sorry to bother you but I have lost the the practical implementation …

Thanks and Best Regards,
Mike Kranidis

@mikekgr the reason you are struggling to find the required pin “read” function is because Blynk call it a “Write” function. Consideration has been given to renaming the function but personally I didn’t see any improvement for the alternative names being considered.

You need BLYNK_WRITE()

You can sync just a single pin and occasionally this might be preferable to syncAll i.e. when speed is important.

So the code you need to get back the stored value is simply:

BLYNK_WRITE(V?){        // Value Display for holding status of RF sockets
  integer_value = param.asInt();
}
1 Like

Good morning dear Costas.

Thanks a lot. I will try it when I return back to home.

Many thanks to you.

Best Regards,
Mike Kranidis

Dear Costas,

I need to get the value from server to my WeMos.
It seems impossible to have something like this ( does not compiled ):

BLYNK_CONNECTED() 
{
      BLYNK_WRITE(V?)
     {        // Value Display for holding status of RF sockets
        integer_value = param.asInt();
     }
}

How can do this way?

Thanks

If the Value Display holding the variable is V0 it is:

      BLYNK_CONNECTED() 
     {
            Blynk.syncVirtual(V0);
     }

      BLYNK_WRITE(V0)
     {        // Value Display for holding status of RF sockets
        integer_value = param.asInt();
     }
1 Like

Dear Costas,

yes your code “just work” ! Thanks a lot, I resolved one more problem with your kind assistance… I will upload here the corrected version 0.7

Best Regards,
Mike Kranidis

Version 0.7 with bug fixes.

Thanks to @Costas big help and contribution !

Next version I will try to improve the quality of my sketch using functions for the “repeated” code…

#define Version "0.7"
#define WellcomeLine1 " Mike Kranidis "
#define WellcomeLine2 "release  Ver="
#define WellcomeLine3 "RF Remote ELRO AB440, with outlet 'sync' status, Full OTA"

/// ELRO AB440R (system code DIP switches 1 to 5 set as ON-OFF-ON-OFF-ON) ///
/// see https://github.com/sui77/rc-switch/ ///

///  associated with: Client Name: ESP_CED95B / MAC Address: 18:FE:34:CE:D9:5B  ///

/// Blynk related setup ///
/*
 * ALL ZONES OFF V0
 * 
 * ALL ZONES ON V10
 * 
 * ZONE A - ON/OFF V1
 *      
 * ZONE B - ON/OFF V2
 *      
 * ZONE C - ON/OFF V3
 *      
 * ZONE D - ON/OFF V4
 *      
 * V14 outletsStatus integer variable that keeps the status of 4 outlets in bit wise operation bit0 <-> outletA   bit1 <-> outletB   bit2 <-> outletC   bit3 <-> outletD
 *      
 * V15 outlet select menu 
 * 
 * V16 timer 
 * 
 * V20 switch to activate ArduinoOTA.handle() on demand
 * 
 * LED V21 led0 RUN? virtual LED
 */
/// mapping the syscode of the RF Switch system as well as outlets A - E ///
#define syscode "10101"

#define outletA "10000"
#define outletB "01000"
#define outletC "00100"
#define outletD "00010"
#define outletE "00001"

/// RF Transmitter is connected to WeMos Pin #D0 but can be changed here ///
#define WeMosPin D0
/// internal WeMos LED pin #D4 ///

#include <ESP8266WiFi.h>

/// OTA dependencies ///
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

/// WiFiManager dependencies ///
#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>          //https://github.com/tzapu/WiFiManager WiFi Configuration Magic

/// blynk dependencies ///
#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
/// it is used above /// #include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h> 

/// RC Switch dependencies and declaration///
#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = " PLACE YOUR AUTH CODE HERE ";

WidgetLED led0(V21);

SimpleTimer timer;

/// start of WiFiManager Global Start here...  ////
WiFiManager wifiManager;

/// switch value to control if the WeMos internal led will be blinking if HIGH or not if LOW ///
boolean ledBlink = false;

/// boolean value for the last status of zones A B C D ///
boolean statusA = true; boolean statusB = true; boolean statusC = true; boolean statusD = true; 

/// boolean value for let us know if timer is in use true or false ///
boolean caseStatus =  false;

/// value that keeps the case number selection for suitable use in the outlet A to D distinguishing based on the outlet selection menu widget ///
unsigned int selected = 0; 

/// timestamp variable to keep track of millis() unsigned long ticks = millis() / 1000;  That is for debugging printings ///
unsigned long timestamp;

/// outletsStatus integer variable that keeps the status of 4 outlets in bit wise operation bit0 <-> outletA   bit1 <-> outletB   bit2 <-> outletC   bit3 <-> outletD ///
/// we are using the lower 4 bits for easy case - switch implementation ... The Status are going to a Value Display widget using V14 virtual pin /// 
unsigned int outletsStatus = 0;

/// SimpleTimer timer function, check each 5 minutes for the connection. If you lost it then it is doing ESP.reset() ///
void connCheck() {
  if(!wifiManager.autoConnect("AutoConnectAP")) {
    Serial.println("failed to connect and hit timeout");
    delay(3000);
    //reset and try again, or maybe put it to deep sleep
    ESP.reset();
    delay(5000);
  }   
}

/// START of SimpleTimer timer activating function blinkLedWidget ///
void blinkLedWidget()
{
  if (led0.getValue()) {
    led0.off();
    ///BLYNK_LOG("LED0: off");
  } else {
    led0.on();
    ///BLYNK_LOG("LED0: on");
  }
/// END of SimpleTimer timer activating function blinkLedWidget ///

/// put the routine here to blink WeMos LED (D4) each ? second(s), using the "control software switch" ledBlink ///
  if (ledBlink) 
  {int test = digitalRead(D4); 
  digitalWrite(D4, !test); 
  }
}

/// START OF SETUP ///
void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  
  //WiFiManager
  //Local initialization. Once its business is done, there is no need to keep it around
 ///  WiFiManager wifiManager;

  //fetches ssid and pass from eeprom and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  wifiManager.autoConnect("AutoConnectAP");

  //if you get here you have connected to the WiFi
  Serial.println("connected...yesss! :)");

   // Port defaults to 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  // ArduinoOTA.setHostname("myesp8266");

  // No authentication by default
  // ArduinoOTA.setPassword((const char *)"123");

  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("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  /// consider to use Blynk.config(auth); that is now ssid, password hard code specific ///
  /// due to WiFiManager framework the bellow credentials are not needed anymore... ///
  /// Blynk.begin(auth, ssid, password);
  Blynk.config(auth);

  while (Blynk.connect() == false) {
    // Wait until connected
    }
  /// we ensure here that outletsStatus integer will have all the upper bits set to zero //
  outletsStatus = outletsStatus & 15;

  /// Transmitter is connected to "WeMosPin" that is #D0 by default and can be changed in the relevant define above ///
  mySwitch.enableTransmit(WeMosPin);

  // Optional set pulse length.
  mySwitch.setPulseLength(320);
  pinMode(BUILTIN_LED, OUTPUT);  // initialize onboard LED as output  
  digitalWrite(BUILTIN_LED, HIGH); // dim the LED 

/// start of SimpleTimer timer Functions 

  // Check the connection  every 5 minutes. If not connected run 
/// disabled temporary ///  timer.setInterval(300000L, connCheck);

  /// This blink LED function be called every 3 seconds
  timer.setInterval(3000L, blinkLedWidget);

  /// end of SimpleTimer timer Functions
   
}
/// END OF SETUP ///

/// start of timekeeper function return time in tenth of seconds can be called as unsigned long tempval; e.x. tempval=timekeeper(); ///
  unsigned long timekeeper() {
    timestamp = millis() / 100;
    return timestamp;
  }

/// start routine virtual button V0 ALL OFF button ///
  BLYNK_WRITE(V0)
  {
    if (param.asInt() == true) 
    {
    mySwitch.switchOff(syscode, outletA) ; mySwitch.switchOff(syscode, outletB) ; mySwitch.switchOff(syscode, outletC) ; mySwitch.switchOff(syscode, outletD) ;
    statusA = true; statusB = true; statusC = true; statusD = true;  
    Blynk.virtualWrite(V1, LOW); Blynk.virtualWrite(V2, LOW); Blynk.virtualWrite(V3, LOW); Blynk.virtualWrite(V4, LOW); //state LOW or HIGH;
    outletsStatus = 0;
    Blynk.virtualWrite(V14, outletsStatus); /// set all bits (outletA ... outletD) to 0 ///  
    }
  }
/// end of routine virtual button V0 ALL OFF button ///

/// start routine virtual button V10 ALL ON button ///
  BLYNK_WRITE(V10)
  {
    if (param.asInt() == true) {
    mySwitch.switchOn(syscode, outletA) ; mySwitch.switchOn(syscode, outletB) ; mySwitch.switchOn(syscode, outletC) ; mySwitch.switchOn(syscode, outletD) ;
    statusA = false; statusB = false; statusC = false; statusD = false;
    Blynk.virtualWrite(V1, HIGH); Blynk.virtualWrite(V2, HIGH); Blynk.virtualWrite(V3, HIGH); Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH;  
    outletsStatus = 15;
    Blynk.virtualWrite(V14, outletsStatus); /// set all bits (outletA ... outletD) to 1 ///  
    }
  }
/// end of routine virtual button V10 ALL ON button ///

/// start routine virtual button V1 ///
  BLYNK_WRITE(V1)
  {
    if (param.asInt() == true && statusA == true) 
    {
    mySwitch.switchOn(syscode, outletA) ;
    statusA = false;
    Blynk.virtualWrite(V1, HIGH); //state LOW or HIGH
    outletsStatus = outletsStatus | 1;
    Blynk.virtualWrite(V14, outletsStatus); /// set bit 0 (outletA) to 1 /// 
    } else if (param.asInt() == true && statusA == false) 
      {
      mySwitch.switchOff(syscode, outletA);
      statusA = true;
      Blynk.virtualWrite(V1, LOW); //state LOW or HIGH
      outletsStatus = outletsStatus & 14;
      Blynk.virtualWrite(V14, outletsStatus); /// set bit 0 (outletA) to 0 /// 
      }
  }
/// end of routine virtual button V1 ///

/// start routine virtual button V2 ///
  BLYNK_WRITE(V2)
  {
    if (param.asInt() == true && statusB == true) 
    {
    mySwitch.switchOn(syscode, outletB) ;
    statusB = false;
    Blynk.virtualWrite(V2, HIGH); //state LOW or HIGH
    outletsStatus = outletsStatus | 2;
    Blynk.virtualWrite(V14, outletsStatus); /// set bit 1 (outletB) to 1 /// 
    } else if (param.asInt() == true && statusB == false) 
      {
      mySwitch.switchOff(syscode, outletB);
      statusB = true;
      Blynk.virtualWrite(V2, LOW); //state LOW or HIGH
      outletsStatus = outletsStatus & 13;
      Blynk.virtualWrite(V14, outletsStatus); /// set bit 1 (outletB) to 0 /// 
      }
  }
/// end of routine virtual button V2 ///

/// start routine virtual button V3 ///
  BLYNK_WRITE(V3)
  {
    if (param.asInt() == true && statusC == true) 
    {
    mySwitch.switchOn(syscode, outletC) ;
    statusC = false;
    Blynk.virtualWrite(V3, HIGH); //state LOW or HIGH
    outletsStatus = outletsStatus | 4;
    Blynk.virtualWrite(V14, outletsStatus); /// set bit 2 (outletC) to 1 /// 
    } else if (param.asInt() == true && statusC == false) 
      {
      mySwitch.switchOff(syscode, outletC);
      statusC = true;
      Blynk.virtualWrite(V3, LOW); //state LOW or HIGH
      outletsStatus = outletsStatus & 11;
      Blynk.virtualWrite(V14, outletsStatus); /// set bit 2 (outletC) to 0 /// 
      }
  }
/// end of routine virtual button V3 ///

/// start routine virtual button V4 ///
  BLYNK_WRITE(V4)
  {
    if (param.asInt() == true && statusD == true) 
    {
    mySwitch.switchOn(syscode, outletD) ;
    statusD = false;
    Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH
    outletsStatus = outletsStatus | 8;
    Blynk.virtualWrite(V14, outletsStatus); /// set bit 3 (outletD) to 1 /// 
    } else if (param.asInt() == true && statusD == false) 
      {
      mySwitch.switchOff(syscode, outletD);
      statusD = true;
      Blynk.virtualWrite(V4, LOW); //state LOW or HIGH
      outletsStatus = outletsStatus & 7;
      Blynk.virtualWrite(V14, outletsStatus); /// set bit 3 (outletD) to 0 /// 
      }
  }
/// end of routine virtual button V4 ///

/// put the rest here ///

/// start routine for manual (on demand) requesting OTA The Virtual Button SW V20 is used ///
  BLYNK_WRITE(V20)
  {
    if (param.asInt()) 
    {
    ArduinoOTA.handle();
    ///for(int c = 0; c < 100; c++) { 
    ///ArduinoOTA.handle();
    ///}
    } 
    /// else {
    /// do nothing ///
    ///  }
  }
/// end of routine for manual (on demand) requesting OTA The Virtual Button SW V20 is used ///

/// start routine for menu setting the selected outlet (A to D) for timer use. V15 is used ///
  BLYNK_WRITE(V15) {
    int val = param.asInt();
    switch (val)
 {
    case 1: 
    { // Item 1
      /// outletA selected ///
      selected = 1;
      caseStatus = true;
      statusA == true;
      break;
    }
    case 2: 
    { // Item 2
      /// outletB selected ///
      selected = 2;
      caseStatus = true;
      statusB == true;
      break;
    }
    case 3: 
    { // Item 3
      /// outletC selected ///
      selected = 3;
      caseStatus = true;
      statusC == true;
      break;
    }
    case 4: 
    { // Item 4
      /// outletD selected ///
      selected = 4;
      caseStatus = true;
      statusD == true;
      break;
    }
    default: 
    {
      /// default outlet let's put outletA as default outlet ///
///      selected = 1;
///      caseStatus = true;
///      statusA == true;
///      Serial.println(" default in the menu selection routine ");
      }
    }
  }
/// end of routine for menu setting the selected outlet (A to D) for timer use. V15 is used ///

/// start routine for timer for automated start stop. V16 is used ///
  BLYNK_WRITE(V16)
  {
    // You'll get HIGH/1 at startTime and LOW/0 at stopTime.
    // this method will be triggered every day
    // until you remove widget or stop project or
    // clean stop/start fields of widget
///  Serial.print("Got a value: ");
///  Serial.println(param.asStr());
      bool valb = param.asInt();
      if (caseStatus == true) {
      switch (selected)
    {
    case 1: 
    {
      if (valb == true && statusA == true) {
      mySwitch.switchOn(syscode, outletA) ;
      statusA = false;
      Blynk.virtualWrite(V1, HIGH); //state LOW or HIGH
      outletsStatus = outletsStatus | 1;
      Blynk.virtualWrite(V14, outletsStatus); /// set bit 0 (outletA) to 1 /// 
      break;
      } else if (valb == false && statusA == false) 
        {
        mySwitch.switchOff(syscode, outletA);
        statusA = true;
        caseStatus = false;
        Blynk.virtualWrite(V1, LOW); //state LOW or HIGH
        outletsStatus = outletsStatus & 14;
        Blynk.virtualWrite(V14, outletsStatus); /// set bit 0 (outletA) to 0 /// 
        break;
        }        
      }
      
    case 2: 
    {
      if (valb == true && statusB == true) {
      mySwitch.switchOn(syscode, outletB) ;
      statusB = false;
      Blynk.virtualWrite(V2, HIGH); //state LOW or HIGH
      outletsStatus = outletsStatus | 2;
      Blynk.virtualWrite(V14, outletsStatus); /// set bit 1 (outletB) to 1 /// 
      break;
      } else if (valb == false && statusB == false) 
        {
        mySwitch.switchOff(syscode, outletB);
        statusB = true;
        caseStatus = false;
        Blynk.virtualWrite(V2, LOW); //state LOW or HIGH
        outletsStatus = outletsStatus & 13;
        Blynk.virtualWrite(V14, outletsStatus); /// set bit 1 (outletB) to 0 /// 
        break;  
        }
      }

    case 3: {
      if (valb == true && statusC == true) 
      {
      mySwitch.switchOn(syscode, outletC) ;
      statusC = false;
      Blynk.virtualWrite(V3, HIGH); //state LOW or HIGH
      outletsStatus = outletsStatus | 4;
      Blynk.virtualWrite(V14, outletsStatus); /// set bit 2 (outletC) to 1 /// 
      break;
      } else if (valb == false && statusC == false) 
        {
        mySwitch.switchOff(syscode, outletC);
        statusC = true;
        caseStatus = false;
        Blynk.virtualWrite(V3, LOW); //state LOW or HIGH
        outletsStatus = outletsStatus & 11;
        Blynk.virtualWrite(V14, outletsStatus); /// set bit 2 (outletC) to 0 /// 
        break;  
        }
      }

    case 4: 
    {
      if (valb == true && statusD == true) {
      mySwitch.switchOn(syscode, outletD) ;
      statusD = false;
      Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH
      outletsStatus = outletsStatus | 8;
      Blynk.virtualWrite(V14, outletsStatus); /// set bit 3 (outletD) to 1 /// 
      break;
      } else if (valb == false && statusD == false) 
        {
        mySwitch.switchOff(syscode, outletD);
        statusD = true;
        caseStatus = false;
        Blynk.virtualWrite(V4, LOW); //state LOW or HIGH
        outletsStatus = outletsStatus & 7;
        Blynk.virtualWrite(V14, outletsStatus); /// set bit 3 (outletD) to 0 /// 
        break;  
        }
      }
    default: 
    {
      /*
      if (param.asInt() == true && statusA == true) {
      mySwitch.switchOn(syscode, outletA) ;
      led1.on();
      statusA = false;
      } else if (param.asInt() == true && statusA == false) {
      mySwitch.switchOff(syscode, outletA);
      led1.off();
      statusA = true;
      caseStatus = false;
      break;
         }  */
        }
      } /// end of switch - case 
    } /// end of if 
      else {
    /// all no timer cases ... ///  

    }

  } /// end of BLYNK_WRITE(16)
 /*   
    if (param.asInt() == true && statusA == true) {
    mySwitch.switchOn(syscode, outlet) ;
    led1.on();
    statusA = false;
    } else if (param.asInt() == false && statusA == false) {
    mySwitch.switchOff(syscode, outlet);
    led1.off();
 
    statusA = true;
      }
  }
  */
/// end of routine for timer for automated start stop. V16 is used ///

// Every time we connect to the cloud synchronize some / all of the values from Widgets...
// This function will run every time Blynk connection is established
BLYNK_CONNECTED() 
{
  ///if (isFirstConnect) {
    // Request Blynk server to re-send latest values for all pins
     /// we ensure here that outletsStatus integer will have all the upper bits set to zero ///

    Blynk.syncAll();
    Blynk.syncVirtual(V14);    
    // You can also update an individual Virtual pin like this:
    //Blynk.syncVirtual(V0);

   /// isFirstConnect = false;
  ///}

  // Let's write your hardware uptime to Virtual Pin 2
  ///int value = millis() / 1000;
  ///Blynk.virtualWrite(V2, value);
}
BLYNK_WRITE(V14)
{        // Value Display for holding status of RF sockets
        outletsStatus = param.asInt();
        outletsStatus = outletsStatus & 15;

      switch (outletsStatus) {
      case 0:
      {
        /// do all outlets{A..D}off ///
        mySwitch.switchOff(syscode, outletA) ; mySwitch.switchOff(syscode, outletB) ; mySwitch.switchOff(syscode, outletC) ; mySwitch.switchOff(syscode, outletD) ;
        statusA = true; statusB = true; statusC = true; statusD = true;
        Blynk.virtualWrite(V1, LOW); Blynk.virtualWrite(V2, LOW); Blynk.virtualWrite(V3, LOW); Blynk.virtualWrite(V4, LOW); //state LOW or HIGH;
        break;
      }
      case 1:
      {
        /// do outletA only on ///
        mySwitch.switchOn(syscode, outletA) ; mySwitch.switchOff(syscode, outletB) ; mySwitch.switchOff(syscode, outletC) ; mySwitch.switchOff(syscode, outletD) ;
        Blynk.virtualWrite(V1, HIGH); Blynk.virtualWrite(V2, LOW); Blynk.virtualWrite(V3, LOW); Blynk.virtualWrite(V4, LOW); //state LOW or HIGH;
        statusA = false; statusB = true; statusC = true; statusD = true;
        break;
      }
      case 2:
      {
        /// do outletB only on ///
        mySwitch.switchOff(syscode, outletA) ; mySwitch.switchOn(syscode, outletB) ; mySwitch.switchOff(syscode, outletC) ; mySwitch.switchOff(syscode, outletD) ;
        Blynk.virtualWrite(V1, LOW); Blynk.virtualWrite(V2, HIGH); Blynk.virtualWrite(V3, LOW); Blynk.virtualWrite(V4, LOW); //state LOW or HIGH;
        statusA = true; statusB = false; statusC = true; statusD = true;
        break;
      }
      case 3:
      {
        /// do outlets A & B only on ///
        mySwitch.switchOn(syscode, outletA) ; mySwitch.switchOn(syscode, outletB) ; mySwitch.switchOff(syscode, outletC) ; mySwitch.switchOff(syscode, outletD) ;
        Blynk.virtualWrite(V1, HIGH); Blynk.virtualWrite(V2, HIGH); Blynk.virtualWrite(V3, LOW); Blynk.virtualWrite(V4, LOW); //state LOW or HIGH;
        statusA = false; statusB = false; statusC = true; statusD = true;
        break;
      }
      case 4:
      {
        /// do outletC only on ///
        mySwitch.switchOff(syscode, outletA) ; mySwitch.switchOff(syscode, outletB) ; mySwitch.switchOn(syscode, outletC) ; mySwitch.switchOff(syscode, outletD) ;
        Blynk.virtualWrite(V1, LOW); Blynk.virtualWrite(V2, LOW); Blynk.virtualWrite(V3, HIGH); Blynk.virtualWrite(V4, LOW); //state LOW or HIGH;
        statusA = true; statusB = true; statusC = false; statusD = true;
        break;
      }
      case 5:
      {
        /// do outlets A & C only on ///
        mySwitch.switchOn(syscode, outletA) ; mySwitch.switchOff(syscode, outletB) ; mySwitch.switchOn(syscode, outletC) ; mySwitch.switchOff(syscode, outletD) ;
        Blynk.virtualWrite(V1, HIGH); Blynk.virtualWrite(V2, LOW); Blynk.virtualWrite(V3, HIGH); Blynk.virtualWrite(V4, LOW); //state LOW or HIGH; 
        statusA = false; statusB = true; statusC = false; statusD = true;
        break;
      }
      case 6:
      {
        /// do outlets B & C only on ///
        mySwitch.switchOff(syscode, outletA) ; mySwitch.switchOn(syscode, outletB) ; mySwitch.switchOn(syscode, outletC) ; mySwitch.switchOff(syscode, outletD) ;
        Blynk.virtualWrite(V1, LOW); Blynk.virtualWrite(V2, HIGH); Blynk.virtualWrite(V3, HIGH); Blynk.virtualWrite(V4, LOW); //state LOW or HIGH;
        statusA = true; statusB = false; statusC = false; statusD = true;
        break;
      }
      case 7:
      {
        /// do outlets A & B & C only on ///
        mySwitch.switchOn(syscode, outletA) ; mySwitch.switchOn(syscode, outletB) ; mySwitch.switchOn(syscode, outletC) ; mySwitch.switchOff(syscode, outletD) ;
        Blynk.virtualWrite(V1, HIGH); Blynk.virtualWrite(V2, HIGH); Blynk.virtualWrite(V3, HIGH); Blynk.virtualWrite(V4, LOW); //state LOW or HIGH;
        statusA = false; statusB = false; statusC = false; statusD = true;
        break;
      }
      case 8:
      {
        /// do outletD only on ///
        mySwitch.switchOff(syscode, outletA) ; mySwitch.switchOff(syscode, outletB) ; mySwitch.switchOff(syscode, outletC) ; mySwitch.switchOn(syscode, outletD) ;
        Blynk.virtualWrite(V1, LOW); Blynk.virtualWrite(V2, LOW); Blynk.virtualWrite(V3, LOW); Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH;
        statusA = true; statusB = true; statusC = true; statusD = false;
        break;
      }
      case 9:
      {
        /// do outlets A & D only on ///
        mySwitch.switchOn(syscode, outletA) ; mySwitch.switchOff(syscode, outletB) ; mySwitch.switchOff(syscode, outletC) ; mySwitch.switchOn(syscode, outletD) ;
        Blynk.virtualWrite(V1, HIGH); Blynk.virtualWrite(V2, LOW); Blynk.virtualWrite(V3, LOW); Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH;
        statusA = false; statusB = true; statusC = true; statusD = false;
        break;
      }
      case 10:
      {
        /// do outlets B & D only on ///
        mySwitch.switchOff(syscode, outletA) ; mySwitch.switchOn(syscode, outletB) ; mySwitch.switchOff(syscode, outletC) ; mySwitch.switchOn(syscode, outletD) ;
        Blynk.virtualWrite(V1, LOW); Blynk.virtualWrite(V2, HIGH); Blynk.virtualWrite(V3, LOW); Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH;
        statusA = true; statusB = false; statusC = true; statusD = false;
        break;
      }
      case 11:
      {
        /// do outlets A & B & D only on ///
        mySwitch.switchOn(syscode, outletA) ; mySwitch.switchOn(syscode, outletB) ; mySwitch.switchOff(syscode, outletC) ; mySwitch.switchOn(syscode, outletD) ;
        Blynk.virtualWrite(V1, HIGH); Blynk.virtualWrite(V2, HIGH); Blynk.virtualWrite(V3, LOW); Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH;
        statusA = false; statusB = false; statusC = true; statusD = false;
        break;
      }
      case 12:
      {
        /// do outlets C & D only on ///
        mySwitch.switchOff(syscode, outletA) ; mySwitch.switchOff(syscode, outletB) ; mySwitch.switchOn(syscode, outletC) ; mySwitch.switchOn(syscode, outletD) ;
        Blynk.virtualWrite(V1, LOW); Blynk.virtualWrite(V2, LOW); Blynk.virtualWrite(V3, HIGH); Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH;
        statusA = true; statusB = true; statusC = false; statusD = false;
        break;
      }
      case 13:
      {
        /// do outlets A & C & D only on ///
        mySwitch.switchOn(syscode, outletA) ; mySwitch.switchOff(syscode, outletB) ; mySwitch.switchOn(syscode, outletC) ; mySwitch.switchOn(syscode, outletD) ;
        Blynk.virtualWrite(V1, HIGH); Blynk.virtualWrite(V2, LOW); Blynk.virtualWrite(V3, HIGH); Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH;
        statusA = false; statusB = true; statusC = false; statusD = false;
        break;
      }
      case 14:
      {
        /// do outlets B & C & D only on ///
        mySwitch.switchOff(syscode, outletA) ; mySwitch.switchOn(syscode, outletB) ; mySwitch.switchOn(syscode, outletC) ; mySwitch.switchOn(syscode, outletD) ;
        Blynk.virtualWrite(V1, LOW); Blynk.virtualWrite(V2, HIGH); Blynk.virtualWrite(V3, HIGH); Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH;
        statusA = true; statusB = false; statusC = false; statusD = false;
        break;
      }
      case 15:
      {
        /// do all outlets{A..D}on ///
        mySwitch.switchOn(syscode, outletA) ; mySwitch.switchOn(syscode, outletB) ; mySwitch.switchOn(syscode, outletC) ; mySwitch.switchOn(syscode, outletD) ;
        Blynk.virtualWrite(V1, HIGH); Blynk.virtualWrite(V2, HIGH); Blynk.virtualWrite(V3, HIGH); Blynk.virtualWrite(V4, HIGH); //state LOW or HIGH;
        statusA = false; statusB = false; statusC = false; statusD = false;
        break;
      }
      default: 
      {
        /// what should I put here ??? ///
      }

    } /// end of switch - case ///
}


/// START OF LOOP ///

void loop() {
  /// just as reminder here: mySwitch.switchOn(syscode, outletA) ; ///
  ///                        mySwitch.switchOff(syscode, outletA); ///
  ArduinoOTA.handle();
  Blynk.run();
  timer.run();
}
/// END OF LOOP ///

You don’t need syncAll and syncVirtual(V14) in BLYNK_CONNECTED().

syncAll calls all your BLYNK_WRITE() functions. In your case as you sync all the buttons as well as the Value Display holding the status of the sockets then syncAll is enough without syncVirtual(V14).

yes I know. It left here during a test. I will remove at my next version.

Thanks for point it to me.

Maplins in the UK are currently offering 5 RF controlled sockets for less than £20, so less than £4 per socket. With the £5 it costs for the hardware to control the sockets over the internet that is still less than £5 per socket. The sockets are rated at 3120W so they will cover almost all your household appliances.

I have ordered a set but it will be 3 weeks before I receive them. I have added what I believe the codes are, to the free app. One complaint made by buyers of the Maplin sockets is that there are only 4 buttons on the remote control so you can’t control 5 sockets independently. No such problem for the Blynk app.

Screenshot of the latest version above and a link for the bin file is here.

The app now includes timers for up to 4 devices as standard within the 2000 units of free Energy allowance. To accommodate the 4 timers and cover other modifications the app now includes:

  1. Keyword update in terminal brings up the access point to update the app with a copy of the latest bin file.

  2. Keyword map in terminal sets the 4 timers to Maplin’s sockets, all on channel 1, for buttons 1, 2 ,3 and 4.

  3. Keyword st in terminal sets the 4 timers to the Status sockets for buttons 1, 2, 3 and 4.

  4. The RTC for the ESP is automatically set to the correct time of day, up to 4 times each day, based on the ON times of the 4 timers, without the cost of the RTC widget.

  5. Time currently defaults to British Summer time (BST) and can be changed with terminal keyword GMTX where X is hours plus or minus from BST.

  6. Improved RF data signal capture.

  7. Other minor tweaks.

QR code for the latest project is shown below and available here. Alternatively you can use this url from your Smartphone.

We started the Instructable for the app a couple of weeks ago but it is slow going as we would rather spend our time improving the app.

2 Likes

Can’t wait for instructable! We would also like to post it to hackster.io