WJ4IoT
Published © LGPL

Home Automation with Self-learning 433 Power Switches

The project itself was based on a static sketch running for several months in 2016 with a handful of lights following sunrise/-set.

BeginnerFull instructions provided3 hours4,977

Things used in this project

Hardware components

WeMos D1 R2
×1
433MHz Wireless Transmitter
×1
DS3231 AT24C32 IIC Real Time Clock Module
×1
Arduino UNO
Arduino UNO
×1
Self-learning 433 Power Switches
×1

Software apps and online services

Cayenne
myDevices Cayenne

Story

Read more

Schematics

Simple Schematics

Code

Main Sketch

Arduino
Compile this sketch to your wemos; likely you need to install additional file manager in Arduino application
 /*
 * Initally based upon a sketch from Nick Gammon
 * Collected various values for the switches and adapted for Cayenne By Wouter-Jan 
 * Info DS323-hardware: http://www.dx.com/p/ds3231-at24c32-iic-high-precision-real-time-clock-module-for-arduino-3pcs-408743
 * Info Wemos D1 R2: https://wiki.wemos.cc/tutorials:get_started:get_started_in_arduino\
 *                   http://arduino.esp8266.com/versions/1.6.5-947-g39819f0/doc/reference.html
 * Install additional Device Manager for Wemos: file - preferences - additional boardmanager: http://arduino.esp8266.com/stable/package_esp8266com_index.json
 * 
 * Some additional useful links:
 * http://www.instructables.com/id/Programming-the-WeMos-Using-Arduino-SoftwareIDE/
 * http://community.mydevices.com/t/data-types-for-cayenne-mqtt-api/3714
 * http://community.mydevices.com/t/converting-cayenne-arduino-library-sketches-to-cayenne-mqtt-arduino/5759
 * https://github.com/myDevicesIoT/Cayenne-MQTT-ESP8266
 * https://roboticboyer.files.wordpress.com/2016/03/wemos_pins_00.pdf
 * https://opencircuit.nl/ProductInfo/1000178/WeMos-D1-Handleiding.pdf
 * 
Versions
0.01 Moved from the Arduino Library to Cayenne MQTT
  Replaced the RST-sensor with online query with the NTP-server; refreshed Summer Time (DST) check based upon the NTP data and used in Tardis routine for Sunrise and sunset
  Added DHT22-sensor: 1st working MQTT example
  Added Wi-Fi signal and system uptime information on the dashboard
  Added obsolete scheduling routines in "some Rube Goldberg logic" style to tackle misbehavior of scheduling and triggers (including actuator) including switch to (de-)activate
*/

// WiFi network & Cayenne authentication info.
#include <CayenneMQTTESP8266.h>
char ssid[] = "ssid";
char wifiPassword[] = "password";
char username[] = "user";
char password[] = "pw";
char clientID[] = "id"; // Device abf-testing

// some Cayenne stuff for Wemos D1 R2 with MQTT
#include <CayenneDefines.h>
#define CAYANNE_DEBUG
#define CAYANNE_PRINT Serial

// library, variables for DHT22 (Temperature and Huminity)
#include <DHT.h>
#define DHTPIN D6
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
float h;
float t;
DHT dht(DHTPIN, DHTTYPE);

// library, variables for Flaminco Switches)
#define rfPin D7       // uses digital 7 (the D is important)
//const int rfPin = 13;    // Pin Digital D7 on Wemos D1 R2                 
#include "flamingo.h"  // library in seperate tab for Action switch (self-learning)
//int tmp_switch_value, tmp_switch; //used to invert logic

/*
#include <RemoteTransmitter.h>
KaKuTransmitter kaKuTransmitter(7); //data-pin 433 on pin 7
*/

// for elro switches (if not in use please remove complete sketch low memory on W5100)
#include <RCSwitch.h> //using library: https://github.com/sui77/rc-switch (version 2.6.2)          
RCSwitch mySwitch = RCSwitch();


// for Flamingo SF-501PWD (among others)
#include <NewRemoteTransmitter.h> //library can be found on https://bitbucket.org/fuzzillogic/433mhzforarduino/wiki/Home
NewRemoteTransmitter transmitter(14727168, rfPin, 260, 3); //values are transmittercode, pin, miliseconds, repeat

