[Store]Script : Météo du jour

Discussion et échanges de scripts pour la box eedomus

Re: [Store]Script : Météo du jour

Messagepar dommarion » 25 Sep 2022 10:24

Bonjour,
La version 2.0 est publiée depuis plusieurs jours et tous les tests sont passés avec succès. La limitation de l’API est relativement non contraignante car le polling à 2 minutes n’excède jamais la limitation de 1000 appels par jour. Grand merci à opa95 pour le temps passé à développer, et tester.
Beaucoup de fonctionnalités ont été rajoutées et regroupent en plus de la météo courante des prévisions, la qualité de l’air, la pluie dans l’heure, et des alertes…
Cela en fait un plugin très complet.
Bon dimanche
Dommarion
OpenWeather|Phases soleil|HeatzyV2|SFR Tv| Concaténateur|HP Yamaha|SomfyV3|Epson|Seuils n étages|Baie 2 vantaux|Deezer|Intégrale|Authorization Digest|TV Philips|SmartThings|fonctions PHP|Tuya Smartlife|CozyTouch2
dommarion
 
Messages : 558
Inscription : 28 Déc 2020

Re: [Store]Script : Météo du jour

Messagepar opa95 » 25 Sep 2022 11:06

Merci dommarion
C'est un plaisir de travailler avec vous : Merguez07 et dommarion.
A bientôt pour d'autres projets.
Bon dimanche
:D
eedomus+, Zibase V1, RFP1000, RFXcom, RadioDriver CPL 630 X2D, capteurs puissance OWL, thermometres Oregon, téléinfo (USB Linky), detecteurs ouverture X2D, pilotage chauffage X2D, Ecoflow River PRO, PAC Shogun (Atlantic-Cozytouch)
opa95
 
Messages : 723
Inscription : 04 Fév 2019
Localisation : Val d'Oise

Re: [Store]Script : Météo du jour

Messagepar Fab_Rice » 25 Sep 2022 21:00

Bonsoir,

Par contre, j'ai voulu faire la mise à jour vers le dernier script et depuis je n'ai plus rien qui remonte :shock:

Image
Dire que l'on ne sait pas est une preuve d'intelligence
Eedomus+, Zigate V2, volets Somfy & Bubbendorf, radiateurs en Tado° & fil pilote, gestion chaudière bois/fioul, gestion borne IRVE, gestion piscine ...
Fab_Rice
 
Messages : 815
Inscription : 27 Déc 2020

Re: [Store]Script : Météo du jour

Messagepar opa95 » 25 Sep 2022 21:14

Bonsoir Fab_Rice.
En fait, il faut lire la documentation.
Il est préférable de réinstaller les dévices.
Sinon, tu peux essayer de corriger les XPATH en remplaçant les // par //@.
Bonne soirée.
eedomus+, Zibase V1, RFP1000, RFXcom, RadioDriver CPL 630 X2D, capteurs puissance OWL, thermometres Oregon, téléinfo (USB Linky), detecteurs ouverture X2D, pilotage chauffage X2D, Ecoflow River PRO, PAC Shogun (Atlantic-Cozytouch)
opa95
 
Messages : 723
Inscription : 04 Fév 2019
Localisation : Val d'Oise

Re: [Store]Script : Météo du jour

Messagepar Fab_Rice » 26 Sep 2022 05:41

Merci Opa95, j'ai opté pour la réinstallation :?
Dire que l'on ne sait pas est une preuve d'intelligence
Eedomus+, Zigate V2, volets Somfy & Bubbendorf, radiateurs en Tado° & fil pilote, gestion chaudière bois/fioul, gestion borne IRVE, gestion piscine ...
Fab_Rice
 
Messages : 815
Inscription : 27 Déc 2020

Re: [Store]Script : Météo du jour

Messagepar opa95 » 26 Sep 2022 07:39

Bonjour Fab_Rice
Fab_Rice a écrit:Merci Opa95, j'ai opté pour la réinstallation :?

Désolé pour la gêne. :(
Au début, j'avais opté pour le maintien de la rétrocompatibilité, et puis nous avons préféré l'abandonner en raison de la quantité d'informations renvoyées et du faible nombre d'utilisateurs de l'ancienne version. : d'où la version 2.0 et non 1.x.
La gestion des options est ainsi plus claire et les données du XPATH plus compactes (économie de 30% sur le XPATH qui peut atteindre quand-même plus de 20ko) et plus lisibles.
Effectivement, il vaut mieux réinstaller plutôt que bricoler et tu peux lire la documentation si tu veux créer des requêtes plus subtiles.
Bonne semaine.
:)
eedomus+, Zibase V1, RFP1000, RFXcom, RadioDriver CPL 630 X2D, capteurs puissance OWL, thermometres Oregon, téléinfo (USB Linky), detecteurs ouverture X2D, pilotage chauffage X2D, Ecoflow River PRO, PAC Shogun (Atlantic-Cozytouch)
opa95
 
Messages : 723
Inscription : 04 Fév 2019
Localisation : Val d'Oise

Re: [Store]Script : Météo du jour

Messagepar Fab_Rice » 26 Sep 2022 11:02

Bonjour Opa95,

C'est déjà bien d'avoir des membres qui bossent pour la communauté, donc la ou les gènes, c'est accessoire.
Merci à vous pour le job :thumbup:
Dire que l'on ne sait pas est une preuve d'intelligence
Eedomus+, Zigate V2, volets Somfy & Bubbendorf, radiateurs en Tado° & fil pilote, gestion chaudière bois/fioul, gestion borne IRVE, gestion piscine ...
Fab_Rice
 
Messages : 815
Inscription : 27 Déc 2020

Re: [Store]Script : Météo du jour

Messagepar jeremydk » 29 Sep 2022 17:25

Bonjour,

J’ai installé le script et j’ai beaucoup de valeur à -9999. Par contre les indicateurs pour la qualité de l’air fonctionnent bien. Une idée du problème ?

Merci, Jeremy.
Eedomus +
jeremydk
 
Messages : 63
Inscription : 07 Oct 2014

Re: [Store]Script : Météo du jour

Messagepar dommarion » 30 Sep 2022 06:07

jeremydk a écrit:j’ai beaucoup de valeur à -9999. Par contre les indicateurs pour la qualité de l’air fonctionnent bien. Une idée du problème ?

