Convertir Arduino en un controlador de dispositivos con Alexa

Vamos a convertir, una tarjeta Arduino Wemos (Con modulo wifi), utilizando un modulo de reles, en un accesorio para encender/apagar diferentes dispositivos; luces, ventiladores, calefactores, discos duros o cualquier otro dispositivo que se te ocurra.

Para realizar esta tarea nos hace falta:

  • Una tarjeta Wemos.
  • Un modulo de reles, puede ser de 1, 2, 4 u 8 reles.
  • Darnos de alta en la web https://sinric.com/
  • Instalar la skill Sinric en Amazon Alexa.

Sinric es una Api gratuita desde la que vamos a poder crear todos aquellos dispositivos que necesitemos controlar. Por cada dispositivo que creamos, Sinric asigna un ID para su identificación.

Para añadir un nuevo dispositivo pulsamos en el botón “ADD” de la sección “Smart Home Device“, se abrira un panel como el de la imagen superior.

  • Friendly Name. Es el nombre con el que invocaremos a Alexa, para gestionar nuestro dispositivo, encender / apagar.
  • Description. La descripción del dispositivo.
  • Device Type. De la lista desplegable seleccionamos el que más se adapte a nuestro tipo de dispositivo.

Guardamos el nuevo dispositivo, y realizamos la misma operación para crear todos los que necesitemos.

En la pantalla principal de sinric veremos todos los dispositivos creados, es importante apuntar los ID que la aplicación ha generado. También debemos anotar el “Your API Key“, se encuentra en la parte superior, con estos datos podremos controlar los dispositivos desde nuestra Arduino.

En este repositorio de github podemos encontrar los archivos “ino” para la tarjeta Arduino, existen diferentes ejemplos para el uso de la api de sinric.

Aqui tienes el código que utilizo para gestionar mis dispositivos a traves de Alexa. Se pueden controlar 4 dispositivos, pero es muy fácil añadir más.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsClient.h> //  https://github.com/kakopappa/sinric/wiki/How-to-add-dependency-libraries
#include <ArduinoJson.h> // https://github.com/kakopappa/sinric/wiki/How-to-add-dependency-libraries
#include <StreamString.h>

ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
WiFiClient client;

#define MyApiKey "Tu-Api-Key-de-Sinric" // TODO: Change to your sinric API Key. Your API Key is displayed on sinric.com dashboard
#define MySSID "El-Nombre-de-tu-WIFI" // TODO: Change to your Wifi network SSID
#define MyWifiPassword "La-Contraseña-de-tu-WIFI" // TODO: Change to your Wifi network password

#define HEARTBEAT_INTERVAL 300000 // 5 Minutes 

const int relayPin1 = D1;
const int relayPin2 = D2;
const int relayPin3 = D3;
const int relayPin4 = D4;

uint64_t heartbeatTimestamp = 0;
bool isConnected = false;

void setPowerStateOnServer(String deviceId, String value);
void setTargetTemperatureOnServer(String deviceId, String value, String scale);

// deviceId is the ID assgined to your smart-home-device in sinric.com dashboard. Copy it from dashboard and paste it here

void turnOn(String deviceId) {

  // Device 1
  if (deviceId == "El-ID-de-tu-Dispositivo") // Device ID of first device
  {
    Serial.print("Turn on device id: ");
    Serial.println(deviceId);

    digitalWrite(relayPin1, HIGH); // turn on relay with voltage HIGH
  }
  else {
    Serial.print("Turn on for unknown device id: ");
    Serial.println(deviceId);
  }

  // Device 2
  if (deviceId == "El-ID-de-tu-Dispositivo") // Device ID of first device
  {
    Serial.print("Turn on device id: ");
    Serial.println(deviceId);

    digitalWrite(relayPin2, HIGH); // turn on relay with voltage HIGH
  }
  else {
    Serial.print("Turn on for unknown device id: ");
    Serial.println(deviceId);
  }

  // Device 3
  if (deviceId == "El-ID-de-tu-Dispositivo") // Device ID of first device
  {
    Serial.print("Turn on device id: ");
    Serial.println(deviceId);

    digitalWrite(relayPin3, HIGH); // turn on relay with voltage HIGH
  }
  else {
    Serial.print("Turn on for unknown device id: ");
    Serial.println(deviceId);
  }

  // Device 4
  if (deviceId == "El-ID-de-tu-Dispositivo") // Device ID of first device
  {
    Serial.print("Turn on device id: ");
    Serial.println(deviceId);

    digitalWrite(relayPin4, HIGH); // turn on relay with voltage HIGH
  }
  else {
    Serial.print("Turn on for unknown device id: ");
    Serial.println(deviceId);
  }
}