// Library to connnect to time-servers in NL https://github.com/SensorsIot/SNTPtime
#include <SNTPtime.h>
SNTPtime NTPnl("nl.pool.ntp.org");
strDateTime dateTime;
strDateTime dateTime_wo_DST;
int check_DST;

//timelord tardis libary for sunset/sunrise Info Tardis http://forum.arduino.cc/index.php?topic=129249.msg972860#msg972860
#include <TimeLord.h>

// various variables
unsigned long lastMillis = 0;
int time_now = 0;             //set time funtion
int time_sunset = 0;          //sunset time funtion
int time_sunrise = 0;         //sunrise time funtion
int time_offset = 0;          //to calculate the twilight zone
float time_now_d, time_sunset_d, time_sunrise_d; //to display time without a colon only a point
float uptime;                 // time system is up and running
int int_scheduling = 1;       // actuator to activate internal sceduling
//int systemUpTimeMn, systemUpTimeHr, systemUpTimeDy; //used in calculation system uptime
//int ActualCounter = 0;

void setup() {
  
  Serial.begin(115200);
  Serial.println("sketch: MQTT_433_Switches");
  Serial.print("compiled: ");
  Serial.print(__DATE__);
  Serial.print(" ");
  Serial.println(__TIME__);
  Serial.println("Following sensors are/should be connected");
  //Serial.println("-> Analog 4 = SCL RTC DC3231");
  //Serial.println("-> Analog 5 = SDA RTC DC3231");
  Serial.println("-> Digital 6 = DHT22");
  Serial.println("-> Digital 7 = Data 433");

  dht.begin();
  
  Serial.println("Booted");
  Serial.println("Connecting to Wi-Fi");
  Cayenne.begin(username, password, clientID, ssid, wifiPassword);
  while (WiFi.status() != WL_CONNECTED) {
         Serial.print(".");
         delay(500);
  }
  Serial.println("WiFi connected");

  //refresh time and DST
  Time_DST_refresh();
  Cayenne.virtualWrite(43, check_DST, "digital_sensor", "d");

  // Set internal scheduling to true
  Serial.print("int_scheduling : " );
  Serial.println(int_scheduling);
  Cayenne.virtualWrite(26, int_scheduling);
}

void loop() {
  Cayenne.loop();
  //Publish data every 10 seconds (10000 milliseconds). Change this value to publish at a different interval.
  if (millis() - lastMillis > 10000) {
    lastMillis = millis();
    
    //Misc
      Cayenne.virtualWrite(32, WiFi.RSSI()); //display signal WiFi connection
      //source: https://diyprojects.io/portable-wifi-scanner-oled-display-esp8266-signal-strength-connection-test-server/#.Whacbjco-Uk
    //refresh present time
    Timeroutine();
    Cayenne.virtualWrite(40, time_now_d);

    if ( dateTime.dayofWeek == 1 && dateTime.hour == 3 && dateTime.minute == 0 ) { // monthly reset of time based upon NTP-servers and DST-check
       Time_DST_refresh();
       Cayenne.virtualWrite(43, check_DST, "digital_sensor", "d");
    }

    if ( dateTime.hour == 0 && dateTime.minute == 0 ) {      // daily reset of sunrise and sunsut   
       sunsetrise();
       Cayenne.virtualWrite(38, time_sunset_d);
       Cayenne.virtualWrite(39, time_sunrise_d);
    }
    
    publishSystemUpTime();                        //calculate and display system up time
      //Cayenne.virtualWrite(35, systemUpTimeDy);
      //Cayenne.virtualWrite(36, systemUpTimeHr);
      Cayenne.virtualWrite(37, uptime);
    
    DHTroutine();

    Serial.print("int_scheduling : " );
    Serial.println(int_scheduling);
    if ( int_scheduling == 1) { // is the internal scheduling requested?
       obsolete_scheduling();
    }
  }
}