Bonjour jeremydk,
les valeurs -9999 indiquent que le PLUGIN est en erreur, plusieurs cas peuvent être à l'origine:
- le lieu est mal renseigné (ce qui devrait être le cas aussi pour la qualité de l'air, mais à vérifier),
- le nombre de demandes à l'API météo dépasse 1000 demandes par jour (vérifier polling >=2),
- autre erreur.
Il existe en mode test la possibilité de voir plus en détail en ajoutant &debug=1 à la fin de l'url.
Normalement cela devrait indiquer le type d'erreur.
Merci
dommarion
OpenWeather|Phases soleil|HeatzyV2|SFR Tv| Concaténateur|HP Yamaha|SomfyV3|Epson|Seuils n étages|Baie 2 vantaux|Deezer|Intégrale|Authorization Digest|TV Philips|SmartThings|fonctions PHP|Tuya Smartlife|CozyTouch2
dommarion
 
Messages : 558
Inscription : 28 Déc 2020

Re: [Store]Script : Météo du jour

Messagepar jeremydk » 30 Sep 2022 09:09

Bonjour dommarion,

Merci pour tes pistes:
- j’ai essayé d’autres villes j’ai le même soucis.
- Je n’ai pas touché au polling et j’ai eu l’erreur dès la mise en place du script.
- j’ai essayé le mode test mais je ne trouve pas le message d’erreur.

J’ai désinstallé et réinstallé le script mais le soucis persiste.

Merci de ton aide, Jeremy.
Eedomus +
jeremydk
 
Messages : 63
Inscription : 07 Oct 2014

Re: [Store]Script : Météo du jour

Messagepar dommarion » 30 Sep 2022 12:40

Ok je regarde cela demain samedi.
OpenWeather|Phases soleil|HeatzyV2|SFR Tv| Concaténateur|HP Yamaha|SomfyV3|Epson|Seuils n étages|Baie 2 vantaux|Deezer|Intégrale|Authorization Digest|TV Philips|SmartThings|fonctions PHP|Tuya Smartlife|CozyTouch2
dommarion
 
Messages : 558
Inscription : 28 Déc 2020

Re: [Store]Script : Météo du jour

Messagepar opa95 » 30 Sep 2022 13:36

Bonjour dammarion
dommarion a écrit:Ok je regarde cela demain samedi.

Moi j'ai rechargé complètement Openweather et je suis tombé sur une très vieille version du script qui ne tournait pas.
Essaie de recharger la dernière version qui a été mise au point.
Pour ceux qui sont pressés, la dernière version devrait ressembler à cela.
Code : Tout sélectionner
<?php

/*************************************************************************************************************************************
 * Script Meteo du Jour basé sur le site OpenWeather.com pour box eedomus
 * Développement par dommarion et opa95 V2.0
 *
 * voir la documentation en ligne pour plus de precisions
 *
 * Ce script permet de récupérer la réponse JSON puis traduire en XML, la météo du jour, la prévision et les polluants de l'air.
 * Les données sont récupérées sur le site OpenWeather à partir des coordonnées GPS (lat,lon) (3 appels api)
 *
 * La traduction des références zip ou nom commune ou coordonnées est faite par l'api : api-adresse.data.gouv.fr pour la France
 * ou l'api api.openweathermap.org/geo/1.0/ sinon.
 * La traduction n'est utilisée que si l'adresse a été changée
 *
 * Un widget est déclaré comme Master et effectue les demandes aux api (device=Master, casse indifférente, 6 premiers caractères); les résultats sont mémorisés
 * Tous les autres widgets ne font que relire les résultats mémorisés par le widget Master (device[0..5] != Master ou absent)
 *
 * Appel Master : http://localhost/script/?exec=openweather.php&commune=[VAR1]&key=[VAR2]&country=[VAR3]&device=Master
 * Appel autres : http://localhost/script/?exec=openweather.php&key=[VAR2][&device=Sensor] ou
 * ou           : http://localhost/script/?exec=openweather.php&key=[VAR2][&device=Sensor]&country=[VAR3] (country est utilisé pour sélectionner les blocs du XML)
 *   [VAR1] : Doit contenir la commune; Formats possibles :
 *            lat,lon (ou lat,lon,country ou lat,lon,state,country) ou zip ou (zip,country) ou commune (ou commune,country ou commune,state,country ou commune,zip,country)
 *   [VAR2] : Doit contenir la clef OpenWeather
 *   [VAR3] : Doit contenir l'état (pour US), le code pays (selon ISO 3166, 2 Lettres) : country ou state,country
 *            Les définitions de country et state de [VAR1] sont prioritaires sur celles de [VAR3]. Si [VAR3] contient un "_" Countery=FR
 *  mode de sortie short (par defaut)
 *  XPATH : infos standards //@nom_champ_valable
 *  exemples //@temperature ou//@hauteur ou //@air_no
 *     cas particuliers : previsions day ou hour
 *       résultats prévisions : jour courant (J0)      //day[@jour='auj']/@temp_nuit ou //day[@num='0']/@temp_nuit
 *                              jour J0+n              //day[@num=n]/@temp_nuit (n entre 0 et 7)
 *                              jour de la semaine     //day[@jour='Lun']/temp_nuit (Dim -> Sam) si identique au jour courant, on obtient le jour de la semaine suivante
 *                              heure courante (H0)    //hour[@heure='now']/@temperature ou //hour[@num=0]/@temperature
 *                              heure H0+n             //hour[@num=n]/@temperature (n entre 0 et 47)
 *                              heure du jour          //hour[@heure=12]/@temperature (0 -> 23) heure du jour ou du lendemain ( *12 -> heure du lendemain ou du surlendemain)
 *  mode de sortie long (variables augmentées de 30%) : idem en ôtant les "@".
 *  si extraction des données, on peut obtenir un seul bloc day ou hour et interroger directement comme pour current : //@temperature (ou //temperature, selon le format).
 * Mode Debug avec en fin d'url &debug=1 (si &reloc = 1 recalcul de la commune), mettre &mem=no pour ne pas utiliser la sauvegarde en mode test
 * Format de sortie : &format=long : Format XML classique, les champs sont appelés directement ex : //temperature  (environ 34ko)
 *                    &format=short : Format XML condensé, les champs sont appelés directement ex : //@temperature (environ 25ko)
 *
 * Selection de blocs de sortie : tout : rien ou _all ; commune : _com ; current : _cou ; precipitation ; _alr : alertes ; _dju : DJU ; _day : days; _hor : hours; _qua : qualite
 *       si _day pas sélectionné : _nJ : jour J+n ; _'auj' : jour 0 ; _dim ... _sam : dimanche à samedi (_sam_dim : week_end)
 *       si _hor pas sélectionné : _nh : heure h+n ; _'now' : heure h ; _h (0 a 23) : heure h suivante ; _*h (*0 a *23) : heure h lendemain ou surlendemain
 *
 * Pour utiliser des widgets correspondants à des lieux différents rajouter $mem=nom_mem dans la chaine de commande des widgets correspondants, par défaut $mem='xml'
 *
 * Evolution des versions (voir documentation):
 *
 * 2021-03-06 (dommarion et opa95): V1.0 -> V1.4  - Version initiale et modifications avec choix nom ou code postal ou "lat,lon" prévision 3h et 24h et lecture API en latitude et longitude, mise en place MasterData et Sensors.
 * 2022-09-16 (opa95 et dommarion): V2.0 - Adaptation à API onecall 1.0 Lecture données par MasterData (2 mins) Utilisation des données par Sensors.
 *                                        - Valeurs actuelles, qualité de l'air, précipitations dans l'heure, prévisions de 1h à 47h et de 1j à 7j, DJU du lendemain
 *                                        - Données normalisées
 *
 *************************************************************************************************************************************/

define ('DEFCOUNTRY' , 'FR');// par défaut fr (France)
define ('DEFLANG' , 'FR');// par défaut fr (France)
define ('DEFDEBUG',0);// par défaut debug = 0 (pas de debug)
define ('DEFDEVICE','Sensor');// par défaut mode Sensor
define ('DEFAFFICHE',39);// Longueur d'affichage de la commune

define ('SEPCOORD',',');//separateur latitude, longitude
define ('SEPMODE','_');//separateur modes
define ('SEPHEURE','*');//indicateur heure initiale >23
define ('SUFFH','h');//suffixe heure (maj ou min)
define ('SUFFJ','j');//suffixe jour (maj ou min)
define ('VOID' , '');// Code erreur champ texte
define ('NBDIGIT' , 4);// nombre de chiffres après la virgule des coordonnées
define ('DJUREF' , 18);// Temperature de reference DJU

define ('ERRCODE',-9999);//Code erreur
define ('ERRTXT','#Erreur');//Code erreur texte
define ('ERRCOORD',199);//Code erreur coordonnées
define ('VALIDHTTP',200);//Code réponse valide
define ('BUFFERNAME','xml');// prefixe de la mémoire
define ('NOMEM','no');// pas de sauvegarde
define ('FORMATXML','short');// long <tag>valeur</tag> short <tags tag="valeur" /> (réduit la taille de 25%)
define ('ELEMXML','_elem');// _beg ou _elem ou _end

define ('ALERTS',0);


//***************** heure locale
function sdk_hloc($elem,$deltaT = 0,$mode = 'hour') {// heure locale de la ville
  if ($elem == ERRCODE) return ERRCODE;
  else    {
    $elem += $deltaT;
    if ($mode == 'hour') return date('G',$elem).':'.date('i',$elem);
    else return date('Y',$elem).'-'.date('m',$elem).'-'.date('d',$elem).' '.date('G',$elem).':'.date('i',$elem);
  }
}// function sdk_hloc

//***************** testNum
function sdk_testNum(&$elem,$is_invalid = false,$err = ERRCODE) {// $elem inchangé ou mis à ERRCODE
  if ( ($is_invalid) || (!is_numeric($elem)) ) {$elem = $err;}
}// function sdk_testNum

//***************** testWeather codes
function sdk_testWeather(&$tableau,$is_invalid = false,$err = ERRCODE) {// $elem inchangé ou mis à ERRCODE
  if ( (!is_numeric($tableau['id'])) || ($is_invalid) ) {
      $tableau['id']          = ERRCODE;
      $tableau['main']        = ERRTXT;
      $tableau['description'] = ERRTXT;
      $tableau['icon']        = ERRTXT;
    }
}// function sdk_testWeather

//***************** alerts XML
function sdk_alertsXML($tableau) {
    $xml  = sdk_formatXML('values','_beg');
    $xml .= sdk_formatXML('sender',$tableau['sender_name']);
    $xml .= sdk_formatXML('evenement',$tableau['event']);
    $xml .= sdk_formatXML('alert_debut',$tableau['start']);
    $xml .= sdk_formatXML('alert_fin',$tableau['end']);
    $xml .= sdk_formatXML('alert_debut_hloc',sdk_hloc($tableau['start'],$delta_h,'date'));
    $xml .= sdk_formatXML('alert_fin_hloc',sdk_hloc($tableau['end'],$delta_h,'date'));
    $xml .= sdk_formatXML('description',$tableau['description']);
    $xml .= sdk_formatXML('values','_end').PHP_EOL;
    $xml .= sdk_formatXML('tags','_beg','long').PHP_EOL; 
    if (array_key_exists('0',$tableau['tags'])){
      foreach($tableau['tags'] as $cle => $elem){
        $xml .= sdk_formatXML('values','_beg');
        $xml .= sdk_formatXML('tag'.$cle,$elem);
        $xml .= sdk_formatXML('values','_end').PHP_EOL;
      }
    }
    else {
      $xml .= sdk_formatXML('values','_beg');
      $xml .= sdk_formatXML('tag0','notags');
      $xml .= sdk_formatXML('values','_end').PHP_EOL;
    }
    $xml .= sdk_formatXML('tags','_end','long').PHP_EOL;
    return $xml;
}// function sdk_alertsXML

//***************** formatXML donnee
function sdk_formatXML($tag,$value,$formatXML = 'default') {// Formattage XML
  global $format;
  if ($formatXML == 'default') $formatXML = $format;
 
  if ($value === 0) $value = '_0';
  if ($value === null) $value = '_?_?';

  switch ($formatXML) {
      case 'long'  : switch ($value) {
                       case '_?_?'  : $xml = '<'.$tag.'></'.$tag.'>';break;
                       case '_0'    : '<'.$tag.'>0</'.$tag.'>';break;
                       case '_beg'  : $xml = '<'.$tag.'>';break;
                       case '_end'  : $xml = '</'.$tag.'>';break;
                       default      : $xml = '<'.$tag.'>'.$value.'</'.$tag.'>';
                     }
                     break;
      default      : switch ($value) {
                       case '_?_?'  : $xml = $tag.'="_" ';break;
                       case '_0'    : $xml = $tag.'="0" ';break;
                       case '_beg'  : $xml = '<'.$tag.' ';break;
                       case '_end'  : $xml = '/>';break;
                       default      : $xml = $tag.'="'.$value.'" ';
                     }
  }
  return $xml;
}// function sdk_formatXML

//***************** formattableauXML donnees
function sdk_formatTableauXML(&$tableau,$formatXML = 'default') {// Formattage XML
  global $format;
  global $delta_h;
  global $jours_fr;

  if ($formatXML == 'default') $formatXML = $format;
      $local_time = $tableau['dt'] + $delta_h;//correction d'heure locale
      $jour_fr = $jours_fr[date('w',$local_time)];
      $xml .= sdk_formatXML('num',$tableau['num']);
      $xml .= sdk_formatXML('nom',$tableau['nom']);
      $xml .= sdk_formatXML('dt',$tableau['dt']);
      $xml .= sdk_formatXML('date_loc_str',date('Y',$local_time) . '-' . date('m',$local_time).'-'.date('d',$local_time));
      $xml .= sdk_formatXML('heure_loc_str',date('G',$local_time) . ':' . date('i',$local_time));
      $xml .= sdk_formatXML('jour_loc_semaine',date('w',$local_time));//dimanche = 0
      $xml .= sdk_formatXML('jour_loc_fr',$jours_fr[date('w',$local_time)]);
      $xml .= sdk_formatXML('sunrise',$tableau['sunrise']);
      $xml .= sdk_formatXML('sunset',$tableau['sunset']);
      $xml .= sdk_formatXML('sunrise_hloc',sdk_hloc($tableau['sunrise'],$delta_h,'date'));
      $xml .= sdk_formatXML('sunset_hloc',sdk_hloc($tableau['sunset'],$delta_h,'date'));
      $xml .= sdk_formatXML('moonrise',$tableau['moonrise']);
      $xml .= sdk_formatXML('moonset',$tableau['moonset']);
      $xml .= sdk_formatXML('moonrise_hloc',sdk_hloc($tableau['moonrise'],$delta_h,'date'));
      $xml .= sdk_formatXML('moonset_hloc',sdk_hloc($tableau['moonset'],$delta_h,'date'));
      $xml .= sdk_formatXML('moon_phase',$tableau['moon_phase']);
      $xml .= sdk_formatXML('night',$tableau['night']);
     
      if (array_key_exists('temperature',$tableau)) {$xml .= sdk_formatXML('temperature',$tableau['temperature']);}
      else {$xml .= sdk_formatXML('temperature',$tableau['temp']);}
      $xml .= sdk_formatXML('temp_morn',$tableau['temp_morn']);
      $xml .= sdk_formatXML('temp_day',$tableau['temp_day']);
      $xml .= sdk_formatXML('temp_eve',$tableau['temp_eve']);
      $xml .= sdk_formatXML('temp_night',$tableau['temp_night']);
      $xml .= sdk_formatXML('temp_min',$tableau['temp_min']);
      $xml .= sdk_formatXML('temp_max',$tableau['temp_max']);
      $xml .= sdk_formatXML('feels_like',$tableau['feels_like']);
      $xml .= sdk_formatXML('temp_like_morn',$tableau['like_morn']);
      $xml .= sdk_formatXML('temp_like_day',$tableau['like_day']);
      $xml .= sdk_formatXML('temp_like_eve',$tableau['like_eve']);
      $xml .= sdk_formatXML('temp_like_night',$tableau['like_night']);
      $xml .= sdk_formatXML('pressure',$tableau['pressure']);
      $xml .= sdk_formatXML('humidity',$tableau['humidity']);
      $xml .= sdk_formatXML('dew_point',$tableau['dew_point']);
      $xml .= sdk_formatXML('wind_speed',$tableau['wind_speed']);
      $xml .= sdk_formatXML('wind_gust',$tableau['wind_gust']);
      $xml .= sdk_formatXML('wind_deg',$tableau['wind_deg']);
      $xml .= sdk_formatXML('clouds',$tableau['clouds']);
      $xml .= sdk_formatXML('uvi',$tableau['uvi']);
      $xml .= sdk_formatXML('visibility',$tableau['visibility']);
      $xml .= sdk_formatXML('pop',$tableau['pop']);
      if (array_key_exists('1h',$tableau['rain'])) $xml .= sdk_formatXML('rain',$tableau['rain']['1h']);
      else $xml .= sdk_formatXML('rain',$tableau['rain']);
      if (array_key_exists('1h',$tableau['snow'])) $xml .= sdk_formatXML('snow',$tableau['snow']['1h']);
      else $xml .= sdk_formatXML('snow',$tableau['snow']);
      if ($tableau['night'] && ($tableau['weather'][0]['id'] == 800)) $tableau['weather'][0]['id'] = 900;//autres champs non remis à jour
      $xml .= sdk_formatXML('weather_id',$tableau['weather'][0]['id']);
      $xml .= sdk_formatXML('weather_main',$tableau['weather'][0]['main']);
      $xml .= sdk_formatXML('weather_desc',$tableau['weather'][0]['description']);
//     $xml .= sdk_formatXML('weather_icon',$tableau['weather'][0]['icon']);
//var_dump($xml);
  return $xml;
}// function sdk_formatTableauXML

//***************** fonction lecture commune
function sdk_getCity(&$city) {// renvoi true si $*city est valide
  global $debug;
  global $key;

  $url_GPS    = 'http://api.openweathermap.org/geo/1.0/';
  $url_GPS_fr = 'http://api-adresse.data.gouv.fr/';

// récuperation des données de la chaîne de commande
  $commune  = getArg('commune');
  $state_   = getArg('state',false,VOID);
  $country_ = getArg('country',false,VOID);
  if ( ($country_ == VOID) && ($state_ != VOID) ) {$country_ = $state_; $state_ = VOID;}
  if (strpos($country_,SEPMODE) !== false) $country_ = DEFCOUNTRY;
// traitement des données state,country de la chaîne
  $tab_country = explode(SEPCOORD,$country_);
  if (count($tab_country) >1) {// $country_ : state,country
    $state_   = $tab_country[0];
    $country_ = $tab_country[1];
  }
  $country_ = strtoupper($country_);//ISO 3166-1 en majuscules (2 lettres)
  if (($country_=="") or (strpos($country_,'.') != 0)) {$country_=DEFCOUNTRY;}
  $state   = utf8_encode($state_);

// traitement de commune
// forme lat,lon ou lat,lon,country ou lat,lon,state,country count 2 ou 3 ou 4 (state inutile)
// forme name ou name,country ou name,state,country name,zip,country
// forme zip ou zip,country ou zip,state,country
  $localization = explode(SEPCOORD,$commune);
  $nbr_element  = count($localization);

  if ($nbr_element == 1) { //commune : name (pas de chiffres) ou zip (au moins un chiffre)
    $test = preg_replace("/[0-9]/","",$localization[0]);//suppression des chiffres
   if ($test == $localization[0]) {
     $type_commune = "name";
     $city['name'] = utf8_encode($localization[0]);}
   else {
     $type_commune = "zip";
     $city['zip']  = strtoupper($localization[0]);
   }
  }
  else {// 2 elements ou plus
   if ( strpos($localization[1],'.') !== false) {
      //second élément nombre réél commune : lat,lon ou lat,lon,country ou lat,lan,state,country
      $type_commune = "coord";
      switch ($nbr_element) {
        case 4 : $city['state']   = utf8_encode($localization[2]);
        case 3 : $city['country'] = strtoupper($localization[$nbr_element-1]);// country en fin de liste
        case 2 : $city['lat'] = sprintf("%.4f",$localization[0]);
              if (abs($city['lat']) > 90) $city['lat'] = ERRCOORD;
              $city['lon'] = sprintf("%.4f",$localization[1]);
              if (abs($city['lon']) > 180) $city['lon'] = ERRCOORD;
              $city['valid'] = ( ($city['lon'] != ERRCOORD) && ($city['lat'] != ERRCOORD));
      }
    }
  else {// commune : 2 : name,country ou name,zip ou zip,country 3 : name,state,country ou name,zip,country
    switch ($nbr_element) {//name ou zip suivi de state et country
      case 3 : $type_commune = "name";//name,state,country ou name,zip,country
               $city['name']     = utf8_encode($localization[0]);
               $city['country']  = strtoupper($localization[2]);
               $test = preg_replace("/[0-9]/","",$localization[1]);//suppression des chiffres
               if ( $test != $localization[1]) {$city['zip']  = strtoupper($localization[1]);}
               else $city['state'] = utf8_encode($localization[1]);
               break;
      case 2 : //name,country ou name,zip ou zip,country
               $test = preg_replace("/[0-9]/","",$localization[0]);//suppression des chiffres
               if ( $test != $localization[0]) {
                  $type_commune = "zip";
                  $city['zip']     = strtoupper($localization[0]);
                  $city['country'] = strtoupper($localization[1]);
                }
                else {//name,country ou name,zip
                  $type_commune    = "name";
                  $city['name']    = utf8_encode($localization[0]);
                  $test = preg_replace("/[0-9]/","",$localization[1]);//suppression des chiffres
                  if ( $test != $localization[1]) {$city['zip']  = strtoupper($localization[1]);}
                  else $city['country'] = strtoupper($localization[1]);
                }
    }
  }
}

//completer $city avec les valeurs de la chaîne si nécessaire
  if ($city['country'] == VOID) {
    $city['country'] = $country_;
    if ($city['country'] == VOID) {$city['country'] = DEFCOUNTRY;}
    if ($city['state'] == VOID) {$city['state'] = $state_;}
  }
  if ( (strlen($state_) > 0) && ($city['state'] != VOID) && ($city['country'] != $country_) ) {$city['state'] = VOID;} 
  if ( ($city['state'] == VOID) && ($city['country'] == $country_) ) {$city['state'] = $state_;} 

//Affichage Debug
  if ($debug) {
    var_dump($localization);
    echo "nbr_elements = ".$nbr_element." Type commune : ".$type_commune.PHP_EOL;
    echo $country_.' '.$state_.PHP_EOL;
    var_dump($city);
  }

// Recherche localisation en latitude et longitude avec API Geocoding ou $url_GPS_fr
  switch ($city['country']) {
    case 'FR' : if ($type_commune == 'coord') {
                  $requete = 'reverse/?lat='.$city['lat'].'&lon='.$city['lon'];
                }
                else {
                  $requete = 'search/?q=';
                  if ($type_commune == 'name') {
                    $requete .= $city['name'];
                    if ($city['zip'] != VOID) $requete .= '&postcode='.$city['zip'];   
                  }
                  else {$requete .= $city['zip'];}
                    }
                   $url_GPS  = $url_GPS_fr.$requete.'&limit=1';
                    $jsonResponse_GPS = httpQuery($url_GPS);
                $jsonResponse_GPS = preg_replace('/\\\\u([\da-fA-F]{4})/', '&#x\1;', $jsonResponse_GPS);
                    $GPS_ = sdk_json_decode($jsonResponse_GPS, true);
                    $GPS  = &$GPS_['features'][0];
                    if (count($GPS) > 0) {
                      $city['name'] = $GPS['properties']['city'];
                      $city['zip']  = $GPS['properties']['postcode'];
                      $city['lat']  = sprintf("%.4f",$GPS['geometry']['coordinates'][1]);
                      $city['lon']  = sprintf("%.4f",$GPS['geometry']['coordinates'][0]);
                      $contexte     = $GPS['properties']['context'];
                      $bof = explode(',',$contexte);
                      $city['state'] = trim($bof[count($bof)-1]);
                   }
//Affichage Debug
                   if ($debug) {
                  echo "url_GPS : ".$url_GPS.PHP_EOL;
                   echo "reponse : ".$jsonResponse_GPS.PHP_EOL;
                }
                if (count($GPS) > 0) {
                  $city['valid'] = ($city['lat'] != ERRCOORD) && ($city['lon'] != ERRCOORD);
//Affichage Debug
                if ($debug) {var_dump($city);}
                break;
                }
                else {$city['country'] = VOID;}// si pas en France, continuer
    default   : switch ($type_commune) {
                     case 'name'  : $requete  = 'direct?q='   . $city['name'];
                                 break;
                     case 'zip'   : $requete  = 'zip?zip='    . $city['zip'];
                    break;
                }
                if (strlen($city['state']) > 0) $requete .= SEPCOORD.$city['state'];
                $requete .= SEPCOORD.$city['country'];
                if ($type_commune == 'coord') {}
                else {
                     $url_GPS  .= $requete.'&limit=1&appid='.$key;
                  $jsonResponse_GPS = httpQuery($url_GPS);
                  $GPS_ = sdk_json_decode($jsonResponse_GPS, true);
                  if ($type_commune == 'name') {$GPS = &$GPS_[0];}
                  else {$GPS = &$GPS_;}
                  if ( ($GPS !== null) && array_key_exists('lat',$GPS) ){
                        $GPS['lat'] = sprintf("%.4f",$GPS['lat']);
                        $GPS['lon'] = sprintf("%.4f",$GPS['lon']);
                        foreach ($GPS as $cle => $value){
                               if (array_key_exists($cle,$city)) $city[$cle] = $value;
                        }
                    }
                }
              $city['valid'] = ($city['lat'] != ERRCOORD) && ($city['lon'] != ERRCOORD);
//Affichage Debug
                 if ($debug) {
                  echo "url_GPS : ".$url_GPS.PHP_EOL;
                   echo "reponse : ".$jsonResponse_GPS.PHP_EOL;
                  var_dump($city);
                 }
  }//switch
  return $city['valid'];
   
};//function sdk_getCity

//***************** programme principal
$jours_fr = array('Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi');
$alerts_on = ALERTS;// traitement des alertes

// Mode debug si &debug=1
$debug   = getArg('debug',false,DEFDEBUG);
$reloc   = getArg('reloc',false,'0');//Forcer la relocalisation
$format  = getArg('format',false,FORMATXML);//long ou short : XML étendu ou compact

// On récupère la clé qui doit être sauvegardée après récupération dans le site OpenWeather

$device = getArg('device',false,DEFDEVICE);
$device = substr(strtolower($device),0,6);
if ($debug) {echo "device: ".$device.PHP_EOL;}

$null_city   = array('zip' => 0, 'name' => VOID, 'lat' => ERRCOORD, 'lon' => ERRCOORD, 'state' => VOID, 'country' => VOID, 'valid' => false);
//saisie mémoire
$buffer_name  = getArg('mem',false,BUFFERNAME);
$buffer_data  = $buffername.'_data';
$buffer_xml   = $buffername.'_xml';

$old_data = loadVariable($buffer_data);
if ($old_data == "") {
  $old_data = array ('city' => $null_city, 'input' => "", 'dju' => ERRCODE, 'days' => array(), 'hours' => array());   
}

$xml = array('commune' => ' ', 'current' => ' ','hor' => array(), 'dju' => '','precipitation' => '', 'day' => array(), 'alertes' => '', 'qualite' =>'');//initialisation

switch ($device) {
  case 'master':
// determination du MasterData
    $now = time();//heure
    $commune = getArg('commune');
    $key     = getArg('key');
    $url = 'http://api.openweathermap.org/data/2.5/';// url du site
    $url_meteo      = $url.'onecall?';
    $url_qualiteair = $url.'air_pollution?';
    $old_xml  = "";
    $data     = array ('city' => $null_city, 'xml' => "", 'input' => $commune.';'.$country.';'.$state, 'dju' => ERRCODE, 'days' => array(), 'hours' => array());

    if ( ($data['input'] === $old_data['input']) && !$reloc ) {
      $data['city'] = $old_data['city'];
      $is_valid_city = true;
//Affichage Debug
      if ($debug) echo 'Reprise ancienne localisation'.PHP_EOL;
    }
    else {
      $is_valid_city = sdk_getCity($data['city']);
      $old_data['dju'] = ERRCODE;
//Affichage Debug
      if ($debug) echo 'Calcul nouvelle localisation'.PHP_EOL;
    }

    $lat = $data['city']['lat'];
    $lon = $data['city']['lon'];
//******************************************** Traitement de base (météo)     
/* format matrice {
array(8) {
  ["lat"]
  ["lon"]
  ["timezone"*]
  ["timezone_offset"]
  ["current"]{array (14)
    ["dt"],["sunrise"],["sunset"],["temp"],["feels_like"],["pressure"],["humidity"],["dew_point"],["uvi"],["clouds"],["visibility"],["wind_speed"],["wind_deg"],["weather"][0]{["id"],["main"*],["description"*],["icon"*]},['rain'][1h],['snow'][1h]
  ["minutely"]{array(61)[0]{["dt"],["precipitation"]}}..[60]{..}}
  ["hourly"]{array(48)[0]{...}..[47]{...}}
      array(14) {["dt"],["temp"],["feels_like"],["pressure"],["humidity"],["dew_point"],["uvi"],["clouds"],["visibility"],["wind_speed"]=>,["wind_deg"],["wind_gust"],["weather"][0]{["id"],["main"*],["description"*],["icon"*]},["pop"],,['rain'][1h],['snow'][1h]
  ["daily"]{array(8)[0]{...}..[7]{...}}
      array(18) {["dt"],["sunrise"],["sunset"],["moonrise"],["moonset"],["moon_phase"],["temp"]{["day"],["min"],["max"],["night"],["eve"],["morn"]},["feels_like"]{["day"],["night"],["eve"],["morn"]},
                 ["pressure"],["humidity"],["dew_point"],["wind_speed"],["wind_deg"],["wind_gust"],["weather"][0]{["id"],["main"*],["description"*],["icon"]*},["clouds"],["pop"],["uvi"],["rain"],["snow"],]}
  ["alerts"]{["sender_name"],["event"],["start"],["end"],["description"],["tags"]...}                 
on rajoute $matrice['city'] = $city;                 
*/
    $url_meteo  .= 'lat=' . $lat . '&lon=' . $lon. '&units=metric&lang='. DEFLANG .'&mode=Json&appid=' . $key;
    $jsonResponse_meteo = httpQuery($url_meteo);
    $matrice = sdk_json_decode($jsonResponse_meteo, true);
    $is_invalid_matrice = count($matrice) < 3;
//    $is_invalid_matrice = true;
    $gmt_offset = date('Z');
    $delta_h = $matrice['timezone_offset'] - date('Z');// ajouter à $gmt pour calcul de l'heure locale

//Affichage Debug
    if ($debug) {
      echo "url_meteo= ".$url_meteo.PHP_EOL;
      echo "reponse : ".$jsonResponse_meteo.PHP_EOL;
//      echo "reponse meteo ".$matrice['cod'].PHP_EOL;
    }

//****** Bloc commune
// Pour l'affichage, le nom ville doit etre inférieur à 39 caracteres, sinon couper a 39
   $nom_ville = $data['city']['name'];
   if ($data['city']['state'] != "") $nom_ville .= ' : '.$data['city']['state'];
   elseif (($data['city']['state'] != DEFCOUNTRY)) {$nom_ville .= ' : '.$data['city']['country'];}
   $nom_ville = substr($nom_ville,0,DEFAFFICHE);
   $ville_GPS = $nom_ville . " (" . round($data['city']['lat'],3) . "°, " . round($data['city']['lon'],3) . "°)";
    sdk_testNum($matrice['timezone_offset'],$is_invalid_matrice);
   if ($matrice['timezone_offset'] == ERRCODE) {$matrice['timezone'] = ERRTXT;}
    $result  = sdk_formatXML('commune','_beg');
    $result .= sdk_formatXML('city_GPS',$ville_GPS);
    $result .= sdk_formatXML('country',$data['city']['country']);;
    $result .= sdk_formatXML('state',$data['city']['state']);
    $result .= sdk_formatXML('zip',$data['city']['zip']);
    $result .= sdk_formatXML('lat',$matrice['lat']);
    $result .= sdk_formatXML('lon',$matrice['lon']);
    $result .= sdk_formatXML('timezone',$matrice['timezone']);
    $result .= sdk_formatXML('timezone_offset',$matrice['timezone_offset']);
    $xml['commune'] = $result. sdk_formatXML('commune','_end').PHP_EOL;
//Affichage Debug
    if ($debug) {echo 'Commune : '.$xml['commune'].PHP_EOL;}
//****** Fin Bloc commune

//****** Bloc alertes
    if ($alerts_on){//Lecture alertes
      $result  = sdk_formatXML('alerts','_beg','long').PHP_EOL;
      if (!array_key_exists('alerts',$matrice)){
        $matrice['alerts'][0]= array('sender_name' => 'Aucun','event' => 'Aucun','start' => ERRCODE, 'end' => ERRCODE, 'description' => VOID, 'tags' => VOID); 
        $count = count($matrice['alerts']);
        for ($num = 0; $num < $count; $num++) {
          $result .= sdk_formatXML('alerts_'.$num,'_beg','long').PHP_EOL;
          $result .= sdk_alertsXML($matrice['alerts'][$num]);
          $result .= sdk_formatXML('alerts_'.$num,'_end','long').PHP_EOL;
        }
      }
      else $result .= sdk_alertsXML('noAlert');
      $xml['alertes'] = $result.sdk_formatXML('alerts','_end','long').PHP_EOL;

//Affichage Debug
      if ($debug) {echo 'Alertes : '. $xml['alerts'].PHP_EOL;}
   }
   else $xml['alertes'] = '';//pas de lectures alertes
//****** Fin Bloc alertes

//****** Bloc daily

    for ($num=0;$num<8;$num++){
      foreach ( array('dt','sunrise','sunset','moonrise','moonset','moon_phase','pressure','visibility','humidity','dew_point','wind_speed','wind_deg','wind_gust','clouds','pop','uvi') as $cle) {
        sdk_testNum($matrice['daily'][$num][$cle],$is_invalid_matrice);
      }
      if ( ($matrice['daily'][$num]['rain'] == ERRCODE) && ($matrice['daily'][$num]['pop'] != ERRCODE) ) $matrice['daily'][$num]['rain'] == 0;
      foreach ( array('day','min','max','night','eve','morn' ) as $cle) {
        sdk_testNum($matrice['daily'][$num]['temp'][$cle],$is_invalid_matrice);
        $matrice['daily'][$num]['temp_'.$cle] = $matrice['daily'][$num]['temp'][$cle];
      }
      $matrice['daily'][$num]['temperature'] = $matrice['daily'][$num]['temp_day'];

      foreach ( array('day','night','eve','morn' ) as $cle) {
        sdk_testNum($matrice['daily'][$num]['feels_like'][$cle],$is_invalid_matrice);
        $matrice['daily'][$num]['like_'.$cle] = $matrice['daily'][$num]['feels_like'][$cle];
      }
      sdk_testWeather($matrice['daily'][$num]['weather'][0],$is_invalid_matrice);
      if ( (!array_key_exists('rain',$matrice['daily'][$num])) && ($matrice['daily'][$num]['dt'] != ERRCODE) ) $matrice['daily'][$num]['rain'] = 0;
      if ( (!array_key_exists('snow',$matrice['daily'][$num])) && ($matrice['daily'][$num]['dt'] != ERRCODE) ) $matrice['daily'][$num]['snow'] = 0;
      if ( (!array_key_exists('wind_speed',$matrice['daily'][$num])) && ($matrice['daily'][$num]['wind_speed'] != ERRCODE) ) $matrice['daily'][$num]['wind_speed'] = $matrice['daily'][$num]['wind_speed']*3.6;//km/h
      if ( (!array_key_exists('wind_gust',$matrice['daily'][$num])) && ($matrice['daily'][$num]['wind_gust'] != ERRCODE) ) $matrice['daily'][$num]['wind_gust'] = $matrice['daily'][$num]['wind_gust']*3.6;//km/h
      $night_ = (($matrice['daily'][$num]['dt'] > $matrice['daily'][$num]['sunrise']) && ($matrice['daily'][$num]['dt'] < $matrice['daily'][$num]['sunset']))? 0:1;
      $local_time = $matrice['daily'][$num]['dt'] + $delta_h;//correction d'heure locale
      $jour_fr = $jours_fr[date('w',$local_time)];
      if ($num == 0) {$jour='auj';}
      else {$jour = $jour_fr;}
      $matrice['daily'][$num]['num']= $num;
      $matrice['daily'][$num]['nom']= strtolower(substr($jour,0,3));
      $matrice['daily'][$num]['night']= $night_;
      $data['days'][strtolower(substr($jour,0,3))] = $num;
      $result  = sdk_formatXML('day','_beg');
      $result .= sdk_formatTableauXML($matrice['daily'][$num]);
      $xml['days'][$num] = $result.sdk_formatXML('day','_end').PHP_EOL; 
    }

//Affichage Debug
    if ($debug) {
      echo 'daily : '.PHP_EOL;
      var_dump($matrice['daily']);
      var_dump($xml['days']);
    }
//****** Fin Bloc daily

//****** Bloc precipitation et minutly
// Pour l'affichage, le nom ville doit etre inférieur à 39 caracteres, sinon couper a 39
   
    for ($num=0;$num<61;$num++){
      sdk_testNum($matrice['minutely'][$num]['dt'],$is_invalid_matrice);
      sdk_testNum($matrice['minutely'][$num]['precipitation'],$is_invalid_matrice);
    }
   $stop_rain  = $now - 60;//-1minute
   $start_rain = $now + 7200;//2h
   $rain  = false;
    $is_raining = false;
   for ($ind = 0,$total_rain=0; $ind <= 60; $ind++) {
      if ($matrice['minutely'][$ind]['precipitation'] == ERRCODE) {
        $total_rain = ERRCODE; break;
      }
      elseif ($matrice['minutely'][$ind]['precipitation'] != 0){
        if (!$is_raining) {$rain = true; $is_raining = true; $start_rain = $matrice['minutely'][$ind]['dt'];}
        else {
          $total_rain += $matrice['minutely'][$ind]['precipitation'];
          if ($matrice['minutely'][$ind]['dt'] < $start_rain) {$start_rain = $matrice['minutely'][$ind]['dt'];}
        }
      }
      else {//precipitation == 0
        if ($is_raining) {$is_raining = false; $stop_rain = $matrice['minutely'][$ind]['dt'];break;}
        else {}
      }
    }
    if ($is_raining) {$stop_rain = $matrice['minutely'][60]['dt'];}// pas d'arret de la pluie
    if (!$rain){$start_rain = $now; $stop_rain = $now + 3600;}

    $result  = sdk_formatXML('precipitation','_beg');
    $result .= sdk_formatXML('averse_hauteur',$total_rain);
    $result .= sdk_formatXML('averse_duree',round(($stop_rain-$start_rain)/60));
    $result .= sdk_formatXML('averse_debut_hloc',sdk_hloc($start_rain,$delta_h));
    $result .= sdk_formatXML('averse_fin_hloc',sdk_hloc($stop_rain,$delta_h));
    $xml['precipitation'] = $result.sdk_formatXML('precipitation','_end').PHP_EOL;
   
//Affichage Debug
    if ($debug) {echo 'precipitation : '.$xml['precipitation'].PHP_EOL;}
//****** Fin Bloc precipitation

//****** Bloc prevision hourly 0 à 47
//calcul DJU
    $dju_Tmin = 100;// Temperature minimale de J-1(18h) à J (18h)
    $min_start = -1;
    $dju_Tmax = -100;// Temperature maximale de J(6h) à J+1 (6h)
    $max_start = -1;
    $day_parts = array(0 =>'night',1 =>'morn', 2 =>'day',3 =>'eve');
    $temp_ = array ('morn'=>ERRCODE,'day'=>ERRCODE,'eve'=>ERRCODE,'night'=>ERRCODE);
    $like_ = array ('morn'=>ERRCODE,'day'=>ERRCODE,'eve'=>ERRCODE,'night'=>ERRCODE);

    for ($num=0;$num<48;$num++){
      $local_time = $matrice['hourly'][$num]['dt'] + $delta_h;//correction d'heure locale
      $jour_loc_semaine = date('w',$local_time);//dimanche = 0
      $delta_day        = $jour_loc_semaine - $jour_loc_sem;
      $heure = date('G',$local_time);
      if ($num == 0) {$numh = 'now';}
      elseif ($num <= 24) {$numh = $heure;} 
      else {$numh = SEPHEURE.$heure;}
      $night_ = ( (($matrice['hourly'][$num]['dt'] > $matrice['daily'][0]['sunrise']) && ($matrice['hourly'][$num]['dt'] < $matrice['daily'][0]['sunset'])) || (($matrice['hourly'][$num]['dt'] > $matrice['daily'][1]['sunrise']) && ($matrice['hourly'][$num]['dt'] < $matrice['daily'][1]['sunset'])) || (($matrice['hourly'][$num]['dt'] > $matrice['daily'][2]['sunrise']) && ($matrice['hourly'][$num]['dt'] < $matrice['daily'][2]['sunset'])))? 0:1;
      $day_part_num =    (floor( (date('G',$local_time) + 1)/6))%4;
      $day_part = $day_parts[$day_part_num];
      $matrice['hourly'][$num]['num']   = $num;
      $matrice['hourly'][$num]['nom']   = strtolower(substr($numh,0,3));
      $data['hours'][strtolower(substr($numh,0,3))] = $num;

      $matrice['hourly'][$num]['night'] = $night_;
      if ($temp_[$day_part] == ERRCODE) {
        $temp_[$day_part] = $matrice['hourly'][$num]['temp'];
        $like_[$day_part] = $matrice['hourly'][$num]['feels_like'];
      }
      $matrice['hourly'][$num]['sunrise']    = $matrice['daily'][$delta_day]['sunrise'];
      $matrice['hourly'][$num]['sunrise']    = $matrice['daily'][$delta_day]['sunrise'];
      $matrice['hourly'][$num]['sunset']     = $matrice['daily'][$delta_day]['sunset'];
      $matrice['hourly'][$num]['moonrise']   = $matrice['daily'][$delta_day]['moonrise'];
      $matrice['hourly'][$num]['moonset']    = $matrice['daily'][$delta_day]['moonset'];
      $matrice['hourly'][$num]['moon_phase'] = $matrice['daily'][$delta_day]['moon_phase'];
      foreach ( array('dt','temp','feels_like','pressure','humidity','dew_point','uvi','clouds','visibility','wind_speed','wind_deg','wind_gust','pop') as $cle) {
        sdk_testNum($matrice['hourly'][$num][$cle],$is_invalid_matrice);
      }
      sdk_testWeather($matrice['hourly'][$num]['weather'][0],$is_invalid_matrice);
      if ( !(array_key_exists('rain',$matrice['hourly'][$num])) && ($matrice['hourly'][$num]['dt'] != ERRCODE) ) $matrice['hourly'][$num]['rain']['1h'] = 0;
      if ( !(array_key_exists('snow',$matrice['hourly'][$num])) && ($matrice['hourly'][$num]['dt'] != ERRCODE) ) $matrice['hourly'][$num]['snow']['1h'] = 0;

      if ( ($min_start < 0)  && ($numh == 18) && ($num < 24) ) {$min_start = $num; $min_stop = $min_start + 18;}
      if ( ($min_start >= 0) && ($num < $min_stop) && ($matrice['hourly'][$num]['temp'] != ERRCODE) ) {$dju_Tmin = min($dju_Tmin,$matrice['hourly'][$num]['temp']);}
      if ( ($min_start >= 0) && ($max_start < 0) && ($numh == 6) && ($num >= 12) ) {$max_start = $num; $max_stop = $max_start + 18;}
      if ( ($max_start >= 0) && ($num < $max_stop) && ($matrice['hourly'][$num]['temp'] != ERRCODE)  ) {$dju_Tmax = max($dju_Tmax,$matrice['hourly'][$num]['temp']);}
    }

    for ($num=0;$num<48;$num++){
      $numh = $matrice['hourly'][$num]['nom'];
      $numh = str_replace(SEPHEURE,'',$numh);
      if ($numh == 'now') $numh = $heure_;
      $day_part_num =    (floor( (date('G',$numh) + 1)/6))%4;
      $day_part     = $day_parts[$day_part_num];
      foreach ($temp_ as $cle => $value) {
        if ($value != ERRCODE) {
          $matrice['hourly'][$num]['temp_'.$cle] = $value;
          $matrice['hourly'][$num]['like_'.$cle] = $like_[$cle];
        }
      }
      $result  = sdk_formatXML('hour','_beg');
      $result .= sdk_formatTableauXML($matrice['hourly'][$num]);
      $xml['hours'][$num] = $result.sdk_formatXML('hour','_end').PHP_EOL; 
    }

    if ($dju_Tmin > $dju_Tmax){$dju = $old_dju;}//invalide
    else {
      $dju_Tmin = min($dju_Tmin,DJUREF);
      $dju_Tmax = min($dju_Tmax,DJUREF);
      $dju = DJUREF - ($dju_Tmin + $dju_Tmax)/2;
    }
    $result  = sdk_formatXML('dju','_beg');
    $result .= sdk_formatXML('dju_prev',$dju);
    $result .= sdk_formatXML('dju_tmin',$dju_Tmin);
    $result .= sdk_formatXML('dju_tmax',$dju_Tmax);
    $xml['dju'] = $result.sdk_formatXML('dju','_end').PHP_EOL;

     $xml_        .= sdk_formatXML('hourly','_end','long').PHP_EOL;
     
//Affichage Debug
    if ($debug) {
      echo 'hourly : '.PHP_EOL;
      var_dump($matrice['hourly']);
      var_dump($xml['hor']);
      echo 'dju '.$xml['dju'].PHP_EOL;
    }
//****** Fin Bloc hourly et dju

//****** Bloc current
    foreach ( array('dt','sunrise','sunset','temp','feels_like','pressure','humidity','dew_point','uvi','clouds','visibility','wind_speed','wind_deg') as $cle) {
      sdk_testNum($matrice['current'][$cle],$is_invalid_matrice);
    }
    if ( (!array_key_exists('rain',$matrice['current'])) && ($matrice['current']['dt'] != ERRCODE) ) $matrice['current']['rain']['1h'] = 0;
    if ( (!array_key_exists('snow',$matrice['current'])) && ($matrice['current']['dt'] != ERRCODE) ) $matrice['current']['snow']['1h'] = 0;
    sdk_testWeather($matrice['current']['weather'][0],$is_invalid_matrice);
    $matrice['current']['num'] = 0;
    $matrice['current']['nom'] = 'now';
    $matrice['current']['moonrise']   = $matrice['daily'][0]['moonrise'];
    $matrice['current']['moonset']    = $matrice['daily'][0]['moonset'];
    $matrice['current']['moon_phase'] = $matrice['daily'][0]['moon_phase'];
    $night_ = (($matrice['current']['dt'] > $matrice['current']['sunrise']) && ($matrice['current']['dt'] < $matrice['current']['sunset']))? 0:1;
    $matrice['current']['night'] = $night_;
    foreach (array('morn','day','eve','night','min','max') as $cle){
      $matrice['current']['temp_'.$cle] = $matrice['daily'][0]['temp'][$cle];
    }
    foreach (array('morn','day','eve','night') as $cle){
      $matrice['current']['like_'.$cle] = $matrice['daily'][0]['feels_like'][$cle];
    }
    foreach (array('wind_gust','pop','rain','snow') as $cle){   
      $matrice['current'][$cle] = $matrice['hourly'][0][$cle];
    }

    $result  = sdk_formatXML('current','_beg');
    $result .= sdk_formatTableauXML($matrice['current']);
    $xml['current'] = $result.sdk_formatXML('current','_end').PHP_EOL; 
//Affichage Debug
    if ($debug) {
        echo 'current : '.$xml.PHP_EOL;
        var_dump($matrice['current']);
    }
//****** Fin Bloc current

//******************************************** Traitement qualité air     
/* format content array(5) {     
["coord"]{["lon"],["lat"]}
["list"][0]["main"]["aqi"]
           ["components"]{["co"],["no"],["no2"],["o3"],["so2"],["pm2_5"],["pm10"],["nh3"]},
           ["dt"]}     
*/
// Envoi de la requete pour qualité de l'air
// http://api.openweathermap.org/data/2.5/air_pollution?lat={lat}&lon={lon}&appid={API key}
    $url_qualiteair .= 'lat=' . $data['city']['lat'] . '&lon=' . $data['city']['lon'] . '&appid=' . $key;
    $jsonResponse_qualite = httpQuery($url_qualiteair);
    $content = sdk_json_decode($jsonResponse_qualite, true);
    $is_invalid_content = ( ($content['cod'] !== null) && (!is_numeric($content['main']['aqi'])) );
//    $is_invalid_content = true;

//Affichage Debug
    if ($debug) {
      echo "url_qualiteair: ".$url_qualiteair.PHP_EOL;
      echo "reponse : ".$jsonResponse_qualite.PHP_EOL;
      var_dump($content);
    }

// Vérification des variables récupérées si pas numérique mettre la variable à ERRCODE (-9999)
    $content['coord']['lat'] = $data['city']['lat'];
    $content['coord']['lon'] = $data['city']['lon'];
    sdk_testNum($content['list'][0]['dt'],$is_invalid_content);
    sdk_testNum($content['list'][0]['main']['aqi'],$is_invalid_content);
    foreach ( array('no','no2','o3','so2','co','pm2_5','pm10','nh3') as $cle) {
      sdk_testNum($content['list'][0]['components'][$cle],$is_invalid_content);
    }
    sdk_testNum($content['list'][0]['dt'],$is_invalid_content);

// Generation du XML pour les qualités
    $result  = sdk_formatXML('donnees_qualite','_beg');
    $result .= sdk_formatXML('dt',$content['list'][0]['dt']);
    $result .= sdk_formatXML('air_aqi',$content['list'][0]['main']['aqi']);
    $result .= sdk_formatXML('air_no',$content['list'][0]['components']['no']);
    $result .= sdk_formatXML('air_no2',$content['list'][0]['components']['no2']);
    $result .= sdk_formatXML('air_o3',$content['list'][0]['components']['o3']);
    $result .= sdk_formatXML('air_so2',$content['list'][0]['components']['so2']);
    $result .= sdk_formatXML('air_co',$content['list'][0]['components']['co']);
    $result .= sdk_formatXML('air_pm2_5',$content['list'][0]['components']['pm2_5']);
    $result .= sdk_formatXML('air_pm10',$content['list'][0]['components']['pm10']);
    $result .= sdk_formatXML('air_nh3',$content['list'][0]['components']['nh3']);
    $xml['qualite'] = $result.sdk_formatXML('donnees_qualite>','_end').PHP_EOL;


// Generation du XML
    sdk_header('text/xml');
    echo '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
    echo sdk_formatXML('donnees_meteo','_beg','long').PHP_EOL;
    echo $xml['commune'];
    echo $xml['current'];
    echo $xml['precipitation'];
    echo $xml['dju'];
    echo sdk_formatXML('daily','_beg','long').PHP_EOL;
    foreach ($xml['days'] as $elem) {echo $elem;}
    echo sdk_formatXML('daily','_end','long').PHP_EOL;
    echo sdk_formatXML('hourly','_beg','long').PHP_EOL;
    foreach ($xml['hours'] as $elem) {echo $elem;}
    echo sdk_formatXML('hourly','_end','long').PHP_EOL;   
    echo $xml['qualite'];
    echo sdk_formatXML('donnees_meteo','_end','long').PHP_EOL;
   
    if ($buffer_xml != NOMEM.'xml') {
        saveVariable($buffer_data,$data);
        saveVariable($buffer_xml,$xml);
    }
    break;//fin MasterData
  default:
// modes : _all, _com, _cur, _pre, _alr, _dju, _day, _hor, _qua, _j0 .. _j7, _dim .. _sam,
    $mode  = array ('com' => 1,'cur' => 1,'pre' => 1,'alr' => 1,'dju' => 1,'qua' => 1,'day' => 1,'hor' => 1);
    $days  = array ();
    for ($num =0;$num<8;$num++) {$days[$num] = 1;}
    $hours = array();
    for ($num =0;$num<48;$num++) {$hours[$num] = 1;}
    $state_ = getArg('state',false,VOID);//retrocompatibilite
    $mode_  = getArg('country',false,VOID);
    if ( ($mode_ == VOID) && ($state_ != VOID) ) {$mode_ = $state_;}//retrocompatibilite
    $_mode_ = getArg('mode',false,VOID);
    if ($_mode_ !== VOID) $mode_ = $_mode_;
    $periph_id = getArg('periph_id',false);
    $values = getValue($periph_id);
    $choix_ = $values['value'];
    $choix = array (0=>'auj','1J','2J','3J','4J','5J','6J','7J',
                    100=> 'dim','lun','mar','mer','jeu','ven','sam',
                    200=> '0H','1H','2H','3H','4H','5H','6H','7H','8H','9H','10H','11H',
                         '12H','13H','14H','15H','16H','17H','18H','19H','20H','21H','22H','23H','24H',
                    300=> '0','1','2','3','4','4','6','7','8','9','10','11','12',
                          '13','14','15','16','17','18','19','20','21','22','23');
    if ($choix[$choix_]) $mode_ = SEPMODE.$choix[$choix_];
    $mode_ = strtolower($mode_);
    $modeXML = $mode_;
    if (strpos($mode_,SEPMODE) !== false) {
      foreach ($mode as $cle => $elem){//modes complets
        if (strpos($mode_,SEPMODE.$cle) === false) {$mode[$cle] = 0;}
        else $mode_ = str_replace(SEPMODE.$cle,'',$mode_);
      }
      if (!$mode['day']){
        foreach ($days as $cle => $elem){
          if (strpos($mode_,SEPMODE.$cle.SUFFJ) === false) {$days[$cle] = 0;}
          else {
            $mode_ = str_replace(SEPMODE.$cle.SUFFJ,'',$mode_);
            $mode['day'] = 1;
          }
        }
      }
      if (!$mode['hor']){
        foreach ($hours as $cle => $elem){
          if (strpos($mode_,SEPMODE.$cle.SUFFH) === false) {$hours[$cle] = 0;}
          else {
            $mode_ = str_replace(SEPMODE.$cle.SUFFH,'',$mode_);
            $mode['hor'] = 1;
          }
        }
      }
      if (strpos($mode_,SEPMODE) !== false) {
        $mode_ = substr($mode_,1);
        $mode__ = explode(SEPMODE,$mode_);
        foreach ($mode__ as $cle) {
          if (array_key_exists($cle,$old_data['days'])) {
            $elem = $old_data['days'][$cle];
            $days[$elem] = 1;
            $mode['day'] = 1;
          }
          if (array_key_exists($cle,$old_data['hours'])) {
            $elem = $old_data['hours'][$cle];
            $hours[$elem] = 1;
            $mode['hor'] = 1;
          }
        }
      }
    }
  $xml = loadVariable($buffer_xml);
// debug
  if ($debug) {
    echo 'mode - ';var_dump($mode);
    echo 'days - ';var_dump($days);
    echo 'old_data[days] - ';var_dump($old_data['days']);
    echo 'hours - ';var_dump($hours);
    echo 'old_data[hours] - ';var_dump($old_data['hours']);
    echo 'xml[days] - ';var_dump($xml['days']);
    echo 'xml[hours] - ';var_dump($xml['hours']);
  }   
    sdk_header('text/xml');
    echo '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
    echo sdk_formatXML('donnees_meteo','_beg','long').PHP_EOL;
    echo '<modes mode="'.$modeXML.'" />'.PHP_EOL;
    if ($mode['com']) echo $xml['commune'];
    if ($mode['cur']) echo $xml['current'];
    if ($mode['pre']) echo $xml['precipitation'];
    if ($mode['alr']) echo $xml['alertes'];
    if ($mode['dju']) echo $xml['dju'];
    if ($mode['day']) {
      echo sdk_formatXML('daily','_beg','long').PHP_EOL;
      foreach ($days as $cle => $elem) {
//        echo $cle.' : '.$cle.SUFFJ.' : '.$elem.' = '.$days[$cle].' ; ';
        if ($days[$cle]) {echo $xml['days'][$cle];}
      }
      echo sdk_formatXML('daily','_end','long').PHP_EOL;
    }
    if ($mode['hor']) {
      echo sdk_formatXML('hourly','_beg','long').PHP_EOL;
      foreach ($hours as $cle => $elem) {
//        echo $cle.' = '.$elem.' : '.PHP_EOL;
        if ($hours[$cle]) {echo $xml['hours'][$cle];}
//        if ($elem) {echo $xml[str_replace(SUFFH,'',$cle)];}
      }
      echo sdk_formatXML('hourly','_end','long').PHP_EOL;
    }
    if ($mode['qua']) echo $xml['qualite'];
    echo sdk_formatXML('donnees_meteo','_end','long').PHP_EOL;
    break;
  }
?>

Testez et dites-moi s'il reste des problèmes :)
eedomus+, Zibase V1, RFP1000, RFXcom, RadioDriver CPL 630 X2D, capteurs puissance OWL, thermometres Oregon, téléinfo (USB Linky), detecteurs ouverture X2D, pilotage chauffage X2D, Ecoflow River PRO, PAC Shogun (Atlantic-Cozytouch)
opa95
 
Messages : 723
Inscription : 04 Fév 2019
Localisation : Val d'Oise

Re: [Store]Script : Météo du jour

Messagepar dommarion » 30 Sep 2022 14:30

Bonjour opa95, jeremydk, Fab_Rice,
Je viens de vérifier sur le store eedomus, la version 2.0 a un script qui fait 916 lignes, c'est bien la version qui a été téléchargée le 16 septembre et que Fab_Rice a téléchargé et installé le 26 septembre (cf son message).
Peut-être y a t'il eu un problème sur le serveur eedomus ?
Mais ce jour vendredi 30 septembre à 15h25, le zip du plugin est bien en version 2.0 et complet. Le zip openweather fait 713kb, le script 48kb, le json 37kb, la doc 23kb et le répertoire img contient 47 fichier pour un total de 685kb.
J'ai réinstallé le tout en supprimant et recréant l'ensemble et tout fonctionne correctement.

Fab_Rice peux-tu confirmer que tout se passe bien pour toi ?

jeremydk et opa95 pouvez-vous essayer de reprendre la version du store eedomus ?

Merci pour votre retour.
dommarion
Dernière édition par dommarion le 30 Sep 2022 16:36, édité 3 fois.
OpenWeather|Phases soleil|HeatzyV2|SFR Tv| Concaténateur|HP Yamaha|SomfyV3|Epson|Seuils n étages|Baie 2 vantaux|Deezer|Intégrale|Authorization Digest|TV Philips|SmartThings|fonctions PHP|Tuya Smartlife|CozyTouch2
dommarion
 
Messages : 558
Inscription : 28 Déc 2020

Re: [Store]Script : Météo du jour

Messagepar ARTNOW » 30 Sep 2022 14:42

Salut Dommarion j'ai tester depuis 3 jours pour moi cela marche bien , bravo pour le job ;)
EEDOMUS + -RFP1000-IPX 800 V4-IPX 800 V5 - FIBARO -GOOGLE(Home-Nest & mini)
ARDUINO-RASPBERRY PRUSA MK3S
Domotisation de :1xPiscine/9xClimatisations réversibles/2xVolets somfy/1xAlarme/1xChauffe-Eau thermodynamique/3xPortes Garage et 1xportail
ARTNOW
 
Messages : 1280
Inscription : 22 Avr 2018
Localisation : LOIRE ATLANTIQUE

Re: [Store]Script : Météo du jour

Messagepar opa95 » 30 Sep 2022 15:53

Bonjour à tous
J'ai rechargé l'ensemble et maintenant c'est bon.
Bon week-end
:)
eedomus+, Zibase V1, RFP1000, RFXcom, RadioDriver CPL 630 X2D, capteurs puissance OWL, thermometres Oregon, téléinfo (USB Linky), detecteurs ouverture X2D, pilotage chauffage X2D, Ecoflow River PRO, PAC Shogun (Atlantic-Cozytouch)
opa95
 
