domotique:retro-ingenierie_d_une_station_meteo
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
domotique:retro-ingenierie_d_une_station_meteo [03/08/2019 21:03] – antoineve | domotique:retro-ingenierie_d_une_station_meteo [20/10/2019 15:22] (Version actuelle) – Alecto antoineve | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | ~~DISCUSSION~~ | ||
+ | |||
+ | {{ : | ||
+ | |||
====== Rétro-ingénierie d'une station météo ====== | ====== Rétro-ingénierie d'une station météo ====== | ||
- | //TL;DR// : Le code est disponible sur GitHub | + | Cette station météo, "Otio WH5100" |
+ | |||
+ | //TL;DR// : Le code est disponible sur mon repo git : https://git.antoineve.me/Otio_WH5100/ | ||
===== Le signal radio ===== | ===== Le signal radio ===== | ||
Ligne 47: | Ligne 53: | ||
La ligne qui nous interresse ici est '' | La ligne qui nous interresse ici est '' | ||
+ | |||
+ | ===== Analyse ===== | ||
+ | |||
+ | Vient ensuite le moment d' | ||
+ | Pour cela, j'ai laissé tourner l' | ||
+ | J'ai ainsi pu voir quelles parties de la chaîne se modifiaient dans la journée. | ||
+ | Pour une mieux visualiser ces données, j'ai écrit un script python utilisant pylab et numpy. | ||
+ | Ce script prend en argument le fichier écrit par rtl_433 et affiche un graphique. | ||
+ | |||
+ | <file python meteo_graph.py> | ||
+ | # | ||
+ | |||
+ | from sys import argv | ||
+ | from pylab import * | ||
+ | import numpy as np | ||
+ | |||
+ | data_file = argv[1] | ||
+ | |||
+ | |||
+ | def col2array(dico, | ||
+ | temp_liste = list() | ||
+ | for line in dico: | ||
+ | temp_liste.append(int(dico[line][col], | ||
+ | return(np.array(temp_liste)) | ||
+ | |||
+ | |||
+ | with open(data_file, | ||
+ | data = data.read().splitlines() | ||
+ | data_dict = {} | ||
+ | count = 0 | ||
+ | for line in data: | ||
+ | if "[00] {79}" in line: | ||
+ | data_dict.update({count: | ||
+ | count += 1 | ||
+ | x = np.array(list(data_dict.keys())) | ||
+ | y0 = col2array(data_dict, | ||
+ | y1 = col2array(data_dict, | ||
+ | y2 = col2array(data_dict, | ||
+ | y3 = col2array(data_dict, | ||
+ | y4 = col2array(data_dict, | ||
+ | y5 = col2array(data_dict, | ||
+ | y6 = col2array(data_dict, | ||
+ | y7 = col2array(data_dict, | ||
+ | y8 = col2array(data_dict, | ||
+ | y9 = col2array(data_dict, | ||
+ | |||
+ | figure(figsize=(21, | ||
+ | # plot(x, y0, label=" | ||
+ | # plot(x, y1, label=" | ||
+ | plot(x, y2, label=" | ||
+ | print(' | ||
+ | plot(x, y3, label=" | ||
+ | print(' | ||
+ | plot(x, y4, label=" | ||
+ | print(' | ||
+ | plot(x, y5, label=" | ||
+ | plot(x, y6, label=" | ||
+ | plot(x, y7, label=" | ||
+ | plot(x, y8, label=" | ||
+ | # plot(x, y9, label=" | ||
+ | legend(loc=' | ||
+ | # savefig("/ | ||
+ | show() | ||
+ | close(' | ||
+ | </ | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | J'ai ensuite rapproché les relevés bruts avec les données affichées sur le terminal météo fourni. | ||
+ | Après avoir un peu tâtonné, l' | ||
+ | Pour cette analyse numérique, je vais faire de la [[https:// | ||
+ | |||
+ | Avec python, c'est la fonction // | ||
+ | |||
+ | < | ||
+ | linregress(x, | ||
+ | Calculate a linear least-squares regression for two sets of measurements. | ||
+ | |||
+ | Parameters | ||
+ | ---------- | ||
+ | x, y : array_like | ||
+ | Two sets of measurements. | ||
+ | If only x is given (and y=None), then it must be a two-dimensional | ||
+ | array where one dimension has length 2. The two sets of measurements | ||
+ | are then found by splitting the array along the length-2 dimension. | ||
+ | |||
+ | Returns | ||
+ | ------- | ||
+ | slope : float | ||
+ | slope of the regression line | ||
+ | intercept : float | ||
+ | intercept of the regression line | ||
+ | rvalue : float | ||
+ | | ||
+ | pvalue : float | ||
+ | two-sided p-value for a hypothesis test whose null hypothesis is | ||
+ | that the slope is zero. | ||
+ | stderr : float | ||
+ | Standard error of the estimated gradient. | ||
+ | </ | ||
+ | |||
+ | ==== Température ==== | ||
+ | Pour la température, | ||
+ | (e.g. '' | ||
+ | L' | ||
+ | |||
+ | Régression linéaire : | ||
+ | |||
+ | <code pycon> | ||
+ | >>> | ||
+ | >>> | ||
+ | >>> | ||
+ | >>> | ||
+ | >>> | ||
+ | (0.050000000000000031, | ||
+ | >>> | ||
+ | 0.0 | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | On a donc : f(x) = 0,05 * x − 1268,8. Avec une erreur standard nulle, ce qui signifie que la formule « tombe juste » | ||
+ | (Si on trace la courbe à partir de la formule, elle passe parfaitement par tous les points relevés). | ||
+ | |||
+ | En python : | ||
+ | |||
+ | <code pycon> | ||
+ | >>> | ||
+ | ... return round((0.05*data-1268.8), | ||
+ | ... | ||
+ | >>> | ||
+ | 17.0 | ||
+ | </ | ||
+ | |||
+ | J'ai également remarqué que l' | ||
+ | permettant d' | ||
+ | |||
+ | ==== Humidité ==== | ||
+ | |||
+ | Pour l' | ||
+ | On voit bien sur la courbe des relevés la relation qu'ont la température et l' | ||
+ | L' | ||
+ | La relation est donc très simple : y = 0.5 * x. | ||
+ | C'est à dire que la valeur de l' | ||
+ | |||
+ | En python : | ||
+ | |||
+ | <code pycon> | ||
+ | >>> | ||
+ | | ||
+ | ... | ||
+ | >>> | ||
+ | 94 | ||
+ | </ | ||
+ | |||
+ | ==== Anémomètre ==== | ||
+ | |||
+ | La station météo renvoie deux paramètres pour le vent : une moyenne (ou médiane ?) | ||
+ | et le maximum (ce qui correspond aux rafales). | ||
+ | Ceux-ci sont portés sur les octets 6 et 7. | ||
+ | L' | ||
+ | |||
+ | <code pycon> | ||
+ | >>> | ||
+ | >>> | ||
+ | >>> | ||
+ | >>> | ||
+ | >>> | ||
+ | (0.61264343715451175, | ||
+ | >>> | ||
+ | 0.0009343564466014815 | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | J'ai essayé avec les différentes configuration : km/h, mph, knots (nœuds), ... | ||
+ | Jamais d' | ||
+ | Certainement une erreur à cause d' | ||
+ | |||
+ | La fonction est donc : | ||
+ | |||
+ | <code pycon> | ||
+ | >>> | ||
+ | ... return round((0.61264343715451175*data-0.018142655636458116), | ||
+ | ... | ||
+ | >>> | ||
+ | 55.1 | ||
+ | </ | ||
+ | |||
+ | ==== Pluviomètre ==== | ||
+ | Pour le pluviomètre, | ||
+ | il faut ajouter 0,3 mm de pluie. La donnée est codée sur 1 octet, le 8ème de la transmission, | ||
+ | Il faut pouvoir gérer cette situation. Pour plus de facilité, je stocke la valeur dans un fichier temporaire. | ||
+ | |||
+ | <code python> | ||
+ | def rain(raw): | ||
+ | | ||
+ | try: | ||
+ | with open("/ | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | if old_rain is None: | ||
+ | with open("/ | ||
+ | | ||
+ | | ||
+ | if current > old_rain: | ||
+ | res = round(float(current-old_rain)*0.3, | ||
+ | with open("/ | ||
+ | | ||
+ | else: | ||
+ | if (current+255)-old_rain < 254: | ||
+ | res = round(float((current+255)-old_rain)*0.3, | ||
+ | with open("/ | ||
+ | | ||
+ | else: | ||
+ | res = 0 | ||
+ | | ||
+ | </ |
domotique/retro-ingenierie_d_une_station_meteo.1564866233.txt · Dernière modification : 03/08/2019 21:03 de antoineve