CÓDIGO DEL PROYECTO LETRERO

EL CÓDIGO ESTÁ FORMADO POR 9 ARCHIVOS.

ARCHIVO 1: PROYECTO_LETRERO_FPB_16_17_MARZO. ino

Source file
     1 /************************************************************************
     2  * PROYECTO LETRERO FPB CURSO 2016-2017
     3  * FICHERO PRINCIPAL: PROYECTO_LETRERO_FPB_16_17.INO
     4  * Francisco J. Jiménez 
     5  * fpbásicalectricidad.blogspot.com
     6  * noviembre 2016 - marzo 2017
     7  * *********************************************************************/
     8 
     9 #include "CLAVES_CUENTAS.H"
    10 #include "VARIABLES_GLOBALES.H"
    11 #include <ESP8266WiFi.h>
    12 #include "declaracion_funciones.h"
    13 #include <TimeLib.h>
    14 
    15 #define HORA           1
    16 #define FECHA_CORTA    2
    17 #define TEMPERATURA    3
    18 #define TELEGRAM       4
    19 
    20 #define TIEMPO         5
    21 #define PREVISION_1    6
    22 #define PREVISION_2    7
    23 #define ASTRONOMIA     8
    24 #define FECHA_LARGA    9
    25 #define ALBAYTAR      10
    26 #define BUENOS_D      11
    27 #define OTROS_TEXTOS  12
    28 #define TEXTOS_CLASES  14
    29 
    30 
    31 ///////////////////////////////////////////////////////////////////////////////
    32 // SETUP
    33 ///////////////////////////////////////////////////////////////////////////////
    34 void setup() {
    35   bool f = false;
    36   inicializar_registros();
    37   delay (2000);
    38     Serial.begin(115200);
    39     //ESP.wdtDisable();
    40     //Serial.println ("reset");
    41     ESP.wdtEnable(30000);                 //  Ajusta el Temporizador de RESET (Watchdog.enable) a 30 segundos
    42     
    43     do{
    44       int cuenta = 0;
    45       f = conectar_wifi();
    46       //Serial.println (f);
    47       if((++cuenta) % 3){
    48         limpiar_panel();
    49           unsigned long milisegundos = millis();
    50           do{    
    51             escribir_texto_fijo(1, (F("AlBaytar")));                    //-------------> 
    52             Refrescar_Display();
    53           } while ((millis()-milisegundos)< 1000);
    54         
    55         limpiar_panel();
    56       }
    57     }while (f == false);
    58   if (f){                                           
    59     //Serial.println ("CONECTADO");
    60     //escribe_mensaje_LED("FP BASICA ELECTRICIDAD IES AL-BAYTAR. fpbasicaelectricidad.blogspot.com        ");
    61     //delay (500);
    62     while (actualizar_datos_tiempo_actual() != true){
    63       escribe_mensaje_LED("ERROR DE COMUNICACION CON EL SERVIDOR WONDERGROUND");
    64     };
    65     actualizar_datos_astronomia();
    66     actualizar_datos_prevision(); 
    67     //inicializa_telegram(BOTtoken_MIO, BOTname_MIO, BOTusername_MIO); 
    68    
    69   }
    70 }
    71 ///////////////////////////////////////////////////////////////////////////////
    72 // LOOP
    73 ///////////////////////////////////////////////////////////////////////////////
    74 void loop(){
    75   // VARIABLES PARA GESTIONAR LA ACTUALIZACIÓN DE LOS DATOS DEL TIEMPO CADA 30 MINUTOS
    76   const unsigned long intervalo_actualizacion=1800000; // (cada 30 minutos) 1000 * 60 * 30 = 1800000
    77   unsigned long anterior_millis=0; // millis() returns an unsigned long.
    78   bool f_wifi=false;
    79   int para_act_prevision=0;
    80   unsigned long actual_millis= millis();
    81   int estado_wifi= WiFi.status();
    82 
    83   do{
    84     for( int f=5 ; f<=OTROS_TEXTOS; f++){
    85     //   ESP.wdtFeed();   Watchdog.reset(); // Si esta función no se llama en menos de "Watchdog.enable(30000) de setup" 30 segundos la tarjeta de resetea.
    86                                             // sirve para que no se quede en bucle indefinido ante un fallo de algún servidor o de la tarjeta
    87                                             // Se ha puesto en la función presentar_en DISPLAY();
    88       presentar_en_DISPLAY (HORA); 
    89       presentar_en_DISPLAY (FECHA_CORTA);
    90       presentar_en_DISPLAY (TEMPERATURA);
    91       //presentar_en_DISPLAY (TELEGRAM);                  // LEE LOS DATOS DE TELEGRAM Y ACTUALIZA EL DISPLAY
    92       presentar_en_DISPLAY (HORA);
    93       presentar_en_DISPLAY (TEXTOS_CLASES);
    94       presentar_en_DISPLAY (HORA);
    95       presentar_en_DISPLAY (FECHA_CORTA);
    96       presentar_en_DISPLAY (TEMPERATURA);    
    97       presentar_en_DISPLAY (f);                         // DE FORMA ROTATIVA PRESENTA LOS DATOS DE TIEMPO ACTIAL, PREVISIÓN, ASTRONOMÍA, FECHA LARGA...
    98   
    99       // 1º Actualización de los datos del tiempo cada 30 minutos
   100       actual_millis = millis(); 
   101       if( anterior_millis > actual_millis) anterior_millis = actual_millis;           // Cuando hay desbordamiento cada 50 días
   102       
   103       // VERIFICAR EL INTERVALO PARA ACTUALIZAR EL TIEMPO
   104       if ((actual_millis - anterior_millis) >= intervalo_actualizacion) {             // Se actualiza cada 30 minutos
   105         limpiar_panel();
   106         ESP.wdtFeed();                  // CADA VEZ QUE SE PRESENTA UN DATO NUEVO EN EL DISPLAY SE RESETEA EL Watchdog
   107         estado_wifi= WiFi.status();            // Verificar conexión
   108         if(estado_wifi != WL_CONNECTED){       // Conectar si no está conectado
   109           f_wifi = conectar_wifi();
   110                 limpiar_panel();
   111                 unsigned long milisegundos = millis();
   112                 do{    
   113                   escribir_texto_fijo(0, (F("Al-Baytar")));                    //
   114                   Refrescar_Display();
   115                 } while ((millis()-milisegundos)< 1000);
   116                 limpiar_panel();
   117         }
   118         if ((estado_wifi == WL_CONNECTED) || (f_wifi == true)){
   119           if (actualizar_datos_tiempo_actual()){    // Si se actualizan los datos del tiempo actual correctamente 
   120             f_wifi == false; 
   121             anterior_millis = actual_millis;       // Guardar el Millis actual  ---> para evitar nuevas llamadas a la función
   122             //Serial.print ("ACTUALIZADOS LOS DATOS DE TIEMPO ACTUAL");
   123             ESP.wdtFeed();                  // CADA VEZ QUE SE PRESENTA UN DATO NUEVO EN EL DISPLAY SE RESETEA EL Watchdog
   124             para_act_prevision++;
   125           }
   126           else{
   127             escribe_mensaje_LED("Error de conexión con WonderGround.      ");
   128           }
   129           if((para_act_prevision>=3) || (datos_de_prevision_1 == " ")){       // se actualiza cada hora y media o si hubo fallos en la recogida de datos anteriormente
   130             actualizar_datos_astronomia();
   131             actualizar_datos_prevision();
   132             para_act_prevision=0;
   133             ESP.wdtFeed();                  // CADA VEZ QUE SE PRESENTA UN DATO NUEVO EN EL DISPLAY SE RESETEA EL Watchdog
   134           }
   135 
   136         }
   137       }
   138     }
   139   }while(1);      // Bucle infinito
   140 }
   141 
   142 ////////////////////////////////////////////////////////////////////////////////////////
   143 void presentar_en_DISPLAY (int dato){
   144   unsigned long milisegundos = millis();
   145   String espacios= ("         ");
   146   //Serial.print("presentar en display: ");Serial.println(dato);
   147   ESP.wdtFeed();                  // CADA VEZ QUE SE PRESENTA UN DATO NUEVO EN EL DISPLAY SE RESETEA EL Watchdog
   148   switch (dato){
   149     case TIEMPO:{
   150       limpiar_panel();
   151       escribe_mensaje_LED(ascii_panel_LED(datos_del_tiempo_actual));
   152       escribe_mensaje_LED(espacios);  //escribe_mensaje_LED("         ");
   153       break;
   154     }
   155     case ASTRONOMIA:{
   156       limpiar_panel();
   157       escribe_mensaje_LED(ascii_panel_LED(datos_de_astronomia));
   158       escribe_mensaje_LED(espacios);  //escribe_mensaje_LED("         ");
   159       break;
   160     }
   161     case PREVISION_1:{
   162       limpiar_panel();
   163       escribe_mensaje_LED(ascii_panel_LED(datos_de_prevision_1));
   164       escribe_mensaje_LED(espacios);  //escribe_mensaje_LED("         ");
   165       break;
   166     }
   167     case PREVISION_2:{
   168       limpiar_panel();
   169       escribe_mensaje_LED(ascii_panel_LED(datos_de_prevision_2));
   170       escribe_mensaje_LED(espacios);  //escribe_mensaje_LED("         ");
   171       break;
   172     }
   173     case TELEGRAM:{
   174       limpiar_panel();
   175       gestionar_mensajes_Telegram ();
   176       if( mensaje_telegram_a_panel == true){
   177         limpiar_panel();
   178         escribe_mensaje_LED(mensaje_telegram_panel);
   179         escribe_mensaje_LED("         ");
   180       }
   181       break;
   182     }
   183     case HORA:{
   184       limpiar_panel();
   185       do{    
   186         actualizar_texto_hora();
   187         escribir_texto_fijo(1, hora_actual);
   188         Refrescar_Display();
   189       } while ((millis()-milisegundos)< 10000);
   190       break;
   191     }
   192 
   193     case TEMPERATURA:{
   194       limpiar_panel();
   195       do{    
   196         escribir_texto_fijo(1, temperatura_actual);
   197         Refrescar_Display();
   198       } while ((millis()-milisegundos)< 3000);
   199       break;
   200     }
   201     
   202     case FECHA_LARGA:{
   203       limpiar_panel();
   204       actualizar_texto_hora();
   205       escribe_mensaje_LED(fecha_actual);
   206       escribe_mensaje_LED(espacios);  //escribe_mensaje_LED("         ");
   207       break;
   208     }
   209     case FECHA_CORTA:{
   210       limpiar_panel();
   211       actualizar_texto_hora();
   212       do{    
   213         escribir_texto_fijo(1, fecha_actual_corta);
   214         Refrescar_Display();
   215       } while ((millis()-milisegundos)< 3000);
   216       break;
   217     } 
   218     case ALBAYTAR:{
   219       limpiar_panel();
   220       escribe_mensaje_LED("IES AL-BAYTAR. Arroyo de la Miel. www.albaytar.es.    Centro TIC");
   221       escribe_mensaje_LED(espacios);  //escribe_mensaje_LED("         ");
   222       break;
   223     }
   224     case BUENOS_D:{
   225       limpiar_panel();
   226       if ((hour() >= 6) && (hour() <= 14))escribe_mensaje_LED(ascii_panel_LED("BUENOS DIAS"));
   227       else if ((hour() >= 15) && (hour() <= 20))escribe_mensaje_LED("Buenas tardes");
   228       else if ((hour() >= 21) || (hour() <= 5))escribe_mensaje_LED("Buenas noches");
   229       escribe_mensaje_LED(espacios);  //escribe_mensaje_LED("         ");
   230       break;
   231     }
   232     // SIGUE LA FUNCIÓN
   233       ////////////////////////////////////////////////////////////
   234       // 2º PRESENTAR TEXTOS ESPECIALES. DEPENDIENDO DE LA FECHA
   235       // BUENOS DÍAS, BUEN FIN DE SEMANA, HOY COMIENZA EL INVIERNO, HOY COMIENZA EL VERANO, HOY COMIENZA EL OTOÑO, HOY COMIENZA LA PRIMAVERA, FELIZ (DIA DE LA SEMANA), 
   236       // FELIZ NAVIDAD, RECREO, SALIDA, FP BÁSICA ELECTRICIDAD, IES AL-BAYTAR, 
   237       //    String BUEN_FINDE = "BUEN FIN DE SEMANA. Disfruta de tu tiempo y haz cosas interesantes.      ";
   238       //    String BUEN_DIA = "BUENOS DIAS. ";
   239       //    String SALUDO_BUENOS_DIAS = "Recuerda que estás en un Centro Educativo. Nuestro objetivo es enseñarte, tu objetivo es aprender. Disfruta con tu aprendizaje.      ";
   240       //    String RECREO = "   RECREO   ";
   241       //    String FELIZ_AGNO_NUEVO = "*****   FELIZ AÑO NUEVO   *****";
   242       //    String FELIZ_NAVIDAD = "*****   FELIZ NAVIDAD   *****";
   243       //    String INI_VERANO = "   INICIO DEL VERANO   ";
   244       //    String INICIO_INVIERNO = "   INICIO DEL INVIERNO   ";
   245       ///////////////////////////////////////////////////////////
   246       
   247     case TEXTOS_CLASES:{
   248       limpiar_panel();
   249       if ((weekday() > 1) && (weekday() < 7)){        // DE LUNES A VIERNES   1 - 7
   250         if ((hour() == 8)){                           // MENSAJES DE 8 A 9 DE LA MAÑANA 
   251           escribe_mensaje_LED(F("BUENOS DIAS. Disfruta de tu aprendizaje.")); escribe_mensaje_LED(espacios);
   252           if ((minute()>= 24) && (minute()<= 27)){    
   253             escribe_mensaje_LED(F("PRIMER TIMBRE. Entrada a las aulas.")); escribe_mensaje_LED(espacios);  
   254           }
   255           if ((minute()>= 28) && (minute()<= 31)){  
   256             escribe_mensaje_LED(F("SEGUNDO TIMBRE. Comienzo de las clases.")); escribe_mensaje_LED(espacios);  
   257           }
   258         }
   259         if ((hour() == 11) && (minute()>= 30) && (minute()<= 59)){     // EN EL RECREO
   260           limpiar_panel();
   261           milisegundos = millis();
   262           do{    
   263             escribir_texto_fijo(2, (F("RECREO")));                    //-------------> MENSAJE RECREO
   264             Refrescar_Display();
   265           } while ((millis()-milisegundos)< 4000);
   266         }
   267         if (weekday() == 6){ 
   268           if (((hour() == 14) && (minute()>= 45)) || ((hour() == 15) && (minute()<= 15))){   // BUEN FIN DE SEMANA 
   269             escribe_mensaje_LED(F("BUEN FIN DE SEMANA. Disfruta de tu tiempo y haz cosas interesantes."));   
   270             escribe_mensaje_LED(espacios);
   271           }
   272         }
   273       }
   274       break;
   275     }
   276 
   277     case OTROS_TEXTOS:{
   278       limpiar_panel();    
   279       if ((month()==12) && (day()==25)) escribe_mensaje_LED(F("*****   FELIZ NAVIDAD   ***** "));
   280       if ((month()==3) && (day()==12)) escribe_mensaje_LED("*****   FELIZ " + String (year()) + "   ***** ");
   281       if ((month()==1) && (day()==1)) escribe_mensaje_LED(F("INICIO DEL VERANO. "));
   282       if ((month()==12) && (day()==21)) escribe_mensaje_LED(F("INICIO DEL INVIERNO. "));
   283       escribe_mensaje_LED(espacios);
   284       escribe_mensaje_LED(F("IES AL-BAYTAR. www.albaytar.es. "));
   285       escribe_mensaje_LED(espacios);
   286       if (((minute()>= 10) && (minute()<= 20)) || ((minute()>= 40) && (minute()<= 50))) escribe_mensaje_LED(F("FP BASICA ELECTRICIDAD. fpbasicaelectricidad.blogspot.com "));
   287       escribe_mensaje_LED(espacios);
   288       break;
   289     }
   290     /////////           
   291   }
   292 }
   293 /////////////////////////////////////////////////////////////////////////////////////////
   294 ////////////////////////////////////////////////////////////////////////////////////////

