Analyse de la donnée. Partie 3 : Récupération et mise en forme de données historisées depuis Jeedom

 

Cet article est le troisième concernant l’analyse de donnée. Les précédents articles sont disponibles ici :

  • Partie 1 : installation des outils
  • Partie 2 : Tests basiques de l’API Jeedom

Cet article a été écrit dans un notebook jupyter avant d’être transféré sur ce blog. Les zones nommées In [ ] correspondent donc au code Python qui a été exécuté. La sortie de ce code apparaît juste en dessous.

Nous allons dans cet article effectuer une première récupération de donnée historisée de plusieurs capteurs. Puis nous allons stocker cette donnée correctement dans une time series. Il est important de traiter et stocker correctement ces valeurs si on veut en faire bon usage par la suite.

Paramètres généraux d’accès à l’API Jeedom

Il s’agit des paramètres nécessaires pour accéder à l’API Jeedom : l’URL et la clé API. Cette dernière peut être récupérée dans l’interface de contrôle de Jeedom. Je vais me permettre pour cette partie de cacher mes données personnelles !

In [2]:
adresse_API = 'http://adresse.ip.jeedom/core/api/jeeApi.php'                                                     
Api_key = 'Clé API'

Récupération de l’historique d’un périphérique

On en arrive au coeur du besoin : récupérer l’historique d’un périphérique qu’on pourra traiter avec différents algorithmes de traitement de données par la suite.

Chargement des données

In [3]:
import urllib.request                                                                   
import json 

def Jeedom_getHistory(id, start, stop):                                                          
  parameters = {                                                                
          "jsonrpc" : "2.0",                                                    
          "method" : "cmd::getHistory",                                                                                                           
          "params": {                                                           
              "id" : id,
              "apikey": Api_key,
              "startTime": start, 
              "endTime": stop
              }                                                                 
          }                                                                                              
  params = json.dumps(parameters).encode('utf8')                                                                                                                    
  req = urllib.request.Request(adresse_API, data=params, headers={'Content-Type': 'application/json'})        
                                                                                
  response = urllib.request.urlopen(req)                                               
  return response.read().decode('utf8')                                                         
                                                                                
                                                                                
