Weather script realmente simple con PHP o Javascript y JSON (Updated)

En el 2011 les compartí este artículo para obtener el estado del tiempo vía XML. En este utilizamos el API de Google Weather como fuente de datos. Hoy esta fuente solo está disponible bajo registro como developer, por lo que necesita user/AppID, etc. Pasado estos cuatro años sigo insistiendo en “keep it simple”. Por esto les traigo esta actualización con nuevas fuentes y tecnologías para crear nuestro script del tiempo.

Todos los servicios sobre el clima (google, yahoo, weather channel, etc) utilizan la misma fuente: National Weather Service API (NWS) de la agencia federal NOAA.

Existen otros sites terceros que simplifican el uso de estas librerias o API’s permitiendonos utilizarlas de manera más sencilla. En este caso utilizaremos como fuente a openweathermap.org.  Esta fuente provee el servicio bajo varios paquetes incluyendo una gratuito que permite 1,200 consultas por minuto cuya data es actualizada cada dos horas. Esto es ideal para sitios web pequeños, medianos o apps corporativas con tráfico limitado.

Bien, ya tenemos el preámbulo, ahora vamos por ello.

Primero, la fuente de datos:

En le mundo de los API, el “endpoint” es un término muy frecuente y es la url de consumo del API. El Open Weather Map API endpoint que utilizaremos es la versión 2.5 y es el siguiente:

http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID={APIKEY}

En este enpoint + param estamos consultando el servicio pasando dos parámetros separados por coma (,): ciudad = London y país = uk (ISO2). El API permite además consultas por ciudad ID,  coordenadas (lat,lng), zipcode, etc. si conocemos el valor o parámetro a consultar.

El servicio provee la información en dos formatos XML y jSON. En esta ocasión utilizaremos jSON ya que anteriormente habíamos hecho un script similar con XML y el esquema es el mismo.

La respuesta del servicio se ve algo como esto en tu navegador si visitas la URL:

{"coord":{"lon":139,"lat":35},
"sys":{"country":"JP","sunrise":1369769524,"sunset":1369821049},
"weather":[{"id":804,"main":"clouds","description":"overcast clouds","icon":"04n"}],
"main":{"temp":289.5,"humidity":89,"pressure":1013,"temp_min":287.04,"temp_max":292.04},
"wind":{"speed":7.31,"deg":187.002},
"rain":{"3h":0},
"clouds":{"all":92},
"dt":1369824698,
"id":1851632,
"name":"Shuzenji",
"cod":200}

Como vemos la respuesta es un jSON estructurado. Esto nos permite determinar rápidamente que datos vamos a utilizar del servicio.

Para quienes no conocen jSON, la estructura es sumamente sencilla: {nodo:valor}. Donde nodo es el nombre del dato y valor es eso mismo. Este últiumo puede ser un string, un array, otra estructura json o simplemente otro objeto.

Consumiendo el servicio con PHP

Nuestro script PHP para consumir el API está dividido en tres partes:

1) obtener el contenido
2) almacenar los valores
3) imprimir el resultado

<?php
/* 1 -> OBTENIENDO EL CONTENIDO */
$json_file = file_get_contents('http://api.openweathermap.org/data/2.5/weather?q=San Juan, PR&APPID={APIKEY}');
$vars = json_decode($json_file);
/* 2 -> ASIGNANDO LOS VALORES */
$cond = $vars->main;
$temp_c = $cond->temp - 273.15;
$temp_f = 1.8 * ($cond->temp - 273.15) + 32;
/* 3 -> IMPRIMIR RESULTADOS */
echo "Temp C: ".$temp_c."\n";
echo "Temp F: ".$temp_f."\n";
?>

Vamos a examinar el script paso por paso para comprender mejor lo que hacemos.

En la primera parte de nuestro script obtenemos el contenido del archivo de respuesta del servicio utilizanod la función nativa de php file_get_contents(), la cual nos permite obtener el contenido (código) del documento, en este caso nuestro “endpoint”. El contenido lo vamos a almacenar en la variable $json_file.

$json_file = file_get_contents('http://api.openweathermap.org/data/2.5/weather?q=San Juan, PR&APPID={APIKEY}');

Como el contenido obtenido es un texto, vamos a convertirlo en objeto json utilizando la función de php json_decode.

$vars = json_decode($json_file);

En la segunda parte de nuestro script extraemos los valores que necesitamos y queremos utilizar asignando estos a variables que podamos procesar. En este ejemplo vamos a utilizar la temperatura para mostrarla en nuestra aplicación o website, por ejemplo.