ARCHIVO 2. CLAVES_CUENTAS.h

Source file
     1 /************************************************************************
     2  * PROYECTO LETRERO FPB CURSO 2016-2017
     3  * FICHERO: claves_cuentas.h
     4  * Francisco J. Jiménez 
     5  * fpbásicalectricidad.blogspot.com
     6  * noviembre 2016 - marzo 2017
     7  * *********************************************************************/
     8 
     9 
    10 //DATOS DE LA CONEXIÓN WIFI
    11 
    12 const char SSID_[]     = "Andared";                                             // SSID ANDARED
    13 const char PASSWORD[] = "llevalatararaunvestidoblancollenodecascabeles";       // CLAVE ANDARED
    14 // LA MAC ES: 5C:CF:7F:83:6C:00   //---> Necesario para darle acceso al router si tienes bloqueo de MAC
    15 
    16 //API KEY DE WUNDERGROUND
    17 #define WUNDERGROUND "api.wunderground.com"
    18 #define WU_API_KEY "xxxxxxxxxxxxxxxx"      // ESCRIBIR AQUÍ LA CLAVE DE WUNDERGROOUND    // CLAVE DE http://www.wunderground.com/weather/api/
    19 #define WU_LOCATION "Benalmadena_Costa"
    20 
    21 //CLAVES DEL BOT DE TELEGRAM
    22 #define BOTtoken_MIO "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"        //MI BOT TELEGRAM ___
    23 #define BOTname_MIO "nombredelbot"                                         // EL NOMBRE DE MI BOT
    24 #define BOTusername_MIO "nombredelbot_bot"   
    25 
    26 #define USUARIO_ACREDITADO_TELEGRAM "xxxxxxxxx" 

ARCHIVO 3. CONVERSIÓN_ASCII_UTF8.ino

Source file
     1 /************************************************************************
     2  * CONVERSIÓNES DE DATOS A ASCII PARA PANEL LED Y A UTF-8 PARA TELEGRAM
     3  * Francisco J. Jiménez 
     4  * fpbásicalectricidad.blogspot.com
     5  * noviembre 2016
     6  * *********************************************************************/
     7 // FUNCIÓN: String ascii_panel_LED(String s)
     8 // hace un filtro de los caracteres a imprimir en el panel incluidas vocales acentuadas y Ñ ñ
     9 // La entrada es una cadena UTF-8 y la salida son solo los caracteres imprimibles
    10 // Si un caracter no es imprimible se sustituye por el símbolo ?
    11 String ascii_panel_LED(String s){          
    12    String r="";
    13    char c;
    14         //Serial.println(s); Serial.println(s.length());
    15         if (s.length()>1000) return "";
    16         for (int i=0; i<s.length(); i++){
    17           c = utf8ascii(s.charAt(i));
    18           if (c!=0) r+=c;
    19         }
    20         
    21         return r;                                        
    22 }
    23 
    24 /////////////////////////////////////////////////////////////
    25 // CONVERSIONES DE CARACTERES ASCII UTF8
    26 // CÓDIGO DE: http://playground.arduino.cc/Main/Utf8ascii
    27 ////////////////////////////////////////////////////////////
    28 static byte c1;  // Last character buffer
    29 
    30 // Convert a single Character from UTF8 to Extended ASCII
    31 // Return "0" if a byte has to be ignored
    32 byte utf8ascii(byte ascii) {
    33  
    34     if ( ascii<128 )   // Standard ASCII-set 0..0x7F handling  
    35     {   c1=0; 
    36         return( ascii ); 
    37     }
    38   
    39     // get previous input
    40     byte last = c1;   // get last char
    41     c1=ascii;         // remember actual character
    42 
    43     switch (last)     // conversion depending on first UTF8-character
    44     {   case 0xC2: return  (ascii);  break;
    45         case 0xC3: return  (ascii | 0xC0);  break;
    46         case 0x82: if(ascii==0xAC) return(0x80);       // special case Euro-symbol
    47     }
    48 
    49     return  (0);                                     // otherwise: return zero, if character has to be ignored
    50 }
    51 
    52 
    53 /*******************************************************************************/
    54 // FUNCIÓN: String panel_LED_a_UTF8(String s)
    55 // Transforma los caracteres del display led en caracteres UTF-8 para telegram
    56 // Si un caracter no es imprimible se sustituye por el símbolo ?
    57 /****************************************************************************/
    58 String panel_LED_a_UTF8(String s){          
    59    String r="";
    60         char c;
    61         if (s.length()>1000) return "";
    62         for (int i=0; i<s.length(); i++){   
    63           c = (s.charAt(i));
    64           
    65             if (c!=0){
    66                if (c < 128) r += String (c);                                   // 127 primeros caracteres ASCII 
    67                else {
    68                  switch (c){
    69                   case 'á':
    70                     r += "á";
    71                      r+= "A";
    72                     break;
    73                   
    74                   case 'é':
    75                     //r+= String ("\/u00e9");
    76                     r+= "E";
    77                     break;
    78   
    79                   case 'í':
    80                     //r+= String ('\/u00ed');
    81                     r+= "I";
    82                     break;                
    83                     
    84                   case 'ó':
    85                     //r+= String ("00f3");
    86                     r+= "O";
    87                     break;
    88                   
    89                   case 'ú':
    90                     //r+= String ("00fa");
    91                     r+= "U";
    92 
    93                     break;
    94                   
    95                   case 'ñ':
    96                     //r+= "\\u00f1";
    97                     r +=String ("(n)");
    98                     break;
    99   
   100                   case 'Ñ':
   101                     //r+= "\\u00d1";
   102                     //r += String ('Ñ');
   103                     r+= "(N)";
   104                     break;
   105   
   106                   case 'Á':
   107                     r+= "A";
   108                     break;
   109   
   110                   case 'É':
   111                     r+= "E";
   112                     break;
   113                     
   114                   case 'Í':
   115                     r+= "I";
   116                     break;
   117                     
   118                   case 'Ó':
   119                     r+= "O";
   120                     break;
   121                     
   122                   case 'Ú':
   123                     r+= "U";
   124                     break;
   125   
   126                   default:
   127                     r+= "?";
   128                     break;
   129                  }
   130                }
   131       
   132             }
   133         }
   134    return r;
   135 }
   136 ////////////////////////////////////////////////////////////////////////////////
   137 
   138 /////////////////////////////////////////////////////////////////////////////////////
   139 
   140 String convertUnicode(String unicodeStr){
   141   String out = "";
   142   int len = unicodeStr.length();
   143   char iChar;
   144   char* error;
   145   for (int i = 0; i < len; i++){
   146      iChar = unicodeStr[i];
   147      if(iChar == '\\'){ // got escape char
   148        iChar = unicodeStr[++i];
   149        if(iChar == 'u'){ // got unicode hex
   150          char unicode[6];
   151          unicode[0] = '0';
   152          unicode[1] = 'x';
   153          for (int j = 0; j < 4; j++){
   154            iChar = unicodeStr[++i];
   155            unicode[j + 2] = iChar;
   156          }
   157          long unicodeVal = strtol(unicode, &error, 16); //convert the string
   158          out += (char)unicodeVal;
   159          Serial.print ("Conversión : ");
   160          Serial.println ( (char)unicodeVal);
   161        } else if(iChar == '/'){
   162          out += iChar;
   163        } else if(iChar == 'n'){
   164          out += '\n';
   165        }
   166      } else {
   167        out += iChar;
   168      }
   169   }
   170   return out;
   171 }