Messages : 723
Inscription : 04 Fév 2019
Localisation : Val d'Oise

Re: [Store]Script : Météo du jour

Messagepar Fab_Rice » 30 Sep 2022 16:17

dommarion a écrit:Bonjour opa95, jeremydk, Fab_Rice,
Je viens de vérifier sur le store eedomus, la version 2.0 a un script qui fait 916 lignes, c'est bien la version qui a été téléchargée le 16 setembre et que Fab_Rice a téléchargé et installé le 26 septembre (cf son message).
Peut-être y a t'il eu un problème sur le serveur?
Mais ce jour vendredi 30 septembre à 15h25, le zip du plugin est bien en version 2.0 et complet. Le zip openweather fait 713kb, le script 48kb, le json 37kb, la doc 23kb et le répertoire img contient 47 fichier pour un total de 685kb.
J'ai réinstallé le tout en supprimant et recréant l'ensemble et tout fonctionne correctement.

Fab_Rice peux-tu confirmer que tout se passe bien pour toi ?

jeremydk et opa95 pouvez-vous essayer de reprendre la version du store eedomus ?

Merci pour votre retour.
dommarion


Bonjour à vous,

Je confirme, cela fonctionne chez moi correctement avec une version chargée le 26/09 :thumbup:
Dire que l'on ne sait pas est une preuve d'intelligence
Eedomus+, Zigate V2, volets Somfy & Bubbendorf, radiateurs en Tado° & fil pilote, gestion chaudière bois/fioul, gestion borne IRVE, gestion piscine ...
Fab_Rice
 