Según la estructura de la respuesta jSON del servicio nuestros datos están bajo el nodo “main” cuyo valor es un objeto que incluye la temperatura, humedad, presión atmosférica, entre otros valores. Entonces, debemos extraer este objeto o valor al que llamaremos $cond (condición) para procesar cada elemento:

 $cond = $vars->main;

Donde $cond es nuestra variable de asignación, $vars->main es el valor objeto deribado de $vars o objeto y main el nodo que necesitamos.

Como nuestra fuente provee estos datos en Grados Kelvin (la forma mas universal de medir temperaturas) y una de las unidades del Sistema Internacional de Unidades, el cual nos permite llevar a cualquier otro tipo de unidad aplicando la fórmula adecuada.

Entonces, para convertir nuestro valor de grados Kelvin a grados celcius (C) y fahrenheit (F) para fácil lectura por los seres humanos, aplicamos las fórmulas correspodientes a la vez que asignamos los valores a variables separadas para su posterior uso.

$temp_c = $cond->temp - 273.15;
$temp_f = 1.8 * ($cond->temp - 273.15) + 32;

$temp_c equivale a la temperatura en grados celcius, siendo la fórmula C = tempK – 273.15 y para grados fahrenheit $temp_f, la fórmula es F = 1.8 * (tempK – 273.15) + 32.

Ok. Pero, ¿de dónde sale el 273.15, el 1.8 y el 32 de las fórmulas? El cero absoluto en escala C es -273.15 es una constante. Un grado en escala F es 1/180 ó 1.8 ya que es la diferencia entre el punto de congelación (32F) y el punto de ebullición del agua que es 212 grados F. Entonces 32-212 = 180.

Volviendo a lo nuestro, finalmente solo nos resta imprimir nuestros valores:

echo "Temp C: ".$temp_c;
echo "Temp F: ".$temp_f;

Como un extra podemos incluir un ícono representativo de la condición del clima de la misma forma:

$weather = $vars->weather;
$icon = $weather[0]->icon;
echo '<img src="http://openweathermap.org/img/w/'.$icon.'.png">';

Nótese que en la estrutura de la respuesta del servicio, el nodo ” weather” tiene un valor tipo array o [] cuyo primer y único valor es un objeto {} que contiene un nodo llamado “icon”. Este es el referido para presentar el ícono que tembién podemos utilizar desde la fuente gracias a que esta feunte provee un ícono para cada condición según el valor del nodo “icon”.

Consumiendo el servicio con Javascript

Para hacer uso del mismo recurso; pero esta vez con javascript vamos a utilizar la librería jQuery la cual podemos utilizar con solo incluir la siguiente línea a nuestro fichero html entre los tags <head></head> o al final del documento antes del cierre de la etiqueta </body>.

<script src=”//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js”></script>

Entonces tendríamos algo como esto:

<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
</head>
<body>

</body>
</html>

Para consumir cualquier recurso json tanto interno (mismo server) como externo (url) se emplea l;a instrucción $.ajax(). Nuestro código javascript sería:

var vars;
var temp_c;
var temp_f;

$.ajax({
   type: "GET",
   url: "http://api.openweathermap.org/data/2.5/weather?q=San Juan, PR&APPID={APIKEY}",
   dataType: "json",
   success: function (data) {
      vars = data.main;
      temp_c = vars.temp - 273.15;
      temp_f = 1.8 * (vars.temp - 273.15) + 32;
   },
   error: function (jqXHR, textStatus, errorThrown) {
      alert(errorThrown);
   }
});

Como podemos ver la lógica es la misma, sólo cambiamos el lenguaje y un poco la estructura. No voy a detallar este modelo ya que es muy simple y si necesitan más información, pueden referirse a la documentación de jQuery $.ajax(); utilizada. Por lo demás, una vez asignado los valores a las variables vars (objeto), temp_c y temp_f sólo necesitamos donde colcoarlos o presentarlos haciando uso de javascript o jQuery.

Ahora nuestro fichero debería verse de esta forma:

<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
</head>
<body>
<script>
var vars;
var temp_c;
var temp_f;

$.ajax({
type: "GET",
url: "http://api.openweathermap.org/data/2.5/weather?q=San Juan, PR&APPID={APIKEY}",
dataType: "json",
success: function (data) {
vars = data.main;
temp_c = vars.temp - 273.15;
temp_f = 1.8 * (vars.temp - 273.15) + 32;
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
</script>

</body>
</html>

Pueden consultar las variables por medio de la consola de su navegador (F12 en firefox), sólo necesitan nombrar la variable para que esta muestre su valor.

Ahora contamos con un nuevo script del clima mucho más sencillo gracias a jSON.
Y recuerden ” Code is Poetry”.