void turnOff(String deviceId) {

  // Device 1
  if (deviceId == "El-ID-de-tu-Dispositivo") // Device ID of first device
  {
    Serial.print("Turn off Device ID: ");
    Serial.println(deviceId);

    digitalWrite(relayPin1, LOW);  // turn off relay with voltage LOW
  }
  else {
    Serial.print("Turn off for unknown device id: ");
    Serial.println(deviceId);
  }

  // Device 2
  if (deviceId == "El-ID-de-tu-Dispositivo") // Device ID of first device
  {
    Serial.print("Turn off Device ID: ");
    Serial.println(deviceId);

    digitalWrite(relayPin2, LOW);  // turn off relay with voltage LOW
  }
  else {
    Serial.print("Turn off for unknown device id: ");
    Serial.println(deviceId);
  }

  // Device 3
  if (deviceId == "El-ID-de-tu-Dispositivo") // Device ID of first device
  {
    Serial.print("Turn off Device ID: ");
    Serial.println(deviceId);

    digitalWrite(relayPin3, LOW);  // turn off relay with voltage LOW
  }
  else {
    Serial.print("Turn off for unknown device id: ");
    Serial.println(deviceId);
  }

  // Device 4
  if (deviceId == "El-ID-de-tu-Dispositivo") // Device ID of first device
  {
    Serial.print("Turn off Device ID: ");
    Serial.println(deviceId);

    digitalWrite(relayPin4, LOW);  // turn off relay with voltage LOW
  }
  else {
    Serial.print("Turn off for unknown device id: ");
    Serial.println(deviceId);
  }
}

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
  switch (type) {
    case WStype_DISCONNECTED:
      isConnected = false;
      Serial.printf("[WSc] Webservice disconnected from sinric.com!\n");
      break;
    case WStype_CONNECTED: {
        isConnected = true;
        Serial.printf("[WSc] Service connected to sinric.com at url: %s\n", payload);
        Serial.printf("Waiting for commands from sinric.com ...\n");
      }
      break;
    case WStype_TEXT: {
        Serial.printf("[WSc] get text: %s\n", payload);
        // Example payloads

        // For Switch or Light device types
        // {"deviceId": xxxx, "action": "setPowerState", value: "ON"} // https://developer.amazon.com/docs/device-apis/alexa-powercontroller.html

        // For Light device type
        // Look at the light example in github

        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject((char*)payload);
        String deviceId = json ["deviceId"];
        String action = json ["action"];

        if (action == "setPowerState") { // Switch or Light
          String value = json ["value"];
          if (value == "ON") {
            turnOn(deviceId);
          } else {
            turnOff(deviceId);
          }
        }
        else if (action == "SetTargetTemperature") {
          String deviceId = json ["deviceId"];
          String action = json ["action"];
          String value = json ["value"];
        }
        else if (action == "test") {
          Serial.println("[WSc] received test command from sinric.com");
        }
      }
      break;
    case WStype_BIN:
      Serial.printf("[WSc] get binary length: %u\n", length);
      break;
  }
}