ARCHIVO 4. HORA_FECHA.ino

Source file
     1 /************************************************************************
     2  * PROYECTO LETRERO FPB CURSO 2016-2017
     3  * FICHERO: hora_fecha.ino
     4  * Francisco J. Jiménez 
     5  * fpbásicalectricidad.blogspot.com
     6  * noviembre 2016 - marzo 2017
     7  * *********************************************************************/
     8 // SE TUVO QUE DESESTIMAR POR INCOMPATIBILIDAD DEL PROTOCOLO NTP CON EL SERVIDOR DE ANDARED (BLOQUEO DE PUERTOS)
     9 
    10 /*
    11  * BASADO EN:
    12  * TimeNTP_ESP8266WiFi.ino
    13  * Example showing time sync to NTP time source
    14  *
    15  * This sketch uses the ESP8266WiFi library
    16  */
    17 
    18 #include <TimeLib.h>
    19 //#include <WiFiUdp.h>
    20 
    21 
    22 
    23 // NTP Servers:
    24 static const char ntpServerName[] = "us.pool.ntp.org";
    25 //static const char ntpServerName[] = "time.nist.gov";
    26 //static const char ntpServerName[] = "time-a.timefreq.bldrdoc.gov";
    27 //static const char ntpServerName[] = "time-b.timefreq.bldrdoc.gov";
    28 //static const char ntpServerName[] = "1.pool.ntp.org";               // SERVIDOR ESPAÑOL
    29 
    30 const int timeZone = 1;     // Central European Time
    31 //const int timeZone = -5;  // Eastern Standard Time (USA)
    32 //const int timeZone = -4;  // Eastern Daylight Time (USA)
    33 //const int timeZone = -8;  // Pacific Standard Time (USA)
    34 //const int timeZone = -7;  // Pacific Daylight Time (USA)
    35 
    36 static const char *dias_semana[]={"DOMINGO","LUNES","MARTES","MIERCOLES","JUEVES","VIERNES","SABADO"};
    37 static const char *meses_agno[]={"Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"};
    38 
    39 
    40 //WiFiUDP Udp;
    41 //unsigned int localPort = 123;                                       // local port to listen for UDP packets
    42 
    43 // DECLARACIÓN DE FUNCIONES
    44 //time_t getNtpTime();
    45 time_t actualizar_hora_tiempo();
    46 
    47 void digitalClockDisplay();
    48 void printDigits(int digits);
    49 
    50 time_t prevDisplay = 0;               // Para comprobar que no ha cambiado la hora
    51 int dia_hoy=8;
    52 
    53 void actualizar_texto_hora(){
    54   if (timeStatus() != timeNotSet) {
    55     if (now() != prevDisplay) {       //Ha cambiado la hora (aunque sea en un segundo)
    56       prevDisplay = now();
    57         hora_actual = "";                             // Se cambia la hora
    58         if(hour()<10) hora_actual = "0";
    59         hora_actual += String (hour()) + ":";
    60         if(minute()<10) hora_actual += "0";
    61         hora_actual += String (minute()) + ":";
    62         if(second()<10) hora_actual += "0";
    63         hora_actual += String (second());
    64 
    65         if (dia_hoy != day()){            // Debe cambiar la fecha
    66           fecha_actual = String (dias_semana [ weekday() - 1]) + ", " + String (day()) + " de " + String ( meses_agno [ month() - 1]) + " de " + String (year());
    67           dia_hoy = day();
    68           // FECHA ACTUAL CORTA EN FORMATO DD/MM/AA //
    69           fecha_actual_corta = "";
    70           if (day()<9) fecha_actual_corta += "0";
    71           fecha_actual_corta += String (day()) + "\/";
    72           if (month()<10) fecha_actual_corta += "0";
    73           fecha_actual_corta += String (month()) + "\/" + String (year()-2000);
    74         }
    75     }
    76   }
    77   
    78 }
    79 

ARCHIVO 5. TELEGRAM_BOT.ino (NO SE ESTÁ UTILIZANDO, POR EL MOMENTO. HAY QUE DEPURARLO)

