Tutoriales

Clima actual con Raspberry Pi y LCD Nokia 5110 - Echando a andar el hilo del script weather

Echando a andar el hilo del script weather

Una vez inicializada la variable podremos arrancar un segundo hilo en nuestra aplicación. Un hilo es otra secuencia de ejecución de nuestro programa que corre por su cuenta. El hilo que crearemos se encargará de correr el script weather constantemente para tener los datos del clima actualizados cada cierto tiempo. La función main (hilo 1) se encargará de refrescar datos en la LCD cada que el hilo del script (hilo 2) obtenga datos del clima.

Para arrancar el segundo hilo es necesario contar con una función con un prototipo algo raro... una función que devuelve un apuntador tipo void* pero... que no lo devuelve al terminar.

void* Weather_Thread(void* data)

{

   while(1)

   {

      Weather_Get_Stats((Weather_Data_T*)data, Weather_ID);

      usleep(15000000);

   }

}

 

Esa función será con la que arrancará nuestro hilo 2. Ejecutará Weather_Get_Stats() y después dormirá 15 segundos, haciendo esto una y otra vez. Weather_Get_Stats() se encargará de actualizar los datos del clima.

 

Obteniendo datos del clima

Ya habíamos visto que el script weather devuelve varias líneas de texto con datos del clima. Nuestra aplicación se encargará de ejecutar el script y capturar esas líneas de texto, extrayendo los datos que nos interesan. Para poder capturar las líneas se usará la función popen() que puede ejecutar un programa y toda salida de texto que éste arroje podrá ser redirigida hacia nosotros.

   fp = popen(command, "r");

   if (fp == NULL)

   {

      printf("Failed to run \"%s\"\nTry with \"%s\"\n",

            command, WEATHER_INSTALL_COMMAND);

      return;

   }

 

El script lo llamaremos a través de la cadena command, la cual se armará con los siguientes defines:

#define WEATHER_COMMAND_P1 "weather --id="

#define WEATHER_COMMAND_P2 " -m --no-cache" 

Intercalando el ID que se haya proporcionado al ejecutar nuestra aplicación, que en mi caso es MMQT. El string resultante sería:

"weather --id=MMQT -m --no-cache"

La -m simplemente pide que los datos devueltos del clima vengan dados en unidades métricas.

Una vez que el script está corriendo, podremos atrapar el texto con la siguiente función...

fgets(text, sizeof(text)-1, fp) != NULL

Mientras fgets obtenga cadenas con datos, el script weather estará devolviendo líneas de texto. Cuando termine el script, fgets devolverá un NULL.

Ya teniendo las líneas, bastará con buscar patrones de texto con los que sabremos que el script nos está reportando la temperatura, velocidad del viento, estado del cielo, humedad relativa, y la ubicación que pedimos.

Simplemente ejecutamos strstr() que se encarga de buscar un string dentro de otro string. Si lo encuentra nos devuelve el apuntador, si no, nos da un NULL.

Veamos el caso de la búsqueda de la localidad, buscaremos la siguiente info en cada línea:

#define WEATHER_CITY_TEXT "Current conditions at "

      /* Get the city */

      found_str = strstr(text, WEATHER_CITY_TEXT);

      if(NULL != found_str)

      {

         pthread_mutex_lock(&Weather_Mutex);

         strncpy(weather_data->location,

               &text[strlen(WEATHER_CITY_TEXT)], WEATHER_TEXT_LENGTH);

         Weather_Clean_Newline(weather_data->location);

         pthread_mutex_unlock(&Weather_Mutex);

      }

 

Si la encuentra, entonces levantamos un mutex para apropiarnos de la variable weather para que el hilo 1 del main no la use mientras la modificamos. Se deposita la localidad en el string y bajamos el mutex.

Se usa Weather_Clean_Newline() ya que el texto trae enter y regreso de carro, que no nos sirven.

De esta forma, la variable weather siempre tendrá información actualizada gracias al script que está corriendo constantemente.