Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Christopher Mendez Martinez
Published © GPL3+

No PCB WiFi Smart Switch W/ ESP8266 and Ubidots

On this tutorial I show you how to build your Own Smart ESP8266 WiFi Switch in a perfboard.

IntermediateFull instructions provided2 hours1,658
No PCB WiFi Smart Switch W/ ESP8266 and Ubidots

Things used in this project

Hardware components

ESP8266 ESP-01
Espressif ESP8266 ESP-01
You can buy it here: https://amzn.to/32DlV6r?aff=35
×1
BTA24 Triac
×1
MOC3010
×1
Hi-link 3.3v
×1
Resistor 1k ohm
Resistor 1k ohm
×1
470 1/2 W Resistor
×1
470 1/4 W Resistor
×1
JLCPCB Customized PCB
JLCPCB Customized PCB
×1

Software apps and online services

Arduino IDE
Arduino IDE
Ubidots
Ubidots

Story

Read more

Schematics

Schematics

Here you have a PDF file that will show you all the connetions and the circuitry.

Code

Arduino Code

Processing
Here is the code you need to upload to your ESP8266 with the Arduino IDE
/****************************************

   Libreria

 ****************************************/

#include "UbidotsESPMQTT.h"

/****************************************

   Definir constantes

 ****************************************/

#define TOKEN ".........................." // Your Ubidots TOKEN

#define WIFINAME "..............." //Your SSID
#define WIFIPASS "..............." // Your Wifi Pass

#define DEVICE_LABEL "wifiswitch"

#define VARIABLE_LABEL1  "light"  // Nombre de variable en Ubidots

const int ERROR_VALUE = 65535;  // Valor de error cualquiera

const uint8_t NUMBER_OF_VARIABLES = 2; // Cantidad de variables a las que el programa se va a suscribir
char * variable_labels[NUMBER_OF_VARIABLES] = {VARIABLE_LABEL1}; // Nombres de las variables


#define luz  0
#define boton  2

int seguro = 0;

int ledState = LOW;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = HIGH;   // the previous reading from the input pin

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;

float estadoluz; // Nombre de la variable que se va a usar en el codigo

float value; // Variable para almacenar el dato de entrada.
uint8_t variable; // Para usar en el switch case

Ubidots ubiClient(TOKEN);

WiFiClient client;

/****************************************

   Funciones auxiliares

 ****************************************/

void callback(char* topic, byte* payload, unsigned int length) {
  char* variable_label = (char *) malloc(sizeof(char) * 30);
  get_variable_label_topic(topic, variable_label);
  value = btof(payload, length);
  set_state(variable_label);
  execute_cases();
  free(variable_label);
  /////////////////Bombilla////////////////////

  digitalWrite(luz, estadoluz);

  /////////////////Bombilla////////////////////

}

// Parse topic to extract the variable label which changed value
void get_variable_label_topic(char * topic, char * variable_label) {
  Serial.print("topic:");
  Serial.println(topic);
  sprintf(variable_label, "");
  for (int i = 0; i < NUMBER_OF_VARIABLES; i++) {
    char * result_lv = strstr(topic, variable_labels[i]);
    if (result_lv != NULL) {
      uint8_t len = strlen(result_lv);
      char result[100];
      uint8_t i = 0;
      for (i = 0; i < len - 3; i++) {
        result[i] = result_lv[i];
      }
      result[i] = '\0';
      Serial.print("Label is: ");
      Serial.println(result);
      sprintf(variable_label, "%s", result);
      break;
    }
  }
}

// cast from an array of chars to float value.
float btof(byte * payload, unsigned int length) {
  char * demo = (char *) malloc(sizeof(char) * 10);
  for (int i = 0; i < length; i++) {
    demo[i] = payload[i];
  }
  float value = atof(demo);
  free(demo);
  return value;
}

// State machine to use switch case
void set_state(char* variable_label) {
  variable = 0;
  for (uint8_t i = 0; i < NUMBER_OF_VARIABLES; i++) {
    if (strcmp(variable_label, variable_labels[i]) == 0) {
      break;
    }
    variable++;
  }
  if (variable >= NUMBER_OF_VARIABLES) variable = ERROR_VALUE; // Not valid
}