Source file
     1 /*******************************************************************
     2  *  BOT_TELEGRAM                                                   *
     3  *  PROYECTO: PROYECTO_LETRERO_LED_FPB                             *
     4  *  Francisco J. Jiménez                                           *
     5  *  Benalmádena, enero de 2017                                     *
     6  *  fpbasicaelectricidad.blogspot.com                              *
     7  *                                                                 *
     8  *                                                                 *
     9  *                                                                 *
    10  *******************************************************************/
    11 
    12 #include <WiFiClientSecure.h>
    13 // VARIABLES GLOBALES
    14 // DE IDENTIFICACIÓN DEL USUARIO Y BOT
    15 String Telegram_BOTtoken;
    16 String Telegram_BOTname;
    17 String Telegram_username;
    18 WiFiClientSecure client;
    19 
    20 // DATOS DEL ÚLTIMO MENSAJE RECIBIDO
    21 // String cadena_texto_telegram;
    22 int longitud_maxima_cadena = 450;
    23 char cadena_texto_telegram[460];
    24 
    25 // Una vez analizadda (Parse) la cadena
    26 String update_id ="";
    27 String message_id ="";
    28 String from_id;
    29 String first_name;
    30 String user_name;
    31 String chat_id;
    32 String text;
    33 bool comando_bot = false;
    34 //
    35 // COLA DE DATOS POR ANALIZAR
    36 char *puntero_parse_telegram;
    37 bool mensajes_Telegram_en_cola=false;
    38 
    39 
    40 /////////////////////////////////////////////////////////////////////////////
    41 // devuelve true si hay mensajes nuevos y false si no hay mensajes nuevos
    42 // Los devuelve en las variables globales correspondientes
    43 ////////////////////////////////////////////////////////////////////////////
    44 bool leer_mensajes_Telegram (){
    45   String texto_entrada = "";
    46   String cadena_num_mensaje="";
    47   String numero_mensaje_id="0";
    48   char caracter_entrada= '?';
    49   int contador_caracteres=0;
    50   unsigned long tiempo = millis();
    51   //////////////////////////////////////////////////////////////////////////////////////////////////////////
    52   if(mensajes_Telegram_en_cola==false){
    53     Serial.println ("LEYENDO TELEGRAM");
    54     if (update_id != ""){
    55       numero_mensaje_id = String (update_id.toInt()+1);
    56     }
    57     IPAddress server(149,154,167,198);
    58     if (client.connect(server, 443)) {
    59       String comando = "GET /bot" + Telegram_BOTtoken + "/getUpdates?offset=" + numero_mensaje_id + "/limits=1";
    60       Serial.println(comando);
    61       client.println(comando);
    62       while (!client.available()){
    63         if ((millis()- tiempo) > 2000) return (false);       // Espera a que esté disponible como máximo 2 segundos  
    64       }
    65         
    66       while (client.available() && ((millis()- tiempo) < 2000)){      // como mucho la transmisión debe ser en menos de 2 segundos
    67 
    68             caracter_entrada = (byte) client.read();
    69             if ((contador_caracteres < (longitud_maxima_cadena - 10))) texto_entrada += (char) caracter_entrada;
    70             
    71             contador_caracteres++; 
    72         /*
    73         if (contador_caracteres >= (longitud_maxima_cadena - 2)) break;   
    74         Serial.println(tiempo); Serial.println(contador_caracteres);
    75         */    
    76       }
    77     }
    78     if (texto_entrada != "") texto_entrada.toCharArray(cadena_texto_telegram, contador_caracteres + 1);
    79     else strcpy (cadena_texto_telegram, "");
    80     //strncpy (cadena_texto_telegram, texto_entrada, contador_caracteres);
    81     Serial.println (cadena_texto_telegram);
    82     Serial.println (texto_entrada);
    83     puntero_parse_telegram = cadena_texto_telegram;                       // Se actualiza el puntero con la direcciónd e la cadena de texto telegram
    84   }
    85   //////////////////////////////////////////////////////////////////////////////////////////////////////////
    86 
    87   if (strncmp (cadena_texto_telegram,"{\"ok\":true,\"result\":[]",22) == 0) return false;                 // No hay mensajes
    88   if (strncmp (cadena_texto_telegram,"{\"ok\":true,\"result\":[{\"update_id\":", 34) !=0) return false;         // El dato recibido no se corresponde con la cadena de Telegram
    89 
    90   bool retorno= analiza_mensajes_telegram (puntero_parse_telegram);
    91 
    92   return retorno;
    93 }
    94 /////////////////////////////////////////////////////////////////////////
    95 /*************************************************************************
    96  * 
    97  ************************************************************************/
    98 bool analiza_mensajes_telegram(char *json){
    99   //Serial.print("analiza mensajes");
   100   puntero_parse_telegram = json;
   101 
   102   bool es_bot_command = false;
   103 
   104   update_id = buscar_dato_json (puntero_parse_telegram, "\"update_id\":", ",");               // ES NECESARIO PONERLO AQUÍ DELANTE DEL IF 
   105 
   106   if (buscar_dato_json (puntero_parse_telegram, "\"text\":\"","\"}}") == ""){                // La cadena no está completa hasta el texto
   107     puntero_parse_telegram =json;
   108     if ((text = buscar_dato_json (puntero_parse_telegram, "\"text\":\"" ,"\",\"enti")) != ""){
   109       puntero_parse_telegram =json;
   110      
   111       es_bot_command = true;
   112     }
   113     else return false;     // Y tampoco es un un BOT COMANDO "type":"bot_command" ENTONCES RETURN;
   114   }
   115  
   116   comando_bot = es_bot_command;                                         // Se actualiza la variable global comando_bot
   117   puntero_parse_telegram =json;                                                               // Una vez comprobado se vuelve a inicializar para Analizar el fichero JSon de Telegram
   118   update_id = buscar_dato_json (puntero_parse_telegram, "\"update_id\":", ",");
   119   message_id = buscar_dato_json (puntero_parse_telegram, "\"message_id\":", ",");
   120   from_id = buscar_dato_json (puntero_parse_telegram, "\"from\":{\"id\":",",");
   121   first_name = buscar_dato_json (puntero_parse_telegram, "\"first_name\":\"", "\",");
   122   user_name = buscar_dato_json (puntero_parse_telegram, "\"username\":\"", "\"}");
   123   chat_id = buscar_dato_json (puntero_parse_telegram, "\"chat\":{\"id\":", ",");
   124                                                                                 // TEXTO 2 POSIBILIDADES: ES UN TEXTO O ES UN BOT_COMMAND
   125   if ( es_bot_command == false) text = buscar_dato_json (puntero_parse_telegram, "\"text\":\"","\"}}");
   126   else text = buscar_dato_json (puntero_parse_telegram, "\"text\":\"","\",\"enti");
   127   return true;
   128 }
   129 
   130 ///////////////////////////////////////////////////////////
   131 String buscar_dato_json (char *puntero_json, char texto_dato[], char caracter_final[]){
   132   char *p_ini= puntero_json;         
   133   char *p_fin= p_ini;
   134   int lon_cad=0, lon_texto_dato=0;
   135   char datos[460]="\0";
   136   while (texto_dato[lon_texto_dato++] != '\0'); // Calcula la longitud del texto de datos
   137   if (lon_texto_dato > 1) lon_texto_dato--;     // Se resta 1 que es el caracter fin de cadena \0
   138   
   139   p_ini=strstr (p_ini, texto_dato) + lon_texto_dato ;
   140   if (p_ini == NULL) return "";                 // No se ha encontrado la cadena buscada
   141   
   142   p_fin=p_ini;
   143   //p_fin=strstr (p_fin, "\",");
   144   p_fin=strstr (p_fin, caracter_final);
   145   if (p_fin == NULL){         // No se ha encontrado la cadena buscada
   146     if (strncmp (texto_dato,"\"text\":\"",7) == 0){           // Si la longitud del texto es muy grande y por tanto está trumcado, entonces
   147       datos[0] = '\0';                                // Se recibe como texto vacío
   148       puntero_parse_telegram = p_fin;
   149       //NO   update_id = String (update_id.toInt()+1);               // Se suma 1 al update_id para dar como inválido ese dato.
   150       
   151         message_id = "";                                      // Y todos los demás se reinicializan
   152         from_id = "";               // ESTO ES NECESARIO PARA QUE NO HAGA OVERFLOW LA MEMORIA O NO SE QUEDE EN UNA CADENA LARGA EN BUCLE SIN FIN
   153         first_name = "";
   154         user_name = "";
   155         chat_id = "";
   156         text = "";
   157       return String (datos);                                  // y se termina la conversión
   158     }  
   159   }
   160   
   161   if( (lon_cad = p_fin - p_ini) >=longitud_maxima_cadena) lon_cad = longitud_maxima_cadena; // Se trunca el texto a 500 caracteres
   162   strncpy (datos, p_ini, lon_cad);
   163   datos[++lon_cad] = '\0';
   164   puntero_parse_telegram = p_fin;
   165   return String (datos);
   166 }
   167 
   168 //////////////////////////////////////////////////////////////////////////
   169 boolean escribir_mensajes_Telegram (String texto_enviado, String chat_id_Telegram){
   170   char texto_entrada[460] ;
   171   char caracter_entrada= '?';
   172   int contador_caracteres=0;
   173   IPAddress server(149,154,167,198);
   174   if (client.connect(server, 443)) {
   175     client.println("GET /bot" + Telegram_BOTtoken + "/sendMessage?chat_id=" + chat_id_Telegram + "&text=" + texto_enviado + "&reply_markup=" + "");
   176     while (client.available() && (contador_caracteres < longitud_maxima_cadena - 1)) {
   177         caracter_entrada = client.read();
   178         texto_entrada [contador_caracteres]= caracter_entrada;
   179         contador_caracteres++;
   180     }
   181     texto_entrada [contador_caracteres] ='\0';
   182   }
   183   if (strstr (texto_entrada, "{\"ok\":true") != NULL) return false;
   184   else return true;
   185 }
   186 
   187 
   188 
   189 /*****************************************************************************************
   190  * FUNCIÓN: inicializa_telegram (String token, String nombre, String nombreusuario)
   191  * Recibe las variables para ponerlas como variables globales de la función de librería
   192  ****************************************************************************************/
   193  void inicializa_telegram (String token, String nombre, String nombreusuario){
   194   Telegram_BOTtoken = token;
   195   Telegram_BOTname = nombre;
   196   Telegram_username = nombreusuario;
   197  }
   198 
   199 /****************************************************************************************
   200  * 
   201  * *************************************************************************************/
   202 
   203 void gestionar_mensajes_Telegram(){
   204   bool mensajes_en_cola = false;
   205   do{
   206     mensajes_en_cola = leer_mensajes_Telegram ();
   207     if(mensajes_en_cola != false){
   208       if (from_id == USUARIO_ACREDITADO_TELEGRAM){
   209         if (comando_bot == true){
   210           if(text == "\/activa") {
   211             if (mensaje_telegram_panel != ""){
   212               mensaje_telegram_a_panel = true;
   213               escribir_mensajes_Telegram ("ACTIVADO EL MENSAJE: ", chat_id);
   214               escribir_mensajes_Telegram (panel_LED_a_UTF8(mensaje_telegram_panel), chat_id);
   215             }
   216             else escribir_mensajes_Telegram ("NO HAY MENSAJES PARA MOSTRAR. EDITE PREVIAMENTE EL MENSAJE", chat_id);
   217 
   218           }
   219           else if (text == "\/desactiva"){
   220             mensaje_telegram_a_panel = false;
   221             escribir_mensajes_Telegram ("DESACTIVADO EL MENSAJE: " , chat_id);
   222             escribir_mensajes_Telegram (panel_LED_a_UTF8(mensaje_telegram_panel), chat_id);
   223           }
   224           else if (text == "\/start"){
   225             escribir_mensajes_Telegram ("I.E.S. Al-Baytar. Arroyo de la Miel. www.albaytar.es", chat_id);
   226             escribir_mensajes_Telegram ("Todos los detalles de este proyecto en: www.fpbasicaelectricidad.blogspot.com", chat_id);
   227             escribir_mensajes_Telegram ("Son las: " + hora_actual + " del " + fecha_actual + ". " + temperatura_actual + " en Benalmádena.", chat_id);
   228           }
   229         }
   230         else{
   231           mensaje_telegram_panel = convertUnicode (text);
   232           mensaje_telegram_a_panel = false;
   233           if (mensaje_telegram_panel!=""){
   234             escribir_mensajes_Telegram ("MENSAJE RECIBIDO: ", chat_id);
   235             escribir_mensajes_Telegram (panel_LED_a_UTF8(mensaje_telegram_panel), chat_id);
   236             escribir_mensajes_Telegram ("No olvide activar la salida a panel con el comando: \/activa", chat_id);
   237           }
   238           
   239         }
   240      }
   241       else {
   242             escribir_mensajes_Telegram ("I.E.S. Al-Baytar. Arroyo de la Miel. www.albaytar.es", chat_id);
   243             escribir_mensajes_Telegram ("Todos los detalles de este proyecto en: www.fpbasicaelectricidad.blogspot.com", chat_id);
   244             escribir_mensajes_Telegram ("SON LAS: " + hora_actual + " del " + fecha_actual_corta + ". TEMPERATURA: " + temperatura_actual + " EN BENALMADENA", chat_id);
   245       }
   246     }
   247   }while (mensajes_en_cola == true);
   248 }

ARCHIVO 6. VARIABLES_GLOBALES.h

Source file
     1 /************************************************************************
     2  * PROYECTO LETRERO FPB CURSO 2016-2017
     3  * FICHERO: variables_globales.h
     4  * Francisco J. Jiménez 
     5  * fpbásicalectricidad.blogspot.com
     6  * noviembre 2016 - marzo 2017
     7  * *********************************************************************/
     8 
     9 // WUNDERGROUND
    10 // CADENAS DE TEXTO Y BUFFER DE MEMORIA CARACTERES
    11 String datos_del_tiempo_actual; // = "SIN DATOS DEL TIEMPO EN BENALMÁDENA";
    12 String datos_de_astronomia; // = "SIN DATOS DE ASTRONOMÍA";
    13 String datos_de_prevision_1; // = "SIN DATOS DE PREVISIÓN DEL TIEMPO";
    14 String datos_de_prevision_2; // = "SIN DATOS DE PREVISIÓN DEL TIEMPO";
    15 String temperatura_actual;  // Datos de temperatura 
    16 String mensaje_telegram_panel = "";
    17 String hora_actual = "00:00:00";
    18 String fecha_actual= "Viernes, 01 de Enero de 2016";
    19 String fecha_actual_corta= "01/01/16";
    20 time_t epoch_actual;
    21 static int INTERVALO_ACTULIZACION = 900;      // 900 segundos ---> cada 15 minutos
    22 static long epoch_minimo = 1483228800; // Corresponde al día 1 de enero de 2017 a las 0:00:00 horas.
    23 
    24 const char SIN_DATOS_PREVISION []= "SIN DATOS DE PREVISION";
    25 const char SIN_DATOS_TIEMPO []= "SIN DATOS DEL TIEMPO";
    26 const char SIN_DATOS_ASTRONOMIA []= "SIN DATOS DE ASTRONOMIA";
    27 
    28 // TELEGRAM
    29 // ACTIVADO - DESACTIVADO DE MENSAJES DE TELEGRAM
    30 
    31 bool mensaje_telegram_a_panel = true;
    32 
    33 const PROGMEM char BIENVENIDA_TELEGRAM_1[]= "BIENVENIDO AL BOT DEL IES ALBAYTAR";
    34 const PROGMEM char BIENVENIDA_TELEGRAM_2[]= "Los comandos son: /TIEMPO : Datos del Tiempo. /PREVISION: Previsión a 6 y 12 horas. /ASTRONOMIA: Datos astronómicos del Sol y la Luna. /ON: Activa el Mensaje. /OFF Desactiva el mensaje";
    35 const PROGMEM char TEXTO_USUARIO_NO_ACREDITADO []= "Gracias por su visita. Usted no puede escribir mensajes en el panel del IES Al-Baytar. http://www.albaytar.es/";

ARCHIVO 7. WUNDERGROUND.ino