//Default function for processing actuator commands from the Cayenne Dashboard.
//You can also use functions for specific channels, e.g CAYENNE_IN(1) for channel 1 commands.
CAYENNE_IN_DEFAULT()
{
  CAYENNE_LOG("CAYENNE_IN_DEFAULT(%u) - %s, %s", request.channel, getValue.getId(), getValue.asString());
  //Process message here. If there is an error set an error message using getValue.setError(), e.g getValue.setError("Error message");
}

CAYENNE_IN(0) // action switch lamp V0
{
  Flamingo_Send(0, !getValue.asInt());
}
CAYENNE_IN(1) // action switch lamp V1
{
  Flamingo_Send(1, !getValue.asInt());
}
CAYENNE_IN(2) // action switch lamp V2
{
  Flamingo_Send(2, !getValue.asInt());
}
CAYENNE_IN(3) // action switch lamp V3
{
  Flamingo_Send(3, !getValue.asInt());
}
CAYENNE_IN(4) // action switch lamp V4
{
  Flamingo_Send(4, !getValue.asInt());
}
CAYENNE_IN(5) // action switch lamp V5
{
  Flamingo_Send(5, !getValue.asInt());
}
CAYENNE_IN(6) // action switch lamp V6
{
  Flamingo_Send(6, !getValue.asInt());
}
CAYENNE_IN(7) // action switch lamp V7
{
  Flamingo_Send(7, !getValue.asInt());
}
CAYENNE_IN(13) // Flamingo SF-501PWD unit 1
{
  transmitter.sendUnit(1, getValue.asInt()); // Flamingo SF-501PWD unit 1
  Cayenne.virtualWrite(13, getValue.asInt());
}
CAYENNE_IN(14) // Flamingo SF-501PWD unit 2
{
  transmitter.sendUnit(2, getValue.asInt()); // Flamingo SF-501PWD unit 2
  Cayenne.virtualWrite(14, getValue.asInt());
}
CAYENNE_IN(25) // Because 2 is a crowd for triggers, 1 trigger for all Night Time events GO-GO-GO in testing
{
  int tmp_switch_val = getValue.asInt();
  Serial.println("tmp_switch_val : ");
  Serial.println(tmp_switch_val);
  flamingo_2actions(0, tmp_switch_val);
  flamingo_2actions(1, tmp_switch_val);
  flamingo_2actions(2, tmp_switch_val);
  //flamingo_2actions(3, tmp_switch_val);
  flamingo_2actions(4, tmp_switch_val);
  flamingo_2actions(5, tmp_switch_val);
  flamingo_2actions(6, tmp_switch_val);
  flamingo_2actions(7, tmp_switch_val);
  transmitter.sendUnit(1, tmp_switch_val); // Flamingo SF-501PWD unit 1
  Cayenne.virtualWrite(13, tmp_switch_val);
  transmitter.sendUnit(2, tmp_switch_val); // Flamingo SF-501PWD unit 2
  Cayenne.virtualWrite(14, tmp_switch_val);
}
CAYENNE_IN(26) // activate internal scheduling
{
   int_scheduling = getValue.asInt();
   Serial.print("int_scheduling : " );
   Serial.println(int_scheduling);
}
CAYENNE_IN(27) // set offset
{
   time_offset = getValue.asInt();
   Serial.print("time_offset : " );
   Serial.println(time_offset);
}

Flamingo Libary

Arduino
Should be in the same folder as the main sketch
/*********************************************************************************************************
 * Based upon collective works by an unknown author, adapted for Cayenne (or Blynck) by Wouter-Jan       *
 * Info Flamingo: http://forum.arduino.cc/index.php?topic=201771.0                                       *
 * Info 433: a self-learning 433 libary in wording: https://forum.fhem.de/index.php/topic,36399.60.html  *
 * *******************************************************************************************************

******************************************************************************** 
** Flamingo_send                                                              **
**                                                                            **
**       Flamingo device commands (on/off)hard coded (not deciphered yet)     **
**       code is 28 byte long. To transfer it in 32 bit code 4 *0             **
**       is added to the left. For programming reason hex code representation **
**       of device code is used. E.g. Remote 0,C,On:                          **
**         code 28 bits: 0001100110111111110100100110                         **
**         code 32 bits: 00011001101111111101001001100000                     **
**         Hex:          19BFD260                                             **
**                                                                            **
**        "Sync" 1 pulse High, 15 pulse low                                   **
**        "1"    1 pulse High, 3 pulse low                                    **
**        "0"    3 pulse High, 1 pulse low                                    **
**        "end"  N/A                                                          **
**                                                                            **
**       For internal ref: Unit 0 = white remote , unit 1 = black remote      **
**                                                                            **
*******************************************************************************/

