sábado, 12 de agosto de 2017

Tutorial #15 ESP8266 (Parte5) – Diseño en tu Dashboard MQTT usando CSS y JavaScript

Este es el quinto tutorial de IOT (internet de las cosas) usando MQTT en un ESP8266; en estos videos (Parte A y B) les muestro como agregarle diseño al dashboard (tablero) que vimos en el tutorial 13, para eso vamos a hacer uso de CSS y JavaScript.

Parte A:


Parte B:


tutorial15.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Tutorial 15</title>
    <script src='mqttws31.js' type='text/javascript'></script> 
    <!-- https://api.cloudmqtt.com/sso/js/mqttws31.js -->
    <script src="raphael-2.1.4.min.js"></script>
    <script src="justgage.js"></script>    
  </head>
  <style type="text/css">
    .a200x160px {
      width: 200px;
      height: 160px;
    }
    img {
      margin-left: 75px;
    }

    .switch {
      position: relative;
      display: inline-block;
      width: 120px;
      height: 68px;
    }

    .switch input {display:none;}

    .slider {
      position: absolute;
      cursor: pointer;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: #ccc;
      -webkit-transition: .4s;
      transition: .4s;
    }

    .slider:before {
      position: absolute;
      content: "";
      height: 52px;
      width: 52px;
      left: 8px;
      bottom: 8px;
      background-color: white;
      -webkit-transition: .4s;
      transition: .4s;
    }

    input:checked + .slider {
      background-color: red;
    }

    input:focus + .slider {
      box-shadow: 0 0 1px #2196F3;
    }

    input:checked + .slider:before {
      -webkit-transform: translateX(52px);
      -ms-transform: translateX(52px);
      transform: translateX(52px);
    }

    .slider.round {
      border-radius: 68px;
    }

    .slider.round:before {
      border-radius: 50%;
    }

    input[type=range] {
      height: 26px;
      -webkit-appearance: none;
      margin: 10px 0;
      width: 120px;
    }
    input[type=range]:focus {
      outline: none;
    }
    input[type=range]::-webkit-slider-runnable-track {
      width: 100%;
      height: 14px;
      cursor: pointer;
      animate: 0.2s;
      box-shadow: 1px 1px 1px #50555C;
      background: #50555C;
      border-radius: 14px;
      border: 0px solid #000000;
    }
    input[type=range]::-webkit-slider-thumb {
      box-shadow: 0px 0px 0px #000000;
      border: 0px solid #000000;
      height: 20px;
      width: 40px;
      border-radius: 12px;
      background: green;
      cursor: pointer;
      -webkit-appearance: none;
      margin-top: -3px;
    }
    input[type=range]:focus::-webkit-slider-runnable-track {
      background: #50555C;
    }
   
    input[type=range]:focus::-ms-fill-lower {
      background: #50555C;
    }
    input[type=range]:focus::-ms-fill-upper {
      background: #50555C;
    }
  </style>
  <body>
      <div id="gauge" class="a200x160px"></div>
      <div>
        <img id="imgPulsador" src="nopresionado.png">
      </div>
      <div>
         <svg width="100" height="75" viewBox="0 0 640 480">
         <defs>
          <linearGradient id="svg_6" x1="0" y1="0" x2="1" y2="0">
           <stop stop-color="#bfbfbf" offset="0"/>
           <stop stop-color="#404040" offset="1"/>
          </linearGradient>
          <linearGradient id="svg_11" x1="0" y1="0" x2="1" y2="1" spreadMethod="pad">
           <stop id="led1" stop-color="#000000" stop-opacity="0.992188" offset="0"/>
           <stop stop-color="#820101" stop-opacity="0.988281" offset="1"/>
          </linearGradient>
          <linearGradient id="svg_14" x1="0" y1="0" x2="1" y2="1" spreadMethod="pad">
           <stop stop-color="#ffffff" stop-opacity="0.996094" offset="0"/>
           <stop stop-color="#d30606" stop-opacity="0.984375" offset="0.703125"/>
          </linearGradient>
         </defs>
         <g>
          <title>Layer 1</title>
          <circle fill="url(#svg_6)" stroke-width="17.5" stroke-linecap="round" cx="320" cy="240" r="196.125" id="svg_3" fill-opacity="0.77" transform="rotate(90, 320, 240)"/>
          <circle fill="url(#svg_6)" stroke-width="17.5" stroke-linecap="round" fill-opacity="0.64" cx="319.252837" cy="239.999045" r="160" id="svg_7"/>
          <circle fill="url(#svg_11)" stroke-width="17.5" stroke-linecap="round" cx="320.000535" cy="240.001698" r="150" id="svg_8"/>
          <ellipse fill="url(#svg_14)" stroke-width="17.5" stroke-linecap="round" cx="250.179609" cy="170.124194" rx="75.675959" ry="44.402987" id="svg_20" transform="rotate(-47.7626, 250.18, 170.125)"/>
         </g>
        </svg>
        <label class="switch">
          <input type="checkbox" onclick='OnOff2()'>
          <span class="slider round"></span>
        </label>
      </div>
      <div>
         <svg width="100" height="75" viewBox="0 0 640 480">
         <defs>
          <linearGradient id="svg_26" x1="0" y1="0" x2="1" y2="0">
           <stop stop-color="#bfbfbf" offset="0"/>
           <stop stop-color="#404040" offset="1"/>
          </linearGradient>
          <linearGradient id="svg_211" x1="0" y1="0" x2="1" y2="1" spreadMethod="pad">
           <stop id="led2" stop-color="rgb(0, 0, 0)" stop-opacity="0.992188" offset="0"/>
           <stop stop-color="#018201" stop-opacity="0.988281" offset="1"/>
          </linearGradient>
          <linearGradient id="svg_214" x1="0" y1="0" x2="1" y2="1" spreadMethod="pad">
           <stop stop-color="#ffffff" stop-opacity="0.996094" offset="0"/>
           <stop stop-color="#06d306" stop-opacity="0.984375" offset="0.703125"/>
          </linearGradient>
         </defs>
         <g>
          <title>Layer 1</title>
          <circle fill="url(#svg_6)" stroke-width="17.5" stroke-linecap="round" cx="320" cy="240" r="196.125" id="svg_23" fill-opacity="0.77" transform="rotate(90, 320, 240)"/>
          <circle fill="url(#svg_6)" stroke-width="17.5" stroke-linecap="round" fill-opacity="0.64" cx="319.252837" cy="239.999045" r="160" id="svg_27"/>
          <circle fill="url(#svg_211)" stroke-width="17.5" stroke-linecap="round" cx="320.000535" cy="240.001698" r="150" id="svg_28"/>
          <ellipse fill="url(#svg_214)" stroke-width="17.5" stroke-linecap="round" cx="250.179609" cy="170.124194" rx="75.675959" ry="44.402987" id="svg_220" transform="rotate(-47.7626, 250.18, 170.125)"/>
         </g>
        </svg>
        <input type="range" id="myRange" min="0" max="1023"  onmouseup="enviarSalidaAnalogica()">
      </div>
    <script>      
      usuario = 'placa2';
      contrasena = '12345678';

      var g = new JustGage({
        id: "gauge",
        min: 0,
        max: 50,
        title: "Temperatura ºC"
      });

      estadoDigital = "OFF";

      function OnOff2(){
        if (estadoDigital == "OFF"){
          message = new Paho.MQTT.Message("ON");
          message.destinationName = '/' + usuario + '/salidaDigital'
          client.send(message);
        }
        else if (estadoDigital == "ON"){
          message = new Paho.MQTT.Message("OFF");
          message.destinationName = '/' + usuario + '/salidaDigital'
          client.send(message);
        }
      };

      function enviarSalidaAnalogica(){
        var dato = document.getElementById("myRange").value;
        message = new Paho.MQTT.Message(dato);
        message.destinationName = '/' + usuario + '/salidaAnalogica'
        client.send(message);
      };
       
      // called when the client connects
      function onConnect() {
        // Once a connection has been made, make a subscription and send a message.
        console.log("onConnect");
        client.subscribe("#");
      }
        
      // called when the client loses its connection
      function onConnectionLost(responseObject) {
        if (responseObject.errorCode !== 0) {
          console.log("onConnectionLost:", responseObject.errorMessage);
          setTimeout(function() { client.connect() }, 5000);
        }
      }
        
      // called when a message arrives
      function onMessageArrived(message) {
        if (message.destinationName == '/' + usuario + '/' + 'temperatura') { //acá coloco el topic
            //document.getElementById("temperatura").textContent = message.payloadString  + " ºC";
            g.refresh(message.payloadString);
        }
        if (message.destinationName == '/' + usuario + '/' + 'pulsador') { //acá coloco el topic
            //document.getElementById("pulsador").textContent = message.payloadString;
            if (message.payloadString == "presionado"){
              document.getElementById("imgPulsador").src = "presionado.png"
            }
            else if (message.payloadString == "NO presionado"){
              document.getElementById("imgPulsador").src = "nopresionado.png"
            }
         }
        if (message.destinationName == '/' + usuario + '/' + 'salidaDigital') { //acá coloco el topic
            //document.getElementById("salidaDigital").textContent = message.payloadString;
            estadoDigital = message.payloadString;

            if (estadoDigital == "OFF") {
              document.getElementById("led1").setAttribute("stop-color", "#110000");
            }
            else if (estadoDigital == "ON") {
              document.getElementById("led1").setAttribute("stop-color", "#ff0000");
            }
        }
        if (message.destinationName == '/' + usuario + '/' + 'salidaAnalogica') { //acá coloco el topic
            //document.getElementById("salidaAnalogica").textContent = message.payloadString;
            document.getElementById("led2").setAttribute("stop-color", "rgb(0, " + parseInt(message.payloadString/4) + ", 0)")
        }
      }

        function onFailure(invocationContext, errorCode, errorMessage) {
          var errDiv = document.getElementById("error");
          errDiv.textContent = "Could not connect to WebSocket server, most likely you're behind a firewall that doesn't allow outgoing connections to port 39627";
          errDiv.style.display = "block";
        }
        
        var clientId = "ws" + Math.random();
        // Create a client instance
        var client = new Paho.MQTT.Client("m13.cloudmqtt.com", 31948, clientId);
        
        // set callback handlers
        client.onConnectionLost = onConnectionLost;
        client.onMessageArrived = onMessageArrived;
        
        // connect the client
        client.connect({
          useSSL: true,
          userName: usuario,
          password: contrasena,
          onSuccess: onConnect,
          onFailure: onFailure
        });        
    </script>
  </body>
