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