S41 - Projet 2013/2014 - 1 - Extraction et transformation des données

Les données sont produites par la station météo sous la forme d’une séquence de caractère (pour commencer nous le simulerons avec un fichier texte) dont la forme est la suivante :

20.9degC
RHT03 : 	H=55% 		T=19.5degC
BMP085 :	P=998hPa	T=21degC
LDR :  		23.0%
Anemometre : 	0.0m/s
Girouette : 	90degres
Pluviometre : 	0mm


[HRTCC :		21/01/2014     09:25:37
Solaire :	Vpan=0.00V
Batterie :	Vbat=0.00V	Ibat=0.00A
Duty cycle :	R=50%
DS18S20 : 	20.9degC
RHT03 : 	H=55% 		T=19.5degC
BMP085 :	P=998hPa	T=21degC
LDR :  		23.0%
Anemometre : 	0.3m/s
Girouette : 	90degres
Pluviometre : 	0mm


[HRTCC :		21/01/2014     09:25:39
Solaire :	Vpan=0.00V
Batterie :	Vbat=0.00V	Ibat=0.00A
Duty cycle :	R=50%
DS18S20 : 	20.9degC
RHT03 : 	H=55% 		T=20.5degC
BMP085 :	P=998hPa	T=22degC
LDR :  		23.0%
Anemometre : 	0.5m/s
Girouette : 	45degres
Pluviometre : 	0mm

Le fichier data.txt contient une capture d’envoie d’un station météo.

On remarque que :

  • la station envoie régulièrement le même bloc d’information (la date en premier et le pluviomètre en dernier). En réalité chaque bloc d’information commence toujours par deux caractères : le caractère d’échappement (code ASCII 27, invisible sur un écran) et le caractère '['. Cela permet de trouver le début du prochain bloc.
  • Il y a un ensemble d’information fournie par un capteur par ligne, elle commence par une étiquette (Solaire, Batterie, …) suivie de ':'
  • Après le ':' se trouvent des informations qui sont :
    • soit une date (21/01/2014) puis une heure (09:25:39)
    • soit des listes de couples nom=valeur (H=55% T=19.5degC) séparées par des espaces et des tabulations
    • soit simplement une valeur (23.0%).
  • Toutes les valeurs (55%) sont composées d’une nombre (55) et d’une unité (%)

Dans le bloc précédent, il y a donc deux mesures utilisables (la première est incomplète).

Après extraction, toutes les informations seront stockées dans une liste dont chaque élément est un dictionnaire (un par groupe de mesures à un moment donné). L’entrée du dictionnaire est indexé par l’étiquette de la ligne. A l’intérieur, chaque mesure est représentée par un tableau à deux éléments (valeur et unité). Dans le cas où plusieurs mesures existent pour un label, elles sont stockées dans un dictionnaire.

Les dates est stockée dans datetime (http://docs.python.org/2/library/datetime.html#datetime-objects). Pour les utiliser il faut importer la class datetime du module datetime :

Voilà un exemple d’affectation de deux mesures construites ‘à la main’:

data=[{'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'], 'LDR': [23.0, '%'],
  'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']}, 'Anemometre': [0.0, 'm/s'], 'Pluviometre': [0.0, 'mm'],
  'Duty cycle': {'R': [50.0, '%']}, 'BMP085': {'P': [998.0, 'hPa'], 'T': [21.0, 'degC']},
  'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']}, 'HRTCC': datetime(2014, 1, 21, 9, 25, 37),
  'Solaire': {'Vpan': [0.0, 'V']}}, {'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'], 'LDR': [23.0, '%'],
                                     'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']}, 'Anemometre': [0.0, 'm/s'],
                                     'Pluviometre': [0.0, 'mm'], 'Duty cycle': {'R': [50.0, '%']},
                                     'BMP085': {'P': [998.0, 'hPa'], 'T': [22.0, 'degC']},
                                     'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']},
                                     'HRTCC': datetime(2014, 1, 21, 9, 25, 39),
                                     'Solaire': {'Vpan': [0.0, 'V']}},
 {'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'], 'LDR': [23.0, '%'],
  'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']}, 'Anemometre': [0.0, 'm/s'], 'Pluviometre': [0.0, 'mm'],
  'Duty cycle': {'R': [50.0, '%']}, 'BMP085': {'P': [998.0, 'hPa'], 'T': [23.0, 'degC']},
  'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']}, 'HRTCC': datetime(2014, 1, 21, 9, 25, 41),
  'Solaire': {'Vpan': [0.0, 'V']}}, {'DS18S20': [20.9, 'degC'], 'Girouette': [90.0, 'degres'], 'LDR': [23.0, '%'],
                                     'Batterie': {'Vbat': [0.0, 'V'], 'Ibat': [0.0, 'A']}, 'Anemometre': [0.0, 'm/s'],
                                     'Pluviometre': [0.0, 'mm'], 'Duty cycle': {'R': [50.0, '%']},
                                     'BMP085': {'P': [998.0, 'hPa'], 'T': [21.0, 'degC']},
                                     'RHT03': {'H': [55.0, '%'], 'T': [19.5, 'degC']},
                                     'HRTCC': datetime(2014, 1, 21, 9, 25, 43),
                                     'Solaire': {'Vpan': [0.0, 'V']}}]                                     