</html>

Enlaces externos:

http://justgage.com
https://www.flaticon.com/free-icon/one-finger-click-black-hand-symbol_56011
https://www.flaticon.com/free-icon/touch-of-one-finger-of-solid-black-hand-symbol_55421
http://www.downloadclipart.net/svg/18483-led-red-off-svg.svg
https://www.w3schools.com/howto/howto_css_switch.asp
http://www.cssportal.com/style-input-range/

sábado, 5 de agosto de 2017

Tutorial #14 ESP8266 (Parte4) – Login en tu Dashboard MQTT

Este es el cuarto tutorial de IOT usando MQTT en un ESP8266; es un complemento del número 13, en el que les mostré cómo hacer sus propios dashboards (tableros).  En este video muestro cómo hacer un login previo de exactamente el mismo ejemplo anterior. En el tutorial muestro como hacer la aplicación web usando PHP (además de HTML y JavaScript), tanto en un servidor local como en un servidor externo.



index.html:

<!DOCTYPE html>
<html >
<head>
  <meta charset="UTF-8">
  <title>Login - Tutorial 14</title>
</head>
<body>
  <form action="login.php" method="POST">
    <input type="text" name="user" placeholder="usuario">
    <input type="password" name="pass" placeholder="contraseña">
    <input type="submit" name="Enviar" >
  </form>