Source file
     1 /****************************
     2  * 
     3  * LIBRERÍA DE ADQUISICIÓN DE DATOS CON LA API DE WUNDERGROUND
     4  * fpbasicaelectricidad.blogspot.com
     5  * MIT License (MIT) Copyright (c) 2015 by profesor_electricidad@hotmail.com
     6  * 
     7  * 
     8  * BASADO EN LA LIBRERÍA esp-wunderground.ino: https://gist.github.com/bbx10/149bba466b1e2cd887bf
     9  * The MIT License (MIT) Copyright (c) 2015 by bbx10node@gmail.com
    10  ******************************/
    11 //#include <ESP8266WiFi.h>
    12 //#include "VARIABLES_GLOBALES.H"
    13 #ifndef min
    14 #define min(x,y) (((x)<(y))?(x):(y))
    15 #endif
    16 #ifndef max
    17 #define max(x,y) (((x)>(y))?(x):(y))
    18 #endif
    19 #include <ArduinoJson.h>
    20 
    21 // DEFINICIÓN DE ERRORES
    22 #define TODO_BIEN 0
    23 #define OVERFLOW_BUFFER 1
    24 #define ERROR_DATOS 2
    25 #define ERROR_CONEXION 3
    26 
    27 
    28 //DEFINICIÓN DE TIPO DE DATOS PEDIDOS A SERVIDOR
    29 #define TIEMPO_ACTUAL 1
    30 #define ASTRONOMIA 2
    31 #define PREVISION 3
    32 
    33 // DATOS DE LA CONEXIÓN
    34 //const char SSID_[]     = "Andared";                                             // SSID ANDARED
    35 //const char PASSWORD[] = "llevalatararaunvestidoblancollenodecascabeles";       // CLAVE ANDARED
    36 
    37 
    38 // CADENAS DE TEXTO Y BUFFER DE MEMORIA CARACTERES
    39 //String datos_del_tiempo_actual = "SIN DATOS DEL TIEMPO EN BENALMÁDENA";
    40 //String datos_de_astronomia = "SIN DATOS DE ASTRONOMÍA";
    41 //String datos_de_prevision = "SIN DATOS DE PREVISIÓN DEL TIEMPO"; */
    42 //static char respBuf[8000];                  // BUFFER DE RESPUESTA DE DATOS DESDE EL SERVIDOR HTTP
    43 char respBuf[12*1024];
    44 
    45 // CADENA PARA LAS PETICIONES DE TIEMPO ACTUAL, PREVISIÓN Y ASTRONOMÍA
    46 const char WUNDERGROUND_ACTUAL[] =
    47   "GET /api/" WU_API_KEY "/conditions/lang:SP/q/" WU_LOCATION ".json HTTP/1.1\r\n"
    48   "User-Agent: ESP8266/0.1\r\n"
    49   "Accept: */*\r\n"
    50   "Host: " WUNDERGROUND "\r\n"
    51   "Connection: close\r\n"
    52   "\r\n";
    53 
    54 const char WUNDERGROUND_ASTRONOMIA[] =
    55   "GET /api/" WU_API_KEY "/astronomy/lang:SP/q/" WU_LOCATION ".json HTTP/1.1\r\n"
    56   "User-Agent: ESP8266/0.1\r\n"
    57   "Accept: */*\r\n"
    58   "Host: " WUNDERGROUND "\r\n"
    59   "Connection: close\r\n"
    60   "\r\n";
    61 
    62 const char WUNDERGROUND_PREVISION[] =
    63   "GET /api/" WU_API_KEY "/forecast/lang:SP/q/" WU_LOCATION ".json HTTP/1.1\r\n"
    64   "User-Agent: ESP8266/0.1\r\n"
    65   "Accept: */*\r\n"
    66   "Host: " WUNDERGROUND "\r\n"
    67   "Connection: close\r\n"
    68   "\r\n";
    69 ///////////////////////////////////////////////////////////////////////////////////////////////
    70 ///////////////////////////////////////////////////////////////////////////////////////////////
    71 
    72 boolean conectar_wifi(){
    73   WiFi.begin(SSID_, PASSWORD);
    74   unsigned long tiempo = millis();
    75   do{
    76     if(WiFi.status() == WL_CONNECTED){
    77       //Serial.print("Conectado");
    78       return true;
    79     }
    80     delay(500);
    81   } while ((millis()-tiempo)<5000); // intenta la conexión durante 5 segundos
    82   WiFi.disconnect(); 
    83   return false;
    84 }
    85 
    86 ///////////////////////////////////////////////////////////////////////////////////////////////
    87 // FUNCIONES PÚBLICAS QUE ACTUALIZAN LAS VARIABLES GLOBALES
    88 ///////////////////////////////////////////////////////////////////////////////////////////////
    89 
    90 boolean actualizar_datos_tiempo_actual(){
    91   for (int f=0; f<=2; f++){
    92     if (conexion_servidor_wonderground(TIEMPO_ACTUAL) == TODO_BIEN) {
    93       if (actualizar_texto_tiempo_actual(respBuf)) return true;
    94     }
    95   }
    96   datos_del_tiempo_actual = " ";
    97   return false;
    98 }
    99 
   100 boolean actualizar_datos_astronomia(){
   101   for (int f=0; f<=2; f++){
   102     if (conexion_servidor_wonderground(ASTRONOMIA) == TODO_BIEN) {
   103       if (actualizar_texto_astronomia(respBuf)) return true;
   104     }
   105   }
   106   datos_de_astronomia = " ";
   107   return false;
   108 }
   109 
   110 boolean actualizar_datos_prevision(){
   111   for (int f=0; f<=2; f++){
   112     if (conexion_servidor_wonderground(PREVISION) == TODO_BIEN) {
   113       if (actualizar_texto_prevision(respBuf)) return true;
   114     }
   115   }
   116   datos_de_prevision_1 = " ";
   117   datos_de_prevision_2 = " ";
   118   return false;
   119 }
   120 
   121 
   122 ///////////////////////////////////////////////////////////////////////////////////////////////
   123 ///////////////////////////////////////////////////////////////////////////////////////////////
   124 
   125 int conexion_servidor_wonderground(int tipo_peticion) {
   126   int f = 0;                            // Constate f para iteraciones bucles for
   127   const int httpPort = 80;              // Puerto HTTP
   128   WiFiClient httpclient;                // WiFiClient class
   129   unsigned long tiempo = millis();
   130   
   131   // CREAR CONEXIONES TCP USANDO LA CLASE WiFiClient class
   132   for (f = 0; f < 5; f++) {
   133     if (httpclient.connect(WUNDERGROUND, httpPort)) break;    // Si se conecta sale del bucle
   134     if (f > 3) return (ERROR_CONEXION);                       // Si no conecta devuelve ERROR_CONEXION
   135     delay (1);
   136   }
   137   // ENVIAR PETICIÓN AL SERVIDOR HTTP
   138   if (tipo_peticion == ASTRONOMIA) httpclient.print(WUNDERGROUND_ASTRONOMIA);          // WUNDERGROUND_ACTUAL, WUNDERGROUND_PREVISION O ASTRONOMÍA
   139   else if (tipo_peticion == TIEMPO_ACTUAL) httpclient.print(WUNDERGROUND_ACTUAL);
   140   else if (tipo_peticion == PREVISION) httpclient.print(WUNDERGROUND_PREVISION);
   141   else return (ERROR_CONEXION);
   142   httpclient.flush();
   143 
   144   // RECIBIR LOS DATOS DEL SERVIDOR HTTP EN FORMATO JSON Y GUARDARLOS EN respBuf.
   145 
   146   int respLen = 0;
   147   bool skip_headers = true;
   148   while (httpclient.connected() || httpclient.available()) {
   149     if ((millis()-tiempo) > 5000) return (ERROR_CONEXION);              // Demasiado tiempo de conexión
   150     // SE DESCARTA LA CABECERA HTTP
   151     if (skip_headers) {
   152       String aLine = httpclient.readStringUntil('\n');
   153       if (aLine.length() <= 1) {                                // UNA LÍNEA EN BLANCO INDICA EL FIN DE LA CABECERA
   154         skip_headers = false;
   155       }
   156     }
   157     // UNA VEZ DESCARTADA LA CABECERA, LOS DEMÁS DATOS VAN A respBuf
   158     else {
   159       unsigned int bytesIn;
   160       bytesIn = httpclient.read((uint8_t *)&respBuf[respLen], sizeof(respBuf) - respLen);
   161       
   162       if (bytesIn > 0) {
   163         respLen += bytesIn;
   164         
   165         if (respLen > sizeof(respBuf)) respLen = sizeof(respBuf);
   166       }
   167       else if (bytesIn < 0) {
   168         //Serial.println("error datos ---------------------------");
   169         return (ERROR_DATOS);
   170       }
   171     }
   172     delay(1);
   173   }
   174   httpclient.stop();                                        // SE CIERRA LA CONEXIÓN HTTP
   175   respBuf[sizeof(respBuf)] = '\0'; 
   176   if (respLen<10) return (ERROR_DATOS);                      // No hay datos
   177   if (respLen >= sizeof(respBuf)) {
   178     respBuf[sizeof(respBuf)] = '\0';                      // LA CADENA ES DEMASIADO LARGA Y SE TRUNCA AL TAMAÑO DEL BUFFER.
   179     return (OVERFLOW_BUFFER);                             // LA CADENA DE FORECAST ES MUY LARGA PERO SOLO NECESITAMOS LOS PRIMEROS DATOS
   180   }                                                       // SI BUFFER LO HACEMOS MÁS GRANDE TENEMOS PROBLEMAS DE MEMORIA EN EL ESP8266 O NODEMCU
   181   // ESCRIBIR CARACTER DE FIN DE CADENA EN respBuf
   182   respBuf[respLen++] = '\0';
   183   //Serial.println(respBuf);
   184   return (TODO_BIEN);
   185 }
   186 
   187 ///////////////////////////////////////////////////////////////////////////////////////////////
   188 ///////////////////////////////////////////////////////////////////////////////////////////////
   189 
   190 bool actualizar_texto_tiempo_actual(char *json)
   191 {
   192   if (strlen(json)<300){                               // EVITA ERRORES SI NO SE RECIBEN DATOS
   193     //datos_del_tiempo_actual = SIN_DATOS_TIEMPO;
   194     return false;
   195   }
   196   
   197   StaticJsonBuffer<3 * 1024> jsonBuffer;
   198     
   199   // Ignorar caracteres hasta la primera llave '{', e ignorar la longitud fragmentada, si existe.
   200   char *jsonstart = strchr(json, '{');
   201 
   202   if (jsonstart == NULL) {
   203     //datos_del_tiempo_actual = SIN_DATOS_TIEMPO;
   204     return false;
   205   }
   206   json = jsonstart;
   207 
   208   // Analizar el JSON
   209   JsonObject& root = jsonBuffer.parseObject(json);
   210   if (!root.success()) {
   211     return false;
   212   }
   213   // Extract weather info from parsed JSON
   214 
   215   JsonObject& current = root["current_observation"];
   216   const float temp_f = current["temp_f"];
   217   const float temp_c = current["temp_c"];
   218   const char *humi = current[F("relative_humidity")];
   219   const char *weather = current["weather"];
   220   const char *pressure_mb = current["pressure_mb"];
   221   //const char *observation_time = current["observation_time_rfc822"];
   222   const char *wind_dir = current["wind_dir"];
   223   const char *wind_kph = current["wind_kph"];
   224   const char *dewpoint_c = current["dewpoint_c"];
   225   const char *precip_today_metric = current["precip_today_metric"];
   226   //const char *local_tz_short = current["local_tz_short"];
   227   //const char *local_tz_long = current["local_tz_long"];
   228   const char *local_tz_offset = current["local_tz_offset"];
   229   const char *local_epoch = current["local_epoch"];
   230   const char *radiacion_UV = current["UV"];
   231 
   232   if (temp_f == 0){
   233     //datos_del_tiempo_actual = SIN_DATOS_TIEMPO;
   234     return false;            // HAY UN ERROR EN LOS DATOS JSON. NO ACTUALIZAR.
   235   }
   236 
   237   datos_del_tiempo_actual = "AHORA: " +
   238                             String (temp_c) + "ºC. "
   239                             + String (weather)
   240                             + ". Viento del " + String (wind_dir) + " a " + String(wind_kph) + "Km/h."
   241                             + " Precip (hoy): " + String (precip_today_metric) + "l/m2. HumRel:" + String (humi)
   242                             + " P.Rocío:" + String (dewpoint_c) + "ºC. Bar:"                                                   
   243                             + String (pressure_mb) +  "mbar. UV:" + String (radiacion_UV);
   244   
   245 
   246   if (datos_del_tiempo_actual.length() > 50) {
   247     long epoch_local_ultimo =  atol (local_epoch);
   248     if (epoch_local_ultimo > epoch_minimo ){          // La fecha y hora están bien
   249       epoch_actual = (time_t) ((atol (local_epoch)) + (atoi (local_tz_offset) *36));      // ACTUALIZAR FECHA - HORA SIN NTP
   250       setTime (epoch_actual);
   251     }
   252     // else ----> si no está bien la fecha y la hora, no se actualiza y se mantiene la del reloj del sistema                                                      
   253     if (temp_c > 0) temperatura_actual = "+";                                       // ACTUALIZAR TEMPERATURA
   254     else temperatura_actual = " ";
   255     temperatura_actual += String (temp_c,1) + "ºC";
   256     return true;
   257   }
   258   
   259   return false;
   260 }
   261 
   262 ///////////////////////////////////////////////////////////////////////////////////////////////
   263 ///////////////////////////////////////////////////////////////////////////////////////////////
   264 
   265 bool actualizar_texto_astronomia (char *json)
   266 {
   267   
   268   if (strlen(json)<300){                               // EVITA ERRORES SI NO SE RECIBEN DATOS
   269     //datos_de_astronomia = SIN_DATOS_ASTRONOMIA;
   270     return false;
   271   }
   272   
   273   StaticJsonBuffer<3 * 1024> jsonBuffer;      // BUFFER DEL FICHERO JSON
   274   
   275   // Ignorar caracteres hasta la primera llave '{', e ignorar la longitud fragmentada, si existe.
   276 
   277   char *jsonstart = strchr(json, '{');
   278 
   279   if (jsonstart == NULL) {
   280     //datos_de_astronomia = SIN_DATOS_ASTRONOMIA;
   281     return false;
   282   }
   283   json = jsonstart;
   284 
   285   // Analizar el JSON
   286   JsonObject& root = jsonBuffer.parseObject(json);
   287   if (!root.success()) {
   288     
   289     return false;
   290   }
   291   // Extract weather info from parsed JSON
   292 
   293   JsonObject& current = root ["astronomy"];
   294 
   295   const char *fase_lunar =  (root["moon_phase"]["phaseofMoon"]);
   296   const char *luna_porcent_iluminada =  (root["moon_phase"]["percentIlluminated"]);
   297   int luna_sale_hora = root["moon_phase"]["moonrise"]["hour"];
   298   int luna_sale_minuto = root["moon_phase"]["moonrise"]["minute"];
   299   int luna_pone_hora = root["moon_phase"]["moonset"]["hour"];
   300   int luna_pone_minuto = root["moon_phase"]["hour"]["minute"];
   301   int sol_sale_hora = (root["sun_phase"]["sunrise"]["hour"]);
   302   int sol_sale_minuto =  (root["sun_phase"]["sunrise"]["minute"]);
   303   int sol_pone_hora = root["sun_phase"]["sunset"]["hour"];
   304   int sol_pone_minuto = root["sun_phase"]["sunset"]["minute"];
   305 
   306   datos_de_astronomia = "SOL: ";
   307   if (sol_sale_hora < 9) datos_de_astronomia += "0";
   308   datos_de_astronomia += String(sol_sale_hora) + ":";
   309   if (sol_sale_minuto < 9) datos_de_astronomia += "0";
   310   datos_de_astronomia +=  String(sol_sale_minuto)   + "-";
   311   if (sol_pone_hora < 9) datos_de_astronomia += "0";
   312   datos_de_astronomia +=  String (sol_pone_hora) + ":";
   313   if (sol_pone_minuto < 9) datos_de_astronomia += "0";
   314   datos_de_astronomia += String (sol_pone_minuto) + ". LUNA: ";
   315   if (luna_sale_hora < 9) datos_de_astronomia += "0";
   316   datos_de_astronomia += String (luna_sale_hora) + ":";
   317   if (luna_sale_minuto < 9) datos_de_astronomia += "0";
   318   datos_de_astronomia += String (luna_sale_minuto)  + "-";
   319   if (luna_pone_hora < 9) datos_de_astronomia += "0";
   320   datos_de_astronomia += String (luna_pone_hora) + ":";
   321   if (luna_pone_minuto < 9) datos_de_astronomia += "0";
   322   datos_de_astronomia += String (luna_pone_minuto)
   323                             + ". FASE: " + String (fase_lunar) + ", " + String (luna_porcent_iluminada) + "%.";
   324                             
   325   //datos_de_astronomia = ascii_panel_LED( datos_de_astronomia);
   326   return true;
   327 }
   328 
   329 ///////////////////////////////////////////////////////////////////////////////////////////////
   330 ///////////////////////////////////////////////////////////////////////////////////////////////
   331 
   332 bool actualizar_texto_prevision(char *json){
   333 char *p_ini, *p_fin;
   334   char datos[600];
   335   int lon_cad=0;
   336   p_ini=json;
   337    
   338   if (strlen(json)<400){                               // EVITA ERRORES SI NO SE RECIBEN DATOS
   339     //datos_de_prevision_1 = SIN_DATOS_PREVISION;
   340     //datos_de_prevision_2 = SIN_DATOS_PREVISION;
   341     return false;
   342   }
   343   
   344   
   345   //datos_de_prevision_1 = "";
   346   //datos_de_prevision_2 = "";
   347 
   348   for (int veces=0; veces<3; veces++){                 // DATOS DE PREVISIÓN DE DOS PERIODOS O SEA 1 DÍA
   349     p_ini=strstr (p_ini, "\"title\":\"") + 9;          // BUSCA EL TÍTULO DE LA PREVISIÓN
   350     if (p_ini == NULL){ 
   351       //datos_de_prevision_1 = SIN_DATOS_PREVISION;
   352       //datos_de_prevision_2 = SIN_DATOS_PREVISION;
   353       return false;
   354     }
   355     p_fin=p_ini;
   356     p_fin=strstr (p_fin, "\",");
   357     if( (lon_cad = p_fin - p_ini) >=500) return false;
   358     strncpy (datos, p_ini, lon_cad);
   359     datos[lon_cad++] = '\0';
   360     //Serial.println(datos);
   361 
   362     if (veces==1) datos_de_prevision_1 = String (datos);            // NO SE PONEN LOS DATOS DE LA PREVISIÓN 0 veces=0
   363     else if (veces==2) datos_de_prevision_2 = String (datos);
   364     p_ini=strstr (p_fin, "\"fcttext_metric\":\"") + 18;             // BUSCA EL TEXTO DE LA PREVISIÓN
   365     if (p_ini == NULL){
   366       //datos_de_prevision_1 = SIN_DATOS_PREVISION;
   367       //datos_de_prevision_2 = SIN_DATOS_PREVISION;
   368       return false;
   369     }
   370     p_fin=p_ini;
   371     p_fin=strstr (p_fin, "\",\n");
   372     if( (lon_cad = p_fin - p_ini) >=500) return false;
   373     strncpy (datos, p_ini, lon_cad);
   374     datos[lon_cad++] = '\0';
   375     //Serial.println(datos);
   376     if (veces==1) datos_de_prevision_1 += ": " + String (datos) + "  "; // NO SE PONEN LOS DATOS DE LA PREVISIÓN 0 veces=0
   377     if (veces==2) datos_de_prevision_2 += ": " + String (datos) + "  "; // NO SE PONEN LOS DATOS DE LA PREVISIÓN 0 veces=0
   378 
   379   }
   380   //datos_de_prevision_1 = ascii_panel_LED(datos_de_prevision_1);
   381   //datos_de_prevision_2 = ascii_panel_LED(datos_de_prevision_2);
   382   return true;
   383 }