Messages : 815
Inscription : 27 Déc 2020

Re: [Store]Script : Météo du jour

Messagepar jeremydk » 30 Sep 2022 16:51

Bonjour,

Désinstallation et réinstallation fait mais le problème persiste. Je ne sais pas quoi faire de plus.
Eedomus +
jeremydk
 
Messages : 63
Inscription : 07 Oct 2014

Re: [Store]Script : Météo du jour

Messagepar Fab_Rice » 30 Sep 2022 17:09

jeremydk a écrit:Bonjour,

Désinstallation et réinstallation fait mais le problème persiste. Je ne sais pas quoi faire de plus.


Alors deux choses dont une déjà évoquée :

- La ville est-elle bien renseignée (valeur GPS correctes) ?
- Il y a un temps de prise en compte pour les remontées d'info depuis OpenWeather à la 1ère connexion eedomus il me semble, donc un délai de 12 à 24h ne me surprendrait pas.

N.B: je viens de consulter mes historiques et j'ai eu aussi un -9999 le 27/09, mais ponctuel et c'est revenu, probablement plus un appel de données qui n'est pas passé (bug serveur ou connexion).
Dire que l'on ne sait pas est une preuve d'intelligence
Eedomus+, Zigate V2, volets Somfy & Bubbendorf, radiateurs en Tado° & fil pilote, gestion chaudière bois/fioul, gestion borne IRVE, gestion piscine ...
Fab_Rice
 