</body>
</body>
</html>

login.php:

<?php

$user = $_POST ['user'];
$pass = $_POST ['pass'];

require_once ('tutorial14A.html');
echo "      
  usuario = '$user';
  contrasena = '$pass';
";
require_once ('tutorial14B.html');

?>

tutorail14A.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Tutorial 14</title>
    <script src='mqttws31.js' type='text/javascript'></script> 
    <!-- https://api.cloudmqtt.com/sso/js/mqttws31.js -->    
  </head>
  <body>
      <div>
        <h2>Suscripciones:</h2>
      </div>
      <div>
        <a>Temperatura: </a>
        <a id ="temperatura">-</a>
      </div>
      <div>
        <a>Pulsador: </a>
        <a id ="pulsador">-</a>
      </div>
      <div>
        <a>Salida Digital: </a>
        <a id ="salidaDigital">-</a>
      </div>
      <div>
        <a>Salida Analógica: </a>
        <a id ="salidaAnalogica">-</a>
      </div>
      <div>
        <h2>Publicaciones:</h2>
      </div>
      <div>
        <a>Salida Digital: </a>
        <button type='button' onclick='OnOff("ON")'>ON</button>
        <button type='button' onclick='OnOff("OFF")'>OFF</button>
      </div>
      <div>
        <a>Salida Analógica: </a>
        <input type="range" id="myRange" min="0" max="1023"  onmouseup="enviarSalidaAnalogica()">
      </div>
    <script>

