Ajouter un widget Météo à Node-RED Dashboard

Près de 2 ans après le dernier article, j'ai terminé de migrer toutes mes automatisation sur Node-RED.

Depuis, j'utilise de plus en plus largement Node-RED Dashboard en remplacement de Domoticz, qui ne sert quasiment plus qu'a conserver un historique (difficile de migrer un historique de pratiquement 8 ans...).

La souplesse de Node-RED Dashboard fait que je peux rajouter quasiment tout et n'importe quoi et surtout trier mes équipements comme je le souhaite.

Récemment, j'ai voulu rajouter un widget Météo sur la Homepage de mon Dashboard. Ca a été plus compliqué que prévu, alors autant le partager.

Quelle API utiliser ?

Quand j'ai commencé à chercher quel service je pouvais utiliser pour récupérer les données météo, OpenWeatherMap ressortait systématiquement en haut de la liste. Un très bon article du blog Projets DIY détaillait comment utiliser cette API

Pourtant, très vite, je me suis rendu compte que ça ne répondait pas à mon besoin : les prévisions météo sont presque trop complètes, avec des prévisions toutes les 3 heures. Dans mon cas, je ne voulais afficher que des prévisions pour les 5 ou 7 prochains jours, sans avoir besoin d'autant de précisions.

Après quelques essais avec des widgets tout prêt qui ne s'intégraient pas correctement dans Node-RED Dashboard, j'ai fini par utiliser l'API de VisualCrossing : https://www.visualcrossing.com/weather-api.

La version gratuite permet de requêter l'API à hauteur de 1000 records/day. La définition de records est définie ici mais vous pouvez retenir qu'un appel vers l'API de prévisions (forecast) comptera comme un record. Cela veut dire que je peux appeler 1000 fois par jour cet API au maximum. Ca tombe bien, ce sera largement suffisant pour mon utilisation personnelle.

Intégration dans Node-RED

Une fois le compte créé et ma clé API récupérée, je peux construire ma requête via la page Query Builder. Pour ma part j'ai décidé de ne conserver que les prévisions météo.
Tout est paramétrable. Une fois que vous avez décidé ce dont vous avez besoin, récupérez l'URL API générée.

J'ai collé cette URL dans un node http-request, couplé à un node inject qui se répète toutes les 5 minutes. Le retour de cette requête est un objet en JSON. Ensuite, j'utilise un node template (dashboard) pour afficher ces données :

<div class="row">
    <div class="column" ng-repeat="i in [0,1,2,3,4,5,6] track by $index">
        <span>{{msg.payload.days[$index].datetimeEpoch*1000 | date : 'EEE'}}</span>
        <h1>
            <span ng-if="msg.payload.days[$index].icon=='snow'">🌨️</span>
            <span ng-if="msg.payload.days[$index].icon=='snow-showers-day'">🌨️</span>
            <span ng-if="msg.payload.days[$index].icon=='snow-showers-night'">🌨️</span>
            <span ng-if="msg.payload.days[$index].icon=='thunder-rain'">⛈️</span>
            <span ng-if="msg.payload.days[$index].icon=='thunder-showers-day'">⛈️</span>
            <span ng-if="msg.payload.days[$index].icon=='thunder-showers-night'">⛈️</span>
            <span ng-if="msg.payload.days[$index].icon=='rain'">🌧️</span>
            <span ng-if="msg.payload.days[$index].icon=='showers-day'">🌦️</span>
            <span ng-if="msg.payload.days[$index].icon=='showers-night'">🌦️</span>
            <span ng-if="msg.payload.days[$index].icon=='fog'">🌫️</span>
            <span ng-if="msg.payload.days[$index].icon=='wind'">💨</span>
            <span ng-if="msg.payload.days[$index].icon=='cloudy'">☁️</span>
            <span ng-if="msg.payload.days[$index].icon=='partly-cloudy-day'">⛅</span>
            <span ng-if="msg.payload.days[$index].icon=='partly-cloudy-night'">⛅</span>
            <span ng-if="msg.payload.days[$index].icon=='clear-day'">☀️</span>
            <span ng-if="msg.payload.days[$index].icon=='clear-night'">🌙</span>
        </h1>
        <div style="line-height:0.7">
            <font size="2">{{msg.payload.days[$index].tempmax}}°C</font>
            <br />
            <font size="1">{{msg.payload.days[$index].tempmin}}°C</font>
        </div>
    </div>
</div>

Le code ci-dessus utilise de l'AngularJS pour traiter les données. Je n'y connais pas grand chose, mais c'est assez facile à comprendre (et à modifier) :

<div class="column" ng-repeat="i in [0,1,2,3,4,5,6] track by $index">

La directive ng-repeat va me permettre de répéter cette div 7 fois (de 0 à 6). Ca correspond au nombre de jours que je veux afficher.

<span>{{msg.payload.days[$index].datetimeEpoch*1000 | date : 'EEE'}}</span>

Va me permettre d'afficher le jour de la semaine (au format Mon, Tue, etc.) Si je veux afficher la date, je peux remplacer EEE par d/M par exemple.

La partie la plus intéressante se trouve entre les balises <h1></h1> ou pour chaque jour, je vais regarder la description de l'icone associée et la remplacer par une vraie icone.
Après différents essais, et notamment l'utilisation de font dédiée, j'ai préféré utiliser des Emoji. Ca a l'avantage d'être déjà intégré nativement, et le résultat est suffisant dans mon cas.

Les icones renvoyées par l'API de VisualCrossing sont disponibles ici. Il existe 2 sets d'icones, à choisir au moment ou vous faites votre requête API.

Le résultat

Une fois que vous avez compris comment manipulé l'API VisualCrossing et comment afficher les données via le node template, a vous de personnaliser votre widget comme vous le souhaitez. Pour ma part, j'ai également ajouté les heures de lever et de coucher de soleil.

Le résultat est le suivant :