Le fichier data.py contient la déclaration python des mesures précédentes.

En haut de chaque module qui doit utiliser datetime ajouter :

from datetime import datetime

L’intérêt est ensuite de pouvoir accéder simplement aux valeurs :

print("Nombre de mesures:", len(data))
print('Les deux premieres mesures ', data[:3])
print('La pression donnee par le capteur BMP085 de la 5eme mesure ', data[4]['BMP085']['P'])

Créer un projet python pymeteo. Créer un module main.py. Déclarer une variable data qui contient quelques mesures. Tester les expressions précédentes. Afficher la valeur R sans l’unité de l’étiquette Duty cycle de la seconde mesure.

Lire la section chaîne de caractères de la page Traitement simple des chaînes de caractère en python avant de faire cet exercice.

Créer un module parser.py et la fonction def extract_label(ligne). Cette fonction retourne l’étiquette de la ligne passée en paramètre comme une chaîne de caractères.

Ajouter dans le module main.py le test de la fonction précédente :

print(parser.extract_label("HRTCC :		21/1/14     9:25:37"))

Il doit retourner HRTCC.

Lire la section expression régulière de la page Traitement simple des chaînes de caractère en python avant de faire cet exercice et les suivants.

Ajouter la fonction extract_datetime(data) au module parser. Elle doit retourner un datetime à partir d’une chaîne de caractère qui contient une date et une heure (comme dans les données de HRTCC). Pour créer un datetime, vous utiliserez la fonction datetime(int(annee), int(mois), int(jour), int(heure), int(minute), int(seconde)).

Vous tester votre fonction dans le module main.py:

 print(parser.extract_datetime("21/1/2014     9:25:37"))
 print(parser.extract_datetime("21/01/14     9:25:37"))

qui doit retourner

2014-01-21 09:25:37
2014-01-21 09:25:37

Dans le module parser ajouter la fonction extract_unit(data) qui prend en paramètre une chaîne de caractères qui contient un nombre et une unité et qui retourne un tableau avec deux éléments (la valeur et l’unité).

Vous testerez votre fonction :

print(parser.extract_unit("23deg"))
print(parser.extract_unit("+23°"))
print(parser.extract_unit("-23P"))
print(parser.extract_unit("23.4%"))
print(parser.extract_unit("+23.4E-3%"))

ce qui doit retourner :

[23.0, 'deg']
[23.0, '°']
[-23.0, 'P']
[23.4, '%']
[0.0234, '%']

Dans le module parser ajouter la fonction attribute_value(data) qui prend en paramètre une chaîne de caractères contenant des couple de la forme NOM=MESURE et retourne un dictionnaire indexé par les noms et contenant un tableau séparant la valeur et l’unité.

Vous testerez votre fonction :

print(parser.attribute_value("H=55% 		T=19.5degC"))
print(parser.attribute_value("R=50%"))

ce qui doit retourner :

{'H': [55.0, '%'], 'T': [19.5, 'degC']}
{'R': [50.0, '%']}

Ecrire la fonction parse(filename) qui retourne le tableau complet des données en utilisant les fonctions précédentes et en analysant le fichier dont le nom est passé en paramètre.

La démarche suivante est conseillée :

  1. chercher une ligne qui commence une nouvelle mesure, c’est à dire qui débute par les caractères escape (dont le code ASCII est 27) et “[”. La fonction ord(ch[i]) retourne le code ASCII du ième caractère de la chaîne ch), la fonction chr(i) retourne le caractère dont le code ascii est passé en paramètre.
  2. pour chaque ligne extraire l’étiquette et exécuter la bonne fonction pour extraire les données, l’ajouter à un dictionnaire temporaire qui sera ajouté à un tableau à chaque fois que l’on trouve le début d’un nouveau groupe de mesure (le caractère escape).

Ecrire les fonctions qui permettent de créer simplement des tableaux de valeurs à partir des clés

extractMesures(data, key, subkey)
extractMesures(data, key)
extractValues(data, key, subkey)
extractValues(data, key)
print('Le tableau des 3 premières temperatures données par BMP085', parser.extractMesures(data,'BMP085', 'T')[:3])
print('Le tableau des 3 premières temperatures données par BMP085 (sans unité)', parser.extractValues(data,'BMP085', 'T')[:3])

Un défi (optionnel) Création d'un tableur à partir des données

En vous inspirant de Lien avec OpenOffice, ecrire un module libreoffice.py qui permet d’exporter toutes les mesures dans différents onglets d’un tableur.

—- dataentry page —- type : TP enseignement_tags : S41 technologie_tags : Python,UNO