tutorail14B.html:


      function OnOff(dato){
        message = new Paho.MQTT.Message(dato);
        message.destinationName = '/' + usuario + '/salidaDigital'
        client.send(message);
      };

      function enviarSalidaAnalogica(){
        var dato = document.getElementById("myRange").value;
        message = new Paho.MQTT.Message(dato);
        message.destinationName = '/' + usuario + '/salidaAnalogica'
        client.send(message);
      };
       
      // called when the client connects
      function onConnect() {
        // Once a connection has been made, make a subscription and send a message.
        console.log("onConnect");
        client.subscribe("#");
      }
        
      // called when the client loses its connection
      function onConnectionLost(responseObject) {
        if (responseObject.errorCode !== 0) {
          console.log("onConnectionLost:", responseObject.errorMessage);
          setTimeout(function() { client.connect() }, 5000);
        }
      }
        
      // called when a message arrives
      function onMessageArrived(message) {
        if (message.destinationName == '/' + usuario + '/' + 'temperatura') { //acá coloco el topic
            document.getElementById("temperatura").textContent = message.payloadString  + " ºC";
        }
        if (message.destinationName == '/' + usuario + '/' + 'pulsador') { //acá coloco el topic
            document.getElementById("pulsador").textContent = message.payloadString;
        }
        if (message.destinationName == '/' + usuario + '/' + 'salidaDigital') { //acá coloco el topic
            document.getElementById("salidaDigital").textContent = message.payloadString;
        }
        if (message.destinationName == '/' + usuario + '/' + 'salidaAnalogica') { //acá coloco el topic
            document.getElementById("salidaAnalogica").textContent = message.payloadString;
        }
      }

        function onFailure(invocationContext, errorCode, errorMessage) {
          var errDiv = document.getElementById("error");
          errDiv.textContent = "Could not connect to WebSocket server, most likely you're behind a firewall that doesn't allow outgoing connections to port 39627";
          errDiv.style.display = "block";
        }
        
        var clientId = "ws" + Math.random();
        // Create a client instance
        var client = new Paho.MQTT.Client("m11.cloudmqtt.com", 30722, clientId);
        
        // set callback handlers
        client.onConnectionLost = onConnectionLost;
        client.onMessageArrived = onMessageArrived;
        
        // connect the client
        client.connect({
          useSSL: true,
          userName: usuario,
          password: contrasena,
          onSuccess: onConnect,
          onFailure: onFailure
        });        
    </script>
  </body>
</html>

domingo, 30 de julio de 2017

Tutorial #13 ESP8266 (Parte3) - Tus Propios Dashboards (Tableros) MQTT

En la tercera parte de los tutoriales de IOT usando MQTT en ESP8266, explico cómo hacer nuestros propios dashboards (tableros), valiéndonos de HTML y JavaScript; lo que nos permite controlar y monitorear nuestros dispositivos mediante una aplicación web, ya sea desde una PC, tablet, smartphone, etc. Si bien el ejemplo es muy sencillo y carece de diseño, es perfectamente funcional, ya que le idea del video es que se entiendan los conceptos y en futuros videos contemplaremos el diseño, la seguridad, etc.


