sábado, 19 de agosto de 2017

Tutorial #16 ESP8266 (Parte6) – Gráficos en tu Dashboard MQTT usando Highcharts

En este nuevo tutorial sobre IOT (internet de las cosas) usando ESP8266, voy a explica como agregarle un gráfico al dashboard MQTT que vimos en el tutorial anterior. Para eso vamos a usar JavaScript y dos librerías de Highcharts.


tutorial16.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Tutorial 16</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>
    <script src="https://code.highcharts.com/stock/highstock.js"></script>
    <script src="https://code.highcharts.com/stock/modules/exporting.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;
    }

    #container {
      width: 600px;
      height: 300px;
    }
  </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>
      <div id="container"></div>
    <script>      
      usuario = 'placa2';
      contrasena = '12345678';

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

      estadoDigital = "OFF";
      temperaturas = -1;

      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);
            temperaturas = parseFloat(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
        });

        Highcharts.setOptions({
            global: {
                useUTC: false
            }
        });

        // Create the chart
        Highcharts.stockChart('container', {
            chart: {
                events: {
                    load: function () {

                        // set up the updating of the chart each second
                        var series = this.series[0];
                        setInterval(function () {
                            var x = (new Date()).getTime(), // current time
                                y =temperaturas;
                            series.addPoint([x, y]);
                        }, 1000);
                    }
                }
            },

            rangeSelector: {
                buttons: [{
                    count: 1,
                    type: 'minute',
                    text: '1M'
                }, {
                    count: 5,
                    type: 'minute',
                    text: '5M'
                }, {
                    type: 'all',
                    text: 'All'
                }],
                inputEnabled: false,
                selected: 0
            },

            title: {
                text: 'Temperatura ºC'
            },

            exporting: {
                enabled: false
            },

            series: [{
                name: 'ºC',
                data: (function () {
                    // generate an array of random data
                    var data = [],
                        time = (new Date()).getTime(),
                        i;

                    for (i = -300; i <= 0; i += 1) {
                        data.push([
                            time + i * 1000,
                            -1
                        ]);
                    }
                    return data;
                }())
            }]
        });

          
        
    </script>
  </body>
</html>

1 comentario:

  1. PUSE LAS LIBRERIAS Y AUN ASI NO PUEDO VISUALIZAR LOS GRAFICOS, USO ATON COMO EDITOR.
    Y XAMPP COMO SERVIDOR LOCAL.

    ResponderEliminar