// Function with switch case to determine which variable changed and assigned the value accordingly to the code variable
void execute_cases() {
  switch (variable) {
    case 0:
      estadoluz = value;
      Serial.print("Luz: ");
      Serial.println(estadoluz);
      Serial.println();
      break;
    case ERROR_VALUE:
      Serial.println("error");
      Serial.println();
      break;
    default:
      Serial.println("default");
      Serial.println();
  }

}
/****************************************

   Funcion principal

 ****************************************/

void setup() {

  // put your setup code here, to run once:
  pinMode(luz, OUTPUT);
  pinMode(boton, INPUT);
  ubiClient.ubidotsSetBroker("industrial.api.ubidots.com"); // Sets the broker properly for the business account
  ubiClient.setDebug(true); // Pass a true or false bool value to activate debug messages
  Serial.begin(115200);
  ubiClient.wifiConnection(WIFINAME, WIFIPASS);
  ubiClient.begin(callback);
  if (!ubiClient.connected()) {

    ubiClient.reconnect();

  }

  char* deviceStatus = getUbidotsDevice(DEVICE_LABEL);

  if (strcmp(deviceStatus, "404") == 0) {
    ubiClient.add(VARIABLE_LABEL1, 0); //Insert your variable Labels and the value to be sent
    ubiClient.ubidotsPublish(DEVICE_LABEL);
    ubiClient.loop();

  }
  ubiClient.ubidotsSubscribe(DEVICE_LABEL, VARIABLE_LABEL1); //Insert the Device and Variable's Labels
  Serial.println(variable_labels[1]);

}

void loop() {


  // put your main code here, to run repeatedly:

  if (!ubiClient.connected()) {
    ubiClient.reconnect();
    ubiClient.ubidotsSubscribe(DEVICE_LABEL, VARIABLE_LABEL1); //Insert the Device and Variable's Labels
  }

  ubiClient.loop();

  // read the state of the switch into a local variable:
  int reading = digitalRead(boton);

  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // 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 (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is LOW
      if (buttonState == LOW) {
        ledState = !ledState;
        // set the LED:
        digitalWrite(luz, ledState);
        ubiClient.add(VARIABLE_LABEL1, ledState); //Insert your variable Labels and the value to be sent
        ubiClient.ubidotsPublish(DEVICE_LABEL);
        delay(100);
      }
    }
  }

  // save the reading. Next time through the loop, it'll be the lastButtonState:
  lastButtonState = reading;

}



char* getUbidotsDevice(char* deviceLabel) {
  char* data = (char *) malloc(sizeof(char) * 700);
  char* response = (char *) malloc(sizeof(char) * 400);
  sprintf(data, "GET /api/v1.6/devices/%s/", deviceLabel);
  sprintf(data, "%s HTTP/1.1\r\n", data);
  sprintf(data, "%sHost: industrial.api.ubidots.com\r\nUser-Agent:googlehome/1.0\r\n", data);
  sprintf(data, "%sX-Auth-Token: %s\r\nConnection: close\r\n\r\n", data, TOKEN);
  if (client.connect("industrial.api.ubidots.com", 80)) {
    client.println(data);
  } else {
    return "e";
  }
  free(data);
  int timeout = 0;
  while (!client.available() && timeout < 5000) {
    timeout++;
    if (timeout >= 4999) {
      return "e";
    }
    delay(1);
  }
  int i = 0;
  while (client.available()) {
    response[i++] = (char)client.read();
    if (i >= 399) {
      break;
    }

  }
  char * pch;
  char * statusCode;
  int j = 0;
  pch = strtok (response, " ");
  while (pch != NULL) {
    if (j == 1 ) {
      statusCode = pch;
    }
    pch = strtok (NULL, " ");
    j++;
  }
  free(response);
  return statusCode;
}

Credits

Christopher Mendez Martinez
35 projects • 76 followers
Electronic Engineer and Tech YouTuber who loves automation, programming and sharing his knowledge with everyone.
Contact

Comments

Please log in or sign up to comment.