vendredi 13 septembre 2013

Mon DashBoard intégre les prévisions météos (PHP,Javascript,svg)

Je continu la création de mon dashboard basé sur celui de (http://www.magdiblog.fr/avec un plug-in de météo type google, voici une petite copie d'écran : 

Pour ce faire nous allons mettre en œuvre, les principes suivants :
  • appel d'un web Service avec JSONP, 
  • un peu de JQUERY 
  • et enfin un petit graphique en SVG.
Bien pour comprendre la construction PHP et du pourquoi l'utilisation de DIV et la répartition des fichiers il vous faudra lire http://www.magdiblog.fr/boa-pi-homedashscreen/3-principe-de-base/.

L'architecture du plug-in :

Bon tout est bon let's go to 

openweathermap.org


Ce site va nous fournir des informations provenant des stations météo et les prévisions d'une ville proche de notre habitation. 
Nous allons faire un 1er test des services: 
aller sur le site  : http://api.openweathermap.org/ et entrée votre ville dans mon cas Lille (en fait j'habite une ville à 3KM de lille). Une fois votre ville trouvée, notez l'id de celle-ci, il est dans la barre d'adresse. celui-ci vous sera utile pour l'appel des webservices.
Dans la page nous avons deux parties : 
  • Une partie qui donne la courbe + la T° courante
  • la seconde qui donne la prévision des 5 jours à venir
Naturellement notre 1ere étape est de récupérer leurs données, essayez les liens suivants : 
STOP ne cliquez pas trop vite sur les liens remplacer l'id par celui que vous avez noté à l'étape précédente. 

Le 1er lien vous renvoie les données pour constituer le graphique sous forme d'un XML : 
Chaque entrée time représente 3h de prévision avec les températures et les pluies.
Le second vous renvoie les prévisions dans les 6 prochains jours : 
cette fois-ci chaque entrée time représente un jour de prévision, attention la 1ere entrée donne le jour en cours et me sert pour alimenter les informations actuelles. 
le webservice peut fournir 14 jours de prévision, pour une question de résolution je ne prends que 6 jours, ce paramètre se règle sur le 2eme lien : cnt=<nbr de jour>

Le Code : 


le Code HTML du bloque prévisions : 


Maintenons détaillons l'ensemble des fichiers : 
Comme dans index.php nous n'avons que les DIV vides qui composent la page du DashBoard, il nous faut l'alimenter avec un fragment de code HTML, c'est le rôle de la fonction meteo() dans le fichier inc.php.
function meteo () {
     $meteo  = file_get_contents ("./fragmentMeteo.fg"); // récupérer le contenu de la page
     return $meteo;
}

Le fragment donne le design et chaque emplacement de donnée reçoit un ID HTML, qui sera plus tard alimenté via du code JQUERY 
les bloques de prévision vide dans le fragment : 

Le code HTML : 
 <div id="day4" class="MetoPrev"> <span class="moreDescription"             id="dateD4">Days 4</span> <br>           <span class="moreDescription" id="texteD4">Texte</span> <br>           <span class="moreDescription" id="iconeD4">Icône</span> <br>           <span class="moreDescription" id="tempMinD4">XX°</span><span id="tempMaxD4"
            class="moreDescription">XX°</span> </div> 

La page PHP est appelée par fonction météo() dans le fichier Javascript.js. Cette fonction est automatiquement lancée quand le DOM est chargé.
$(document).ready(function() {
   horloge();
   meteo();
   ping();
    photo();
//   deezer();
});

function meteo ()
{
  $.ajax({
    async : false,
    type: "GET",
    url: "./ajax.php",
    data: "block=meteo",
    success: function(html){
      $("#meteo").html(html);
    }
  });
       

L'appel est fait via Ajax et dès que la requête est un succès on vient placer le contenu dans la div météo :  $("#meteo").html(html);

L'appel JSONP 


Il ne nous reste plus qu'a mettre les données dans la page. Pour cela je fais deux appels JSONP (http://fr.wikipedia.org/wiki/JavaScript_Object_Notation), c'est une technique standard qui permet d'aller chercher des données au format JSON et d'appeler automatiquement une fonction JS. 
Cette technique permet d'appeler en cross domaine (donc depuis une page qui vient de mon domaine, le code javascript appel des données sur un autre domaine). Mais pour éviter toute complication l'appel JSON est fait vers mon serveur web qui ira chercher les données pour me les envoyer. 
Nous avons donc la page json_lille.php qui fait les appels OpenWeatherMap et qui renvoie le résultat : 
       
 if(isset($_REQUEST['block'])){$block = $_REQUEST['block'];}else{$block = 'none';}
  if($block == 'Prev')
     $adresse = "http://api.openweathermap.org/data/2.5/forecast/daily?id=2998324&units=metric&lang=fr&callback=jsoncallback&cnt=6";
  if($block == 'Graph')
     $adresse = "http://api.openweathermap.org/data/2.5/forecast?id=2998324&units=metric&lang=fr&callback=jsoncallback2";
  $page = file_get_contents ($adresse); // récupérer le contenu de la page
  echo $page ; // afficher la page

météo() dans le fichier Javascript.js fait les appels JSONP à l'aide de JQuery :
 $.getJSON("http://thor/gooBox/json_lille.php?block=Prev&jsoncallback=?");
 $.getJSON("http://thor/gooBox/json_lille.php?block=Graph&jsoncallback2=?");
      

On remarque que l'on passe en paramètre le nom de la fonction de retour qui sera automatiquement appelée, en effet les données JSON nous reviennent encapsulée sous ce nom.
jsoncallback2\"({"cod":"200","message":0.0114,"city":{"id":2998324,"name":"Lille","coord":{"l ....
       

Il ne nous reste plus qu'à alimenter les données et créer le graphique

Alimenter les données :


Regardons la fonction jsoncallback dans le fichier javascript.js : 

     function jsoncallback(data){
        //Jour en cours
        $("#MeteoDesc").text(data.list[0].weather[0].description);
        $("#temperature").text(data.list[0].temp.day);
        $("#MainTempMin").text(data.list[0].temp.min);
        $("#MainTempMax").text(data.list[0].temp.max);
        $("#MainTempHumidity").text(data.list[0].humidity);
        $("#MainWindSpeed").text(data.list[0].speed);
        $("#iconeMain").html("");
        //Prevision 
        for(i=1;i<6 data-blogger-escaped-1000="" data-blogger-escaped-amedi="" data-blogger-escaped-ardi="" data-blogger-escaped-array="" data-blogger-escaped-data.list="" data-blogger-escaped-date="" data-blogger-escaped-ddate="" data-blogger-escaped-description="" data-blogger-escaped-dt="" data-blogger-escaped-endredi="" data-blogger-escaped-ercredi="" data-blogger-escaped-eudi="" data-blogger-escaped-getday="" data-blogger-escaped-html="" data-blogger-escaped-i="" data-blogger-escaped-icone="" data-blogger-escaped-imanche="" data-blogger-escaped-img="" data-blogger-escaped-src="http://openweathermap.org/img/w/"+data.list[i].weather[0].icon+".png" data-blogger-escaped-tab_jour="" data-blogger-escaped-temp.day="" data-blogger-escaped-temp.max="" data-blogger-escaped-temp.min="" data-blogger-escaped-temperature="" data-blogger-escaped-text="" data-blogger-escaped-texte="" data-blogger-escaped-time_zone="" data-blogger-escaped-tmpmax="" data-blogger-escaped-tmpmin="" data-blogger-escaped-undi="" data-blogger-escaped-var="" data-blogger-escaped-weather="">");
          
        }
    
      }

L'appel JSONP à créer en mémoire un objet data contenant les données JSON, on peut le voir dans le débugger JS (plus simple que dans le flux JSON) :


La fonction est très simple, elle utilise les sélecteurs JQUERY par ID HTML ( $("#MeteoDesc") ) pour mettre la donnée correspondante de l'objet Data ( data.list[0].weather[0].description).
Comme je suis nul en design j'ai été chercher les icônes chez Openweathermap :
 $(icone).html("<img src='http://openweathermap.org/img/w/"+data.list[i].weather[0].icon+".png'/>");

Création du graphique :

Pour créer le graphique j'utilise une lib Javascript qui crée un SVG : http://www.highcharts.com/.
Pour créer un graphique il suffit d'une DIV possédant un ID, puis de mettre vos données dans un tableau qui contiendra la série à afficher, puis de régler les axes x y 
Voici ce que cela donne dans le code (fichier javascript.js / MeteoProchaineHeure() )

$('#container').highcharts({
                  chart: { ==> le type du graphique à créer, il y en a plein
                      zoomType: 'xy'
                  },
                  title: NaN,
      
                  xAxis: {       ==> les informations sur l'axe x
                      categories: time, ==> la série pour l'axe x
                      type: 'datetime',
              labels: {
                  formatter: function() {
                  return Highcharts.dateFormat('%H:%M', this.value);
                  }                        
                    }
                  },
                  yAxis: [  ==> les informations sur l'axe x
                  {
                      labels: {
                          format: '{value}°C',
                          style: {
                              color: 'blue'
                          }
                      },
                      opposite: true, 
                      title:NaN
                  },{
                      labels: {
                          format: '{value}mm',
                          style: {
                              color: '#4572A7'
                          }
                      },
                      opposite: true,                 
                      title: NaN
                  }],
                  tooltip: {  ==> le tooltip d'un point de la courbe
                    useHTML: true,
                      shared: true,                
                      formatter: function() {
                var s = '<small>'+ Highcharts.dateFormat('%d %b. %H:%M', this.x) +'</small><table>';
                        $.each(this.points, function(i, point) {
                              s += '<tr><td style="color:'+point.series.color+'">'+ point.series.name +': </td>'+
                                '<td style="text-align: right"><b>'+point.y +'</b></td></tr>';
                        });
                        return s+'</table>';
              }
                  },
            legend: { ==> la légende du graphique pour expliquer la courbe
                      layout: 'vertical',
                      align: 'left',
                      x: 410,
                      verticalAlign: 'top',
                      y: 0,
                      floating: true,
                      backgroundColor: '#FFFFFF'
                  }, 
                  series: [
                  {
                      name: 'Precipitation',
              type: 'column',   
              color: '#A0A0A0',      
              yAxis: 1,
                      data: prcp ==> une serie de donnée les précipitations
                  },{
                      name: 'Temperature',
              type: 'spline',
              color: 'blue',
                      data: tmp  ==> une serie de donnée les température
                  }]
              });

Le code est super simple à comprendre, le seul bémol est qu'il faut faire super gaffe au barket L'amont du graphique est là pour formater correctement les données et créer les trois tableaux tmp & wind et time:
 var curdate = new Date( (new Date()).getTime()- 180 * 60 * 1000 );

        var cnt=0;

        var time = new Array();
        var tmp = new Array();
        var wind = new Array();
        var prcp = new Array();

        for(var i = 0; i <  forecast.length; i ++){

        var dt = new Date(forecast[i].dt * 1000);
     
        if( curdate  > dt )     continue;
        if(cnt > 10)          break;
        cnt++;

        tmp.push( Math.round(10*(forecast[i].main.temp))/10  );
        time.push( new Date( forecast[i].dt * 1000 + time_zone) );
        wind.push(forecast[i].speed);

The End 

Voila la création du plug-in, si vous avez des questions n'hésitez pas car comme d'hab, je suis parti du postulat que vous avez déjà un bon niveau de connaissance des différentes techno utilisée.

Les fichiers sont téléchargeables à l’adresse suivante :

Aucun commentaire:

Enregistrer un commentaire