ARCHIVO 8. _CODIGO_DISPLAY.ino

Source file
     1 //***************************************************************//
     2 //  NOMBRE    : PROGRAMA_MATRIZ_FPB_2016                              
     3 //  AUTOR     : FRANCISCO J. JIMÉNEZ 
     4 //  BASADO EN : By Hari Wiguna http://g33k.blogspot.com/ Creative Commons Attribution-Share Alike 3.0 United States License
     5 //  FECHA     : 17 OCTUBRE 2016    
     6 //  MODIFICADO: 29 DICIEMBRE 2016                                 
     7 //  VERSIÓN   : 1.2 BETA                                            
     8 //  NOTAS     : MATRIZ 64X8 USANDO REGISTROS DE DESPLAZAMIENTO 74HC595 
     9 //****************************************************************//
    10 static byte fuente_5x8[][5] = {
    11   0x00, 0x00, 0x00, 0x00, 0x00,// (espacio)
    12   0x00, 0x00, 0x5F, 0x00, 0x00,// !
    13   0x00, 0x07, 0x00, 0x07, 0x00,// "
    14   0x14, 0x7F, 0x14, 0x7F, 0x14,// #
    15   0x24, 0x2A, 0x7F, 0x2A, 0x12,// $
    16   0x23, 0x13, 0x08, 0x64, 0x62,// %
    17   0x36, 0x49, 0x55, 0x22, 0x50,// &
    18   0x00, 0x05, 0x03, 0x00, 0x00,// '
    19   0x00, 0x1C, 0x22, 0x41, 0x00,// (
    20   0x00, 0x41, 0x22, 0x1C, 0x00,// )
    21   0x08, 0x2A, 0x1C, 0x2A, 0x08,// *
    22   0x08, 0x08, 0x3E, 0x08, 0x08,// +
    23   0x00, 0xA0, 0x60, 0x00, 0x00,// ,       cambiado de 0x00, 0x50, 0x30, 0x00, 0x00
    24   0x08, 0x08, 0x08, 0x08, 0x08,// -
    25   0x00, 0x60, 0x60, 0x00, 0x00,// .       cambiado de 0x30 a 0x60
    26   0x20, 0x10, 0x08, 0x04, 0x02,// /
    27   0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
    28   0x00, 0x42, 0x7F, 0x40, 0x00,// 1
    29   0x42, 0x61, 0x51, 0x49, 0x46,// 2
    30   0x21, 0x41, 0x45, 0x4B, 0x31,// 3
    31   0x18, 0x14, 0x12, 0x7F, 0x10,// 4
    32   0x27, 0x45, 0x45, 0x45, 0x39,// 5
    33   0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
    34   0x01, 0x71, 0x09, 0x05, 0x03,// 7
    35   0x36, 0x49, 0x49, 0x49, 0x36,// 8
    36   0x06, 0x49, 0x49, 0x29, 0x1E,// 9
    37   0x00, 0x36, 0x36, 0x00, 0x00,// :
    38   0x00, 0x56, 0x36, 0x00, 0x00,// ;
    39   0x00, 0x08, 0x14, 0x22, 0x41,// <
    40   0x14, 0x14, 0x14, 0x14, 0x14,// =
    41   0x41, 0x22, 0x14, 0x08, 0x00,// >
    42   0x02, 0x01, 0x51, 0x09, 0x06,// ?
    43   0x32, 0x49, 0x79, 0x41, 0x3E,// @
    44   0x7E, 0x11, 0x11, 0x11, 0x7E,// A
    45   0x7F, 0x49, 0x49, 0x49, 0x36,// B
    46   0x3E, 0x41, 0x41, 0x41, 0x22,// C
    47   0x7F, 0x41, 0x41, 0x22, 0x1C,// D
    48   0x7F, 0x49, 0x49, 0x49, 0x41,// E
    49   0x7F, 0x09, 0x09, 0x01, 0x01,// F
    50   0x3E, 0x41, 0x41, 0x51, 0x32,// G
    51   0x7F, 0x08, 0x08, 0x08, 0x7F,// H
    52   0x00, 0x41, 0x7F, 0x41, 0x00,// I
    53   0x20, 0x40, 0x41, 0x3F, 0x01,// J
    54   0x7F, 0x08, 0x14, 0x22, 0x41,// K
    55   0x7F, 0x40, 0x40, 0x40, 0x40,// L
    56   0x7F, 0x02, 0x04, 0x02, 0x7F,// M
    57   0x7F, 0x04, 0x08, 0x10, 0x7F,// N
    58   0x3E, 0x41, 0x41, 0x41, 0x3E,// O
    59   0x7F, 0x09, 0x09, 0x09, 0x06,// P
    60   0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
    61   0x7F, 0x09, 0x19, 0x29, 0x46,// R
    62   0x46, 0x49, 0x49, 0x49, 0x31,// S
    63   0x01, 0x01, 0x7F, 0x01, 0x01,// T
    64   0x3F, 0x40, 0x40, 0x40, 0x3F,// U
    65   0x1F, 0x20, 0x40, 0x20, 0x1F,// V
    66   0x7F, 0x20, 0x18, 0x20, 0x7F,// W
    67   0x63, 0x14, 0x08, 0x14, 0x63,// X
    68   0x03, 0x04, 0x78, 0x04, 0x03,// Y
    69   0x61, 0x51, 0x49, 0x45, 0x43,// Z
    70   0x00, 0x00, 0x7F, 0x41, 0x41,// [
    71   0x02, 0x04, 0x08, 0x10, 0x20,// "\"
    72   0x41, 0x41, 0x7F, 0x00, 0x00,// ]
    73   0x04, 0x02, 0x01, 0x02, 0x04,// ^
    74   0x40, 0x40, 0x40, 0x40, 0x40,// _
    75   0x00, 0x01, 0x02, 0x04, 0x00,// `
    76   0x20, 0x54, 0x54, 0x54, 0x78,// a
    77   0x7F, 0x48, 0x44, 0x44, 0x38,// b
    78   0x38, 0x44, 0x44, 0x44, 0x20,// c
    79   0x38, 0x44, 0x44, 0x48, 0x7F,// d
    80   0x38, 0x54, 0x54, 0x54, 0x18,// e
    81   0x08, 0x7E, 0x09, 0x01, 0x02,// f
    82   0x08, 0x14, 0x54, 0x54, 0x3C,// g
    83   0x7F, 0x08, 0x04, 0x04, 0x78,// h
    84   0x00, 0x44, 0x7D, 0x40, 0x00,// i
    85   0x20, 0x40, 0x44, 0x3D, 0x00,// j
    86   0x00, 0x7F, 0x10, 0x28, 0x44,// k
    87   0x00, 0x41, 0x7F, 0x40, 0x00,// l
    88   0x7C, 0x04, 0x18, 0x04, 0x78,// m
    89   0x7C, 0x08, 0x04, 0x04, 0x78,// n
    90   0x38, 0x44, 0x44, 0x44, 0x38,// o
    91   0x7C, 0x14, 0x14, 0x14, 0x08,// p
    92   0x08, 0x14, 0x14, 0x18, 0x7C,// q
    93   0x7C, 0x08, 0x04, 0x04, 0x08,// r
    94   0x48, 0x54, 0x54, 0x54, 0x20,// s
    95   0x04, 0x3F, 0x44, 0x40, 0x20,// t
    96   0x3C, 0x40, 0x40, 0x20, 0x7C,// u
    97   0x1C, 0x20, 0x40, 0x20, 0x1C,// v
    98   0x3C, 0x40, 0x30, 0x40, 0x3C,// w
    99   0x44, 0x28, 0x10, 0x28, 0x44,// x
   100   0x0C, 0x50, 0x50, 0x50, 0x3C,// y
   101   0x44, 0x64, 0x54, 0x4C, 0x44,// z
   102   0x00, 0x08, 0x36, 0x41, 0x00,// {
   103   0x00, 0x00, 0x7F, 0x00, 0x00,// |
   104   0x00, 0x41, 0x36, 0x08, 0x00,// }
   105   0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
   106   0x08, 0x1C, 0x2A, 0x08, 0x08, // <-
   107 // FUENTES ESPECIALES ESPAÑOL
   108   0x20,0x54,0x56,0x55,0x78,  // á   ascii 225
   109   0x38,0x54,0x56,0x55,0x58,  // é   ascii 233
   110   0x00,0x44,0x7C,0x42,0x01,  // í   ascii 237
   111   0x38,0x44,0x44,0x46,0x39,  // ó   ascii 243
   112   0x3C,0x40,0x42,0x21,0x7C,  // ú   ascii 250
   113   0x7C,0x09,0x05,0x05,0x78,  // ñ   ascii 241
   114   0x7E,0x05,0x09,0x11,0x7E,  // Ñ   ascii 209
   115   0x04,0x0A,0x0A,0x04,0x00   // º Símbolo de grados ascii 186
   116 };
   117 
   118 // VARIABLES GLOBALES
   119 
   120 // REGISTRO DE DESPLAZAMIENTO 74HC595 (PRIMERO FILAS 0Vcc Y LUEGO COLUMNAS +5V)
   121 int latchPin595 = D7; // Lacth de los 74595 
   122 int relojPin595 = D6; // Reloj CLK de los 74595
   123 int dataPin595 = D5;  // Datos de los 74595. En cascada, siendo el último (primer dato) las filas, y el primero (último dato) las primera columna de la izquierda
   124 
   125 //=== B I T M A P ===
   126 // Los bits de este array representan cada uno de los LED's de la matriz
   127 #define columnas_led_matriz 8
   128 #define matrices_led_panel 8
   129 byte mapeoBIT[columnas_led_matriz][matrices_led_panel]; // 8 matrices de 8 culumnas cada una
   130 int numZonas = sizeof(mapeoBIT) / 8; // I will refer to each group of 8 columns (represented by one matrix) as a zona.
   131 int maxIndiceZonas = numZonas-1;
   132 int numCols = numZonas * 8;
   133 
   134 
   135 /**********************************************************/
   136 /* función: void inicializar_registros();
   137 /* uso :    inicializa los las salidas del arduino 
   138 /*          conectadas a los registros de desplazamiento
   139 /*********************************************************/
   140 
   141 void inicializar_registros() { 
   142   pinMode(latchPin595, OUTPUT);
   143   pinMode(relojPin595, OUTPUT);
   144   pinMode(dataPin595, OUTPUT);
   145   
   146   limpiar_panel();
   147 }
   148 
   149 /**********************************************************/
   150 /* función: void limpiar_panel();
   151 /* uso :    Pone a 0 todos los bits de la matriz para 
   152 /*          apagar todos los LED's del panel
   153 /*********************************************************/
   154 
   155 void limpiar_panel() {
   156   for (int fila=0; fila<8; fila++) {
   157     for (int zona=0; zona<numZonas; zona++) {
   158       mapeoBIT[fila][zona] = 0;
   159     } 
   160   }
   161   Refrescar_Display();
   162 }
   163 
   164 /**********************************************************/
   165 /* función: Refrescar_Display();
   166 /* uso :    Rutina encargada de escribir los registros de desplazamiento 74HC595
   167 /*          para que sean visibles los LED's iluminados
   168 /*********************************************************/
   169 
   170 void Refrescar_Display() {
   171 
   172   // REPETIR 8 VECES. UNA POR CADA UNA DE LAS FILAS //
   173   for (int fila = 0; fila < 8; fila++) {
   174     // ESCRIBIR SOBRE LA FILA. ÚLTIMO REGISTRO DE DESPLAZAMIENTO//
   175     int BIT_de_fila =  (1 << fila);  // ESCRIBO 1 PARA DEJAR PASAR LA CORRIENTE POR EL PAR DARLINTON
   176     digitalWrite(latchPin595, LOW);  // Mantener el Latch en LOW mientras se escriben los datos.
   177     //delay(1);
   178     shiftOut(dataPin595, relojPin595, LSBFIRST, BIT_de_fila);
   179     
   180     // ESCRIBIR SOBRE LAS COLUMNAS COMENZANDO DE DERECHA A IZQUIERDAS //
   181     for (int zona = 0 ; zona <= maxIndiceZonas; zona++) {
   182       shiftOut(dataPin595, relojPin595, LSBFIRST, mapeoBIT[fila][zona]);
   183     }
   184     //delay(1);
   185     digitalWrite(latchPin595, HIGH);  // Activar los LACTH en ON
   186 
   187     //esperar un tiempo para que se enciendan los LED's y puedan ser vistos por el ojo humano
   188     delay(1);
   189   }
   190 }
   191 
   192 /**********************************************************/
   193 /* función: void Actualizar_mapeoBITs(int columna, int fila, bool es_ON);
   194 /* uso :    Escribe un 0 ó un 1 en la posición de la matrix mapeoBIT[fila][zona]
   195 /*          manteniendo los demás datos de la metrix inalterados.
   196 /*********************************************************/
   197 void Actualizar_mapeoBITs(int columna, int fila, bool es_ON) {
   198   int zona = columna/ 8;
   199   int Indice_BIT_columna = columna% 8;
   200   byte BIT_columna = 1 << Indice_BIT_columna;
   201   if (zona<numZonas) {
   202     if (es_ON)
   203       mapeoBIT[fila][zona] =  mapeoBIT[fila][zona] | BIT_columna;
   204     else
   205       mapeoBIT[fila][zona] =  mapeoBIT[fila][zona] & (~BIT_columna);
   206   }
   207 }
   208 
   209 /**********************************************************/
   210 /* función:   escribe_mensaje_LED(String mensaje_LED);
   211 /* uso :      Escribe un mensaje con DESPLAZAMIENTO en la pantalla de LED's
   212 /* ATENCIÓN:  NO SALE DE LA RUTINA HASTA QUE HAYA COMPLETADO DE ESCRIBIR TODO EL MENSAJE
   213 /*********************************************************/
   214 void escribe_mensaje_LED(String mensaje_LED){
   215   //mensaje_LED = "FP BASICA ELECTRICIDAD. DICIEMBRE 2016. http://fpbasicaelectricidad.blogspot.com.es/";
   216   //String mensaje_LED = ascii_panel_LED(mensaje_LED_UTF8);
   217   //Serial.print("mensaje_LED");Serial.println(mensaje_LED); Serial.println(mensaje_LED.length());
   218  
   219   for (int Indice_caracteres=0; Indice_caracteres < mensaje_LED.length(); Indice_caracteres++) {
   220     int Indice_letras = mensaje_LED[Indice_caracteres] - ' ';
   221     //Serial.print(Indice_letras); Serial.print("-----");
   222     if (Indice_letras < 0) Indice_letras=0;
   223     if (Indice_letras>95){                                        // SÍMBOLOS ESPECIALES O CARACTERES ACENTUADOS EN ESPAÑOL
   224       Indice_letras = devuelve_indice_letras_LED(Indice_letras);  // CONVIERTE Indice_letras (Código UTF_8) a la posición de la matriz fuente_5x8[][5]
   225       
   226     }
   227     //Serial.println(Indice_letras);
   228     // Escribiendo en la matriz de mapeo de bit's según el caracter recibido y las fuentes de letras //
   229     // El bucle for se repite 7 veces. 5 veces por que la fuentes es de ancho 5 puntos y 2 puntos de espacio entre caracteres.
   230     for (int columna= 0; columna< 6; columna++) {  // 7 = 5 (letras) + 2 (espacio entre letras)
   231     
   232       for (int fila = 0; fila < 8; fila++) {
   233         // Set the pixel to what the alphabet say for columns 0 thru 4, but always leave columns 5 and 6 blank.
   234         bool es_ON = 0; 
   235         if (columna<5) es_ON = bitRead( fuente_5x8[Indice_letras][columna], 7-fila ) == 1;
   236         Actualizar_mapeoBITs( numCols-1, fila, es_ON); // We ALWAYS draw on the rightmost column, the shift loop below will scroll it leftward.
   237       }
   238       
   239       //REFRESCO DEL DISPLAY. A MAYOR TIEMPO DE REFRESCO, MÁS LENTO VAN LOS CARACTERES DESPLAZANDOSE EN EL DISPLAY //
   240       for (int cont_refrescos_display=0; cont_refrescos_display < 4; cont_refrescos_display++) {
   241         Refrescar_Display();
   242       }
   243       // DESPLAZAMOS UNA COLUMNA LA LETRA EN EL DISPLAY
   244       for (int fila=0; fila<8; fila++) {
   245         for (int zona=0; zona < numZonas; zona++) {
   246           // Aunque las columnas se desplazan en la matriz a la derecha en el display el desplzamiento es a izquierdas.
   247           mapeoBIT[fila][zona] = mapeoBIT[fila][zona] >> 1;
   248           
   249           // Desplaza el Byte más significativo de una zona a la posición menos significativa de la zona siguiente
   250           if (zona < maxIndiceZonas) bitWrite(mapeoBIT[fila][zona], 7, bitRead(mapeoBIT[fila][zona+1],0));
   251         }
   252       }
   253     }
   254   }
   255 }
   256 
   257 /**********************************************************/
   258 /* función:   escribir_texto_fijo(int charOffset, String mensaje_LED);
   259 /* uso :      Escribe un mensaje con FIJO en la pantalla de LED's
   260 /* ATENCIÓN:  
   261 /*********************************************************/
   262 int escribir_texto_fijo(int charOffset, String mensaje_LED_UTF8){
   263 
   264   String mensaje_LED = ascii_panel_LED(mensaje_LED_UTF8);
   265   //int devolver_ERROR = FALSE;
   266   int para_bucle = mensaje_LED.length();
   267   if(para_bucle > (matrices_led_panel+1)){                        // No cabe le mensaje de forma fija
   268     escribe_mensaje_LED(mensaje_LED);                             // Se envía a texto con desplazamiento
   269     return (true);
   270   }
   271   if ((para_bucle + charOffset) > (matrices_led_panel+1)) {        // Evitamos que el texto sea meyor que el número de matrices LED
   272     charOffset = ((matrices_led_panel+1) - para_bucle)/2;
   273     //devolver_ERROR = TRUE;
   274   }
   275   for (int Indice_caracteres=0; Indice_caracteres < para_bucle; Indice_caracteres++)
   276   {
   277     int Indice_letras = mensaje_LED[Indice_caracteres] - ' ';
   278     if (Indice_letras < 0) Indice_letras=0;
   279     if (Indice_letras>95){                                        // SÍMBOLOS ESPECIALES O CARACTERES ACENTUADOS EN ESPAÑOL
   280       Indice_letras = devuelve_indice_letras_LED(Indice_letras);  // CONVIERTE Indice_letras (Código UTF_8) a la posición de la matriz fuente_5x8[][5]
   281     }
   282     // ESCRIBIR CADA CARACTER DEL TEXTO
   283     // CARACTERES DE 5 COLUMNAS + 2 ESPACIOS ENTRE CARACTERES 5 + 2 = 7 ( bucle for)
   284     for (int columna= 0; columna< 7; columna++){
   285       for (int fila = 0; fila < 8; fila++){
   286         bool es_ON = 0; 
   287         if (columna<5) es_ON = bitRead( fuente_5x8[Indice_letras][columna], 7-fila ) == 1;
   288         Actualizar_mapeoBITs( (charOffset+Indice_caracteres)*7 + columna, fila, es_ON); 
   289       }
   290     }
   291   }
   292   return (false);    
   293 }
   294 
   295 /**********************************************************/
   296 /* función:   int devuelve_indice_letras_LED(int Indice_letras);
   297 /* uso :      Devuelve la posición que tiene una letra en la matriz fuente_5x8[][5]
   298 /*            Indice de letras ya tiene quitado los caracteres hasta el 32 (espacio)
   299 /*            o sea el número Indice_letras = Código_ASCII - 32
   300 /*********************************************************/
   301 int devuelve_indice_letras_LED(int Indice_letras) {
   302   if (Indice_letras < 0) Indice_letras=0;
   303   if (Indice_letras>95){                                        // SÍMBOLOS ESPECIALES O CARACTERES ACENTUADOS EN ESPAÑOL
   304       //Serial.print(Indice_letras);
   305       if (Indice_letras == 193) Indice_letras = 96;               // á
   306       else if (Indice_letras == 201) Indice_letras = 97;          // é
   307       else if (Indice_letras == 205) Indice_letras = 98;          // í
   308       else if (Indice_letras == 211) Indice_letras = 99;          // ó
   309       else if (Indice_letras == 218) Indice_letras = 100;         // ú
   310       else if (Indice_letras == 209) Indice_letras = 101;         // ñ
   311       else if (Indice_letras == 177) Indice_letras = 102;         // Ñ
   312       else if (Indice_letras == 154) Indice_letras = 103;         // Símbolo de grados º
   313       else if (Indice_letras == 161) Indice_letras = 33;         // Á se le quita la tilde --> A
   314       else if (Indice_letras == 169) Indice_letras = 37;         // É se le quita la tilde --> E
   315       else if (Indice_letras == 173) Indice_letras = 41;         // Í se le quita la tilde --> I
   316       else if (Indice_letras == 179) Indice_letras = 47;         // Ó se le quita la tilde --> O
   317       else if (Indice_letras == 186) Indice_letras = 53;         // Ú se le quita la tilde --> U
   318       else Indice_letras=31;                                      // Si es un símbolo fuera de ASCII se sustituye por el caracter ? (interrogación)//
   319   }
   320   return(Indice_letras);
   321 }