hist_temp=Jeedom_getHistory(1801,"2020-02-08 00:00:00","2020-02-08 23:59:59")
# Je n'imprime que le début parce que ça peut être très long
print(hist_temp[:255])
{"jsonrpc":"2.0","id":99999,"result":[{"cmd_id":"1801","value":"20.500000","datetime":"2020-02-08 00:00:00"},{"cmd_id":"1801","value":"20.500000","datetime":"2020-02-08 01:00:00"},{"cmd_id":"1801","value":"20.500000","datetime":"2020-02-08 02:00:00"},{"cm

Transformation du format JSON en Time Series

Toutes les données qu’on récupère sont référencées par rapport à une date/heure. Il s’agit de données particulières, qu’on appelle time series en anglais. On transforme donc les données fournies par jeedom d’un capteur dans un format time series. Puis on s’assure que tout va bien.

In [4]:
import json
import pandas as pd

datas = json.loads(hist_temp)
datas2 = datas['result']
pddata = pd.DataFrame.from_dict(datas2)

pddata['datetime']=pd.to_datetime(pddata['datetime'])
pddata['value']=pd.to_numeric(pddata['value'], downcast='float')
pddata = pddata.set_index('datetime')
pddata = pddata.drop(columns=['cmd_id'])
pddata = pddata.rename(columns={'value':'T° SAM'})
print(pddata.info(verbose=True))
pddata.head()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 24 entries, 2020-02-08 00:00:00 to 2020-02-08 23:00:00
Data columns (total 1 columns):
T° SAM    24 non-null float32
dtypes: float32(1)
memory usage: 288.0 bytes
None
Out[4]:
T° SAM
datetime
2020-02-08 00:00:00 20.500000
2020-02-08 01:00:00 20.500000
2020-02-08 02:00:00 20.500000
2020-02-08 03:00:00 20.435833
2020-02-08 04:00:00 20.400000

Afficher graphiquement la timeseries

Pour se faire plaisir, traçons la courbe des données qu’on vient de charger

In [5]:
%matplotlib inline
import matplotlib.pyplot as plt
pddata.plot()
plt.show()

Importation d’un second capteur

Chargement des données

In [6]:
import json
import pandas as pd

hist_phasejour=Jeedom_getHistory(2626,"2020-02-08 00:00:00","2020-02-08 23:59:59")

datas = json.loads(hist_phasejour)
datas2 = datas['result']
pdtmp = pd.DataFrame.from_dict(datas2)

pdtmp['datetime']=pd.to_datetime(pdtmp['datetime'])
pdtmp['value']=pd.to_numeric(pdtmp['value'], downcast='integer')
pdtmp = pdtmp.set_index('datetime')
pdtmp = pdtmp.drop(columns=['cmd_id'])
pdtmp = pdtmp.rename(columns={'value':'Phase Jour'})
pdtmp
Out[6]:
Phase Jour
datetime
2020-02-08 06:35:00 4
2020-02-08 07:15:00 3
2020-02-08 07:50:00 2
2020-02-08 08:30:00 1
2020-02-08 18:20:00 5
2020-02-08 18:55:00 6
2020-02-08 19:35:00 7
2020-02-08 20:10:00 0

Problème : on ne connait pas la valeur au début de la timeserie

La valeur a dû être fixée le jour d’avant, et en téléchargeant l’historique sur une période de date limitée on n’a pas reçu cette valeur, il est donc nécessaire de récupérer la valeur au début de la période qui nous intéresse.

In [10]:
import pandas as pd
import math
def Jeedom_getoldvalue(id, start,stop):                                                          
  parameters = {                                                                
          "jsonrpc" : "2.0",                                                    
          "method" : "cmd::getStatistique",                                                                                                           
          "params": {                                                           
              "id" : id,
              "apikey": Api_key,
              "startTime": start, 
              "endTime": stop
              }                                                                 
          }                                                                                              
  params = json.dumps(parameters).encode('utf8')                                                                                                                    
  req = urllib.request.Request(adresse_API, data=params, headers={'Content-Type': 'application/json'})        
                                                                                
  response = urllib.request.urlopen(req)                                               
  return response.read().decode('utf8')                                                         
                                                                                                          
print(pdtmp['2020-02-08 00:00:00':'2020-02-08 00:04:00'].empty)
if pdtmp['2020-02-08 00:00:00':'2020-02-08 00:04:00'].empty == True :
    oldvalue_phase=Jeedom_getoldvalue(2626,"2020-02-07 00:00:00","2020-02-08 00:00:00")
    datas = json.loads(oldvalue_phase)
    datas2 = datas['result']['last']
    print(type(datas2))
    pdtmp = pdtmp.append(pd.DataFrame({'Phase Jour':math.ceil(float(datas2))},index={pd.to_datetime('2020-02-08 00:00:00')}))
    pdtmp = pdtmp.sort_index()
print(pdtmp.info(verbose=True))
pdtmp
True
<class 'str'>
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 9 entries, 2020-02-08 00:00:00 to 2020-02-08 20:10:00
Data columns (total 1 columns):
Phase Jour    9 non-null int64
dtypes: int64(1)
memory usage: 144.0 bytes
None
Out[10]:
Phase Jour
2020-02-08 00:00:00 4
2020-02-08 06:35:00 4
2020-02-08 07:15:00 3
2020-02-08 07:50:00 2
2020-02-08 08:30:00 1
2020-02-08 18:20:00 5
2020-02-08 18:55:00 6
2020-02-08 19:35:00 7
2020-02-08 20:10:00 0

Intégration des deux types de données dans une seule time serie

On réintègre les données des deux capteurs dans le même jeu de donnée. Attention à la façon de concaténer ces données : il ne faut pas en perdre, ni créer des enregistrements inutiles qui alourdiraient les traitements postérieurs.

In [12]:
import pandas as pd
import matplotlib.pyplot as plt
pdresult = pd.merge(pddata,pdtmp, left_index=True, right_index=True, sort=True,how='outer').fillna(method='ffill')
pdresult.head(10)
Out[12]:
T° SAM Phase Jour
2020-02-08 00:00:00 20.500000 4.0
2020-02-08 01:00:00 20.500000 4.0
2020-02-08 02:00:00 20.500000 4.0
2020-02-08 03:00:00 20.435833 4.0
2020-02-08 04:00:00 20.400000 4.0
2020-02-08 05:00:00 20.333332 4.0
2020-02-08 06:00:00 20.316668 4.0
2020-02-08 06:35:00 20.316668 4.0
2020-02-08 07:00:00 20.400000 4.0
2020-02-08 07:15:00 20.400000 3.0

Affichage graphique des données concaténées

In [15]:
%matplotlib inline
pdresult.plot()
plt.show()

Vincent Recipon

Propriétaire de ce blog. Owner of this blog.

Vous aimerez aussi...

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.