// Compiler only coding
#define FUNITS  12                                 /* Amount of units supported */
#define FCMDN   2                                  /* Amount of CMD 0 = On, 1 = Off */

// int rfPin = D7;                                 /* with ethernet shield D4 = SS (for SD card) (now in main sketch)*/

// define device codes:

uint32_t fdev[FUNITS][FCMDN] = {0xD9762A10, 0xDAA47850, /* Remote 0 */ 
                                0xDBDA22E0, 0xDBA27220, /* Remote 1 */
                                0x19BFD260, 0x195EEAA0, /* Remote 2 */
                                0x984CC650, 0x9A8C1050, /* Remote 3 */
                                0xDBFFFE90, 0xD91CEF10, /* Remote 4 */
                                0xDBC52FA0, 0xD9E35160, /* Remote 5 */
                                0x19B0FE60, 0x19682B20, /* Remote 6 */
                                0x9924E7D0, 0x9BA928D0, /* Remote 7 */                                        
                                0x25B25B60, 0x24DC2060, /* Remote 8  (not tested) */
                                0x2717B510, 0x275BADD0, /* Remote 9  (not tested) */
                                0xE56BF910, 0xE4D49F50, /* Remote 10 (not tested) */
                                0x65F1C2A0, 0x65B67B60  /* Remote 11 (not tested) */ 
           };                                         


// Define Flamingo_send variables / constants

int fpulse = 300;                              /* Pulse witdh in microseconds */
int fretrans = 5;                              /* Code retransmission         */
uint32_t fsendbuff;
uint32_t fdatabit;
uint32_t fdatamask = 0x80000000;

void Flamingo_Send(int funitc, int fcmd)
{

 // Test if used codes are valid

 if ((funitc < 0) || (funitc >  11)) {                  // check if unit code between 0-11 (Remote 0 to 11)
   Serial.print("Unit error: ");
   Serial.println(funitc);
   return;
 }

 if ((fcmd < 0) || (fcmd > 1)) {                       // check if command = 0 (off) or 1 (on)
   Serial.print("Command error: ");
   Serial.println(fcmd);
   return;
 }
 
 //End test used codes
 Serial.println("");
 Serial.println("Send Flamingo command: ");
 Serial.print("Flamingo Unit = :");
 Serial.println(funitc);
 Serial.print("command = :");
 Serial.println(fcmd);
 // Send Command

 for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {

   fsendbuff = fdev[funitc][fcmd];

   // send SYNC 1P High, 15P low
   Serial.println("Send sync");

   digitalWrite(rfPin, HIGH);
   delayMicroseconds(fpulse * 1);
   digitalWrite(rfPin, LOW);
   delayMicroseconds(fpulse * 15);

   // end send SYNC

   // Send command

   for (int i = 0; i < 28; i++)                                 // Flamingo command is only 28 bits */
   {
     // read data bit
     fdatabit = fsendbuff & fdatamask;                         // Get most left bit
     fsendbuff = (fsendbuff << 1);                             // Shift left

     if (fdatabit != fdatamask)
     { // Write 0
       digitalWrite(rfPin, HIGH);
       delayMicroseconds(fpulse * 3);
       digitalWrite(rfPin, LOW);
       delayMicroseconds(fpulse * 1);
     }
     else
     { // Write 1
       digitalWrite(rfPin, HIGH);
       delayMicroseconds(fpulse * 1);
       digitalWrite(rfPin, LOW);
       delayMicroseconds(fpulse * 3);
     }
   }
 }
   //Serial.println("send code = :");
   //Serial.println(fsendbuff);
   Serial.println(rfPin);
}

Routines