Messages : 815
Inscription : 27 Déc 2020

Re: [Store]Script : Météo du jour

Messagepar dommarion » 30 Sep 2022 17:23

jeremydk a écrit:Désinstallation et réinstallation fait mais le problème persiste.

Il est assez probable que ta clef OpenWeather ne soit pas "compatible" avec l'API de météo. Elle fonctionne avec la qualité de l'air mais peut être pas avec l'API onecall 1.0
Essaie de créer une nouvelle clef...
Sinon le mieux est de lancer en mode test avec &debug=1
Dans la fenêtre XML tu fais un copie/coller dans notepad, et tu recherches "url_meteo=" tu devrais avoir l'url météo appelée, et ensuite dessous tu as "reponse :" et "reponse meteo " avec un code.
Tu as de même "url_qualiteair: " et "reponse : ".
Ce sont les appels aux API respectives et les réponses. Du coup tu devrais voir ce qui ne va pas.
Bon courage,
dommarion
OpenWeather|Phases soleil|HeatzyV2|SFR Tv| Concaténateur|HP Yamaha|SomfyV3|Epson|Seuils n étages|Baie 2 vantaux|Deezer|Intégrale|Authorization Digest|TV Philips|SmartThings|fonctions PHP|Tuya Smartlife|CozyTouch2
dommarion
 
Messages : 558
Inscription : 28 Déc 2020

Re: [Store]Script : Météo du jour

Messagepar jeremydk » 30 Sep 2022 18:15

J’ai testé erreur 401 invalid API. Je vais attendre jusque demain.
Eedomus +
jeremydk
 
Messages : 63
Inscription : 07 Oct 2014

PrécédentSuivant

Retour vers Scripts & Périphériques du store

Qui est en ligne ?

Utilisateurs parcourant ce forum : Aucun utilisateur inscrit et 6 invité(s)