ARCHIVO 9. declaracion_funciones.h

Source file
     1 /************************************************************************
     2  * PROYECTO LETRERO FPB CURSO 2016-2017
     3  * FICHERO: declaracion_funciones.h
     4  * Francisco J. Jiménez 
     5  * fpbásicalectricidad.blogspot.com
     6  * noviembre 2016 - marzo 2017
     7  * *********************************************************************/
     8  
     9 void inicializar_registros();
    10 void limpiar_panel();
    11 void Refrescar_Display();
    12 void Actualizar_mapeoBITs(int columna, int fila, bool es_ON);
    13 void escribe_mensaje_LED(String mensaje_LED);
    14 int escribir_texto_fijo(int charOffset, String mensaje_LED_UTF8);
    15 int devuelve_indice_letras_LED(int Indice_letras);
    16 void escribe_LED_INICIANDO();
    17 
    18 
    19 boolean conectar_wifi();
    20 boolean actualizar_datos_tiempo_actual();
    21 boolean actualizar_datos_astronomia();
    22 boolean actualizar_datos_prevision();
    23 int conexion_servidor_wonderground(int tipo_peticion);
    24 bool actualizar_texto_tiempo_actual(char *json);
    25 bool actualizar_texto_astronomia (char *json);
    26 bool actualizar_texto_prevision(char *json);
    27 
    28 
    29 bool leer_mensajes_Telegram ();
    30 bool analiza_mensajes_telegram(char *json);
    31 String buscar_dato_json (char *puntero_json, char texto_dato[], char caracter_final[]);
    32 boolean escribir_mensajes_Telegram (String texto_enviado, String chat_id_Telegram);
    33 void inicializa_telegram (String token, String nombre, String nombreusuario);
    34 void gestionar_mensajes_Telegram();
    35 
    36 
    37 String ascii_panel_LED(String s);
    38 byte utf8ascii(byte ascii);
    39 String panel_LED_a_UTF8(String s);
    40 String convertUnicode(String unicodeStr);
    41 
    42 void inicializar_servidor_NTP();
    43 void actualizar_texto_hora();
    44 void printDigits(int digits);
    45 time_t getNtpTime();
    46 void sendNTPpacket(IPAddress &address);
    47 
    48 void presentar_en_DISPLAY (int dato);

No hay comentarios:

Publicar un comentario