void setup() {
  Serial.begin(115200);

  // Relay PIN eg: https://github.com/wemos/D1_mini_Examples/blob/master/examples/04.Shields/Relay_Shield/Blink/Blink.ino
  pinMode(relayPin1, OUTPUT);
  pinMode(relayPin2, OUTPUT);
  pinMode(relayPin3, OUTPUT);
  pinMode(relayPin4, OUTPUT);
  

  WiFiMulti.addAP(MySSID, MyWifiPassword);
  Serial.println();
  Serial.print("Connecting to Wifi: ");
  Serial.println(MySSID);

  // Waiting for Wifi connect
  while (WiFiMulti.run() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  if (WiFiMulti.run() == WL_CONNECTED) {
    Serial.println("");
    Serial.print("WiFi connected. ");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  }

  // server address, port and URL
  webSocket.begin("iot.sinric.com", 80, "/");

  // event handler
  webSocket.onEvent(webSocketEvent);
  webSocket.setAuthorization("apikey", MyApiKey);

  // try again every 5000ms if connection has failed
  webSocket.setReconnectInterval(5000);   // If you see 'class WebSocketsClient' has no member named 'setReconnectInterval' error update arduinoWebSockets
}

void loop() {
  webSocket.loop();

  if (isConnected) {
    uint64_t now = millis();

    // Send heartbeat in order to avoid disconnections during ISP resetting IPs over night. Thanks @MacSass
    if ((now - heartbeatTimestamp) > HEARTBEAT_INTERVAL) {
      heartbeatTimestamp = now;
      webSocket.sendTXT("H");
    }
  }
}

// If you are going to use a push button to on/off the switch manually, use this function to update the status on the server
// so it will reflect on Alexa app.
// eg: setPowerStateOnServer("deviceid", "ON")

// Call ONLY If status changed. DO NOT CALL THIS IN loop() and overload the server.
void setPowerStateOnServer(String deviceId, String value) {
  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["deviceId"] = deviceId;
  root["action"] = "setPowerState";
  root["value"] = value;
  StreamString databuf;
  root.printTo(databuf);

  webSocket.sendTXT(databuf);
}

//eg: setPowerStateOnServer("deviceid", "CELSIUS", "25.0")

// Call ONLY If status changed. DO NOT CALL THIS IN loop() and overload the server.
void setTargetTemperatureOnServer(String deviceId, String value, String scale) {
  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["action"] = "SetTargetTemperature";
  root["deviceId"] = deviceId;

  JsonObject& valueObj = root.createNestedObject("value");
  JsonObject& targetSetpoint = valueObj.createNestedObject("targetSetpoint");
  targetSetpoint["value"] = value;
  targetSetpoint["scale"] = scale;

  StreamString databuf;
  root.printTo(databuf);

  webSocket.sendTXT(databuf);
}

Rellena los siguientes apartados con tus datos:

  • Tu-Api-Key-de-Sinric.
  • El-Nombre-de-tu-WIFI
  • La-Contraseña-de-tu-WIFI
  • El-ID-de-tu-Dispositivo

Carga el archivo “ino” en la tarjeta Arduino.

Ahora queda montar tu tarjeta Arduino Wemos con la placa de reles, hacer las conexiones entre Arduino y reles, y las conexiones para la corriente electrica de los enchufes que utilices.

Para comprobar que todo funciona correctamente, aun nos queda realizar un paso más.

Desde la aplicación “Amazon Aleza“, de tu dispositivo móvil, instala la skill de “Sinric“, puedes ver más información pinchando en el enlace.

Una vez configurada debes pulsar en “Más” y “Añadir dispositivo“. Pulsa sobre uno de los dispositivos, por ejemplo “Luz“, y en la siguiente pantalla, pulsa en “Otro“. Pulsa en el botón “Detectar Dispositivos“. Si todo fue bien, pasados unos minutos, Alexa habra detectado los nuevos dispositivos.

Dile a Alexa que encienda alguno de los dispositivos que has creado en Sinric.

Recuerda que estos dispositivos se comportan exactamente como cualquier otro dispositivo que has comprado. Creando rutinas, puedes programarlo para que se encienda/apage a una hora determinada o cuando se produzca un determinado evento.



Si encuentras esta noticia interesante la puedes compartir en tus redes sociales, a tus seguidores les puede gustar. Utiliza los botones que tienes más abajo.

Share

Comments are closed.