tutorial13.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Tutorial 13</title>
    <script src='mqttws31.js' type='text/javascript'></script> 
    <!-- https://api.cloudmqtt.com/sso/js/mqttws31.js -->    
  </head>
  <body>
      <div>
        <h2>Suscripciones:</h2>
      </div>
      <div>
        <a>Temperatura: </a>
        <a id ="temperatura">-</a>
      </div>
      <div>
        <a>Pulsador: </a>
        <a id ="pulsador">-</a>
      </div>
      <div>
        <a>Salida Digital: </a>
        <a id ="salidaDigital">-</a>
      </div>
      <div>
        <a>Salida Analógica: </a>
        <a id ="salidaAnalogica">-</a>
      </div>
      <div>
        <h2>Publicaciones:</h2>
      </div>
      <div>
        <a>Salida Digital: </a>
        <button type='button' onclick='OnOff("ON")'>ON</button>
        <button type='button' onclick='OnOff("OFF")'>OFF</button>
      </div>
      <div>
        <a>Salida Analógica: </a>
        <input type="range" id="myRange" min="0" max="1023"  onmouseup="enviarSalidaAnalogica()">
      </div>
    <script>      
      usuario = 'placa1';
      contrasena = '12345678';

      function OnOff(dato){
        message = new Paho.MQTT.Message(dato);
        message.destinationName = '/' + usuario + '/salidaDigital'
        client.send(message);
      };

      function enviarSalidaAnalogica(){
        var dato = document.getElementById("myRange").value;
        message = new Paho.MQTT.Message(dato);
        message.destinationName = '/' + usuario + '/salidaAnalogica'
        client.send(message);
      };
       
      // called when the client connects
      function onConnect() {
        // Once a connection has been made, make a subscription and send a message.
        console.log("onConnect");
        client.subscribe("#");
      }
        
      // called when the client loses its connection
      function onConnectionLost(responseObject) {
        if (responseObject.errorCode !== 0) {
          console.log("onConnectionLost:", responseObject.errorMessage);
          setTimeout(function() { client.connect() }, 5000);
        }
      }
        
      // called when a message arrives
      function onMessageArrived(message) {
        if (message.destinationName == '/' + usuario + '/' + 'temperatura') { //acá coloco el topic
            document.getElementById("temperatura").textContent = message.payloadString  + " ºC";
        }
        if (message.destinationName == '/' + usuario + '/' + 'pulsador') { //acá coloco el topic
            document.getElementById("pulsador").textContent = message.payloadString;
        }
        if (message.destinationName == '/' + usuario + '/' + 'salidaDigital') { //acá coloco el topic
            document.getElementById("salidaDigital").textContent = message.payloadString;
        }
        if (message.destinationName == '/' + usuario + '/' + 'salidaAnalogica') { //acá coloco el topic
            document.getElementById("salidaAnalogica").textContent = message.payloadString;
        }
      }

        function onFailure(invocationContext, errorCode, errorMessage) {
          var errDiv = document.getElementById("error");
          errDiv.textContent = "Could not connect to WebSocket server, most likely you're behind a firewall that doesn't allow outgoing connections to port 39627";
          errDiv.style.display = "block";
        }
        
        var clientId = "ws" + Math.random();
        // Create a client instance
        var client = new Paho.MQTT.Client("m11.cloudmqtt.com", 30722, clientId);
        
        // set callback handlers
        client.onConnectionLost = onConnectionLost;
        client.onMessageArrived = onMessageArrived;
        
        // connect the client
        client.connect({
          useSSL: true,
          userName: usuario,
          password: contrasena,
          onSuccess: onConnect,
          onFailure: onFailure
        });        
    </script>
  </body>
</html>

sábado, 29 de julio de 2017

Tutorial #12 ESP8266 (Parte2) - MQTT + CloudMQTT + App de Android LinearMQTT

Esta es la segunda parte sobre los tutoriales de MQTT en ESP8266, en este caso muestro como configurar la aplicación de Android LinerMQTT, para hacer un tablero (dashboard) para control nuestro ESP8266 desde un smartphone. Con estos 2 tutoriales ya podrían tener una solución completa de IOT (Internet de las Cosas),con entradas y salidas tanto digitales como analógicas.


domingo, 23 de julio de 2017

Tutorial #11 ESP8266 (Parte1) - MQTT + CloudMQTT

Este tutorial de IOT (internet de las cosas) es la primera parte de una serie de tutoriales sobre MQTT en ESP8266, para esto nos valemos del servicio gratuito de CloudMQTT.com

Vamos a usar exactamente el mismo hardware del tutorial 5(.../tutorial-5-esp8266-mqtt-ioadafruitcom.html), donde tenemos una entrada digital (pulsador), una entrada analógica (sensor de temperatura LM35), una salida digital (LED Rojo) y una salida analógica PWM (LED Verde).

En el video muestro como controlar la placa desde la consola de CloudMQTT; en próximos tutoriales voy a explicar cómo controlarlo desde una aplicación de Android, hacer nuestros propios tableros usando WebSocket, controlarlo desde Python, etc.



Código Fuente:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

//-------------------VARIABLES GLOBALES--------------------------
int contconexion = 0;

const char *ssid = "---";
const char *password = "---";
char   SERVER[50]   = "75.101.131.202"; //"m11.cloudmqtt.com"
int    SERVERPORT   = 10722;
String USERNAME = "placa1";   
char   PASSWORD[50] = "12345678";     

unsigned long previousMillis = 0;

char charPulsador [15];
String strPulsador;
String strPulsadorUltimo;

char PLACA[50];

char valueStr[15];
String strtemp = "";
char TEMPERATURA[50];
char PULSADOR[50];
char SALIDADIGITAL[50];
char SALIDAANALOGICA[50];