Arduino
Should be in the same folder as the main sketch
void sunsetrise() {

/*  Calculate when sunrises and sunsets based upon GSP-coordinates and date of the year
 *  using TimeLord.h library.
 *  dates are stores as integer and float whereas float simulates a time-notation without semi-column. 
 */
  
  float const LONGITUDE = 4.26; //change this according to your own location
  float const LATITUDE = 52.08; //ditto 

  TimeLord tardis; 
  tardis.TimeZone((60) + check_DST * 60); // tell TimeLord what timezone your RTC / NTP-server is synchronized to. You can ignore DST
  // as long as the RTC never changes back and forth between DST and non-DST
  tardis.Position(LATITUDE, LONGITUDE); // tell TimeLord where in the world we are
  //byte today[] = {  0, 0, 12, 21, 8, 2017    }; // store manual date (at noon) in an array for TimeLord to use
  byte today[] = {  0, 0, 12, dateTime.day, dateTime.month, dateTime.year }; // store RTC date (at noon) in an array for TimeLord to use
  
  if (tardis.SunRise(today)) // if the sun will rise today (it might not, in the [ant]arctic)
     {
     time_sunrise = today[tl_hour] * 60 + today[tl_minute];
     time_sunrise_d = today[tl_hour] * 1.0 + today[tl_minute] / 100.0;
     }
  if (tardis.SunSet(today)) // if the sun will set today (it might not, in the [ant]arctic)
     {
     time_sunset = today[tl_hour] * 60 + today[tl_minute];
     time_sunset_d = today[tl_hour] * 1.0 + today[tl_minute] / 100.0;
     }
  }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  
  void publishSystemUpTime(){ 
    //source: http://community.mydevices.com/t/system-uptime-millis-to-dd-hh-mm-code-optimization-question-esp8266/4434
    long millisecs = millis();
    //systemUpTimeMn = int((millisecs / (1000*60)) % 60);
    //systemUpTimeHr = int((millisecs / (1000*60*60)) % 24);
    //systemUpTimeDy = int((millisecs / (1000*60*60*24)) % 365);
    uptime = int((millisecs / (1000*60*60)) % 24) + int((millisecs / (1000*60)) % 60) / 100.0;
    //Serial.println(uptime);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void DHTroutine() {
    h = dht.readHumidity();
    t = dht.readTemperature();
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.println(" %\t");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.println(" Celcius ");
    Cayenne.virtualWrite(30, t, "temp", "c");
    Cayenne.virtualWrite(31, h, "rel_hum", "p");
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void flamingo_2actions(int tmp_switch, int tmp_switch_value){ //used to invert the flamingo switch

  Cayenne.virtualWrite(tmp_switch, tmp_switch_value);
  Flamingo_Send(tmp_switch, !tmp_switch_value); // ON/OFF

}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void Timeroutine() {
     
    // first parameter: Time zone; second parameter: 1 for European summer time; 2 for US daylight saving time (not implemented yet)
    dateTime = NTPnl.getTime(1.0, 1); // get time from internal clock
    //NTPnl.printDateTime(dateTime);
    time_now = dateTime.hour * 60 + dateTime.minute;
    time_now_d = dateTime.hour * 1.0 + ( dateTime.minute / 100.0);
    
    if (time_now >= time_sunset || time_now <= time_sunrise) {
       Cayenne.virtualWrite(41, 1, "digital_sensor", "d");
       //Serial.println("Night time = 1");
       } else {
       Cayenne.virtualWrite(41, 0, "digital_sensor", "d");
       //Serial.println("Night time = 0");
  }
    if (time_now >= time_sunset + time_offset || time_now <= time_sunrise - time_offset) { //delay for twilight offset set by slider
       Cayenne.virtualWrite(42, 1, "digital_sensor", "d");
       //Cayenne.virtualWrite(42, 1);
       //Serial.println("Twilight = 1");
       } else {
       //Cayenne.virtualWrite(42, 0);
       Cayenne.virtualWrite(42, 0, "digital_sensor", "d");
       //Serial.println("Twilight = 0");
       }
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void Time_DST_refresh(){ //monthly reset of time based upon NTP-servers

  Serial.println("inside Time_DST_refresh()");
  // NTP-server part
  Serial.println("Connecting to NTP-server NL");
  while (!NTPnl.setSNTPtime()) Serial.print("."); // set internal clock
  Serial.print("Time set : ");
  // first parameter: Time zone; second parameter: 1 for European summer time; 2 for US daylight saving time (not implemented yet)
  dateTime = NTPnl.getTime(1.0, 1); // get time from internal clock
  NTPnl.printDateTime(dateTime);
  byte actualHour = dateTime.hour;
  /*
  byte actualMinute = dateTime.minute;
  byte actualsecond = dateTime.second;
  int actualyear = dateTime.year;
  byte actualMonth = dateTime.month;
  byte actualday = dateTime.day;
  byte actualdayofWeek = dateTime.dayofWeek;
  */
  // DST-part
  dateTime_wo_DST = NTPnl.getTime(1.0, 0); // get time from internal clock with out DST correction
  byte Hour_wo_DST =  dateTime_wo_DST.hour;
  if (Hour_wo_DST == dateTime.hour) {
    check_DST = 0;
  } else {
    check_DST = 1;
  }
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

scheduling

Arduino
Should be in the same folder as the main sketch

Some obsolete scheduling because Cayenne's Triggers and scheduling was not working end 2017 as desired. Might be working now though;)
void obsolete_scheduling() {
Serial.println("inside obsolete_scheduling");

//setting switches on !!!!
  if(time_now == time_sunset + time_offset + 11) {
      Cayenne.virtualWrite(13, 1);
      transmitter.sendUnit(1, 1); // Flamingo SF-501PWD unit 1
      Cayenne.virtualWrite(14, 1);
      transmitter.sendUnit(2, 1); // Flamingo SF-501PWD unit 2
  }
  
  if(time_now == time_sunset + time_offset + 1) {
     flamingo_2actions(0, 1);
     flamingo_2actions(2, 1);
     flamingo_2actions(4, 1);
     flamingo_2actions(7, 1);
  }

  if(time_now == time_sunset + time_offset + 24) {
     flamingo_2actions(1, 1);
     flamingo_2actions(3, 1);
  }

  //kerstverlichting
  if(time_now == 8 * 60 ) {
     flamingo_2actions(5, 1);
     flamingo_2actions(6, 1);
  }
  if(time_now == 2 * 60 ) {
     flamingo_2actions(6, 0);
  }

  if(time_now == 22 * 60 + 30 ) {
     flamingo_2actions(3, 0);
  }
  
  if(time_now == 23 * 60 + 40 ) {
     flamingo_2actions(0, 0);
     flamingo_2actions(1, 0);
     flamingo_2actions(2, 0);
     flamingo_2actions(3, 0);
     flamingo_2actions(4, 0);
     flamingo_2actions(5, 0);
     flamingo_2actions(7, 0);
  }
  
  //turn light off by sleeping time
  if(time_now == 5) {
      //Serial.println("inside time_now == (24*60 - 5)");
      Cayenne.virtualWrite(13, 0);
      transmitter.sendUnit(1, 0); // Flamingo SF-501PWD unit 1
  }
  
  // turn lights off by sunrise
  if(time_now == time_sunrise - 30) { // half hour for actual sunrise light switches out
      Cayenne.virtualWrite(14, 0);
      transmitter.sendUnit(2, 0); // Flamingo SF-501PWD unit 2
  }

  if(time_now == 8 * 60 + 15 ) { // turning on some christmas lights by scheduling overide by remote only
    mySwitch.enableTransmit(rfPin);
    mySwitch.switchOn("11111", "10000");
    mySwitch.switchOn("11111", "01000");
    mySwitch.switchOn("11111", "00010");
    mySwitch.disableTransmit();
  }
  
  if(time_now ==  23 * 60 + 5 ) { // turning on some christmas lights by scheduling overide by remote only
  //Serial.println("Switch: woodpile");
    mySwitch.enableTransmit(rfPin);
    mySwitch.switchOff("11111", "10000");
    mySwitch.switchOff("11111", "00100");
    mySwitch.switchOff("11111", "00010");
    mySwitch.disableTransmit();
  }
}

Credits

WJ4IoT

WJ4IoT

0 projects • 2 followers

Comments