//-------------------------------------------------------------------------
WiFiClient espClient;
PubSubClient client(espClient);

//------------------------CALLBACK-----------------------------
void callback(char* topic, byte* payload, unsigned int length) {

  char PAYLOAD[5] = "    ";
  
  Serial.print("Mensaje Recibido: [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    PAYLOAD[i] = (char)payload[i];
  }
  Serial.println(PAYLOAD);

  if (String(topic) ==  String(SALIDADIGITAL)) {
    if (payload[1] == 'N'){
     digitalWrite(12, HIGH);
    }
    if (payload[1] == 'F'){
      digitalWrite(12, LOW);
    }
  }

  if (String(topic) ==  String(SALIDAANALOGICA)) {
    analogWrite(13, String(PAYLOAD).toInt());
  }
}

//------------------------RECONNECT-----------------------------
void reconnect() {
  uint8_t retries = 3;
  // Loop hasta que estamos conectados
  while (!client.connected()) {
    Serial.print("Intentando conexion MQTT...");
    // Crea un ID de cliente al azar
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    USERNAME.toCharArray(PLACA, 50);
    if (client.connect("", PLACA, PASSWORD)) {
      Serial.println("conectado");
      client.subscribe(SALIDADIGITAL);
      client.subscribe(SALIDAANALOGICA);
    } else {
      Serial.print("fallo, rc=");
      Serial.print(client.state());
      Serial.println(" intenta nuevamente en 5 segundos");
      // espera 5 segundos antes de reintentar
      delay(5000);
    }
    retries--;
    if (retries == 0) {
      // esperar a que el WDT lo reinicie
      while (1);
    }
  }
}

//------------------------SETUP-----------------------------
void setup() {

  //prepara GPI13 y 12 como salidas 
  pinMode(13, OUTPUT); // D7 salida analógica
  analogWrite(13, 0); // analogWrite(pin, value);
  pinMode(12, OUTPUT); // D6 salida digital
  digitalWrite(12, LOW);

  // Entradas
  pinMode(14, INPUT); // D5

  // Inicia Serial
  Serial.begin(115200);
  Serial.println("");

  // Conexión WIFI
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED and contconexion <50) { //Cuenta hasta 50 si no se puede conectar lo cancela
    ++contconexion;
    delay(500);
    Serial.print(".");
  }
  if (contconexion <50) {
      //para usar con ip fija
      IPAddress ip(192,168,1,156); 
      IPAddress gateway(192,168,1,1); 
      IPAddress subnet(255,255,255,0); 
      WiFi.config(ip, gateway, subnet); 
      
      Serial.println("");
      Serial.println("WiFi conectado");
      Serial.println(WiFi.localIP());
  }
  else { 
      Serial.println("");
      Serial.println("Error de conexion");
  }
  
  client.setServer(SERVER, SERVERPORT);
  client.setCallback(callback);

  String temperatura = "/" + USERNAME + "/" + "temperatura"; 
  temperatura.toCharArray(TEMPERATURA, 50);
  String pulsador = "/" + USERNAME + "/" + "pulsador"; 
  pulsador.toCharArray(PULSADOR, 50);
  String salidaDigital = "/" + USERNAME + "/" + "salidaDigital"; 
  salidaDigital.toCharArray(SALIDADIGITAL, 50);
  String salidaAnalogica = "/" + USERNAME + "/" + "salidaAnalogica"; 
  salidaAnalogica.toCharArray(SALIDAANALOGICA, 50);
  
}

//--------------------------LOOP--------------------------------
void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  unsigned long currentMillis = millis();
    
  if (currentMillis - previousMillis >= 10000) { //envia la temperatura cada 10 segundos
    previousMillis = currentMillis;
    int analog = analogRead(17);
    float temp = analog*0.322265625;
    strtemp = String(temp, 1); //1 decimal
    strtemp.toCharArray(valueStr, 15);
    Serial.println("Enviando: [" +  String(TEMPERATURA) + "] " + strtemp);
    client.publish(TEMPERATURA, valueStr);
  }
  
  if (digitalRead(14) == 0) {
    strPulsador = "presionado";
  } else {
    strPulsador = "NO presionado";
  }

  if (strPulsador != strPulsadorUltimo) { //envia el estado del pulsador solamente cuando cambia.
    strPulsadorUltimo = strPulsador;
    strPulsador.toCharArray(valueStr, 15);
    Serial.println("Enviando: [" +  String(PULSADOR) + "] " + strPulsador);
    client.publish(PULSADOR, valueStr);
  }
}