Outils pour utilisateurs

Outils du site


domotique:retro-ingenierie_d_une_station_meteo

Ceci est une ancienne révision du document !


Rétro-ingénierie d'une station météo

TL;DR : Le code est disponible sur GitHub : https://github.com/AntoineVe/Otio_WH510

Le signal radio

Pour recevoir les signaux de la station météo, j'utilise une radio définie par logiciel, ou software defined radio.

La radio Définie par logiciel, ou SDR pour Software Definied Radio, consiste à utiliser un ordinateur et une suite logicielle pour recevoir/émettre, moduler/démoduler, crypter/décrypter des signaux Radio. La pratique s'est développée dans les années 90 avec le perfectionnement du matériel informatique.
La Radio Définie par Logiciel (SDR) avec le chipset rtl2832u

Le signal est émis sur 868,292 Mhz. J'ai donc utilisé la commande suivante pour recevoir le signal : rtl_433 -f 868292000 -q -A.

Voici un exemple des données reçues :

$ rtl_433 -f 868292000 -q -A
 Found Rafael Micro R820T tuner
 Exact sample rate is: 250000.000414 Hz
 Sample rate set to 250000.
 Bit detection level set to 0 (Auto).
 Tuner gain set to Auto.
 Tuned to 868292000 Hz.
 Detected OOK package    @ 2017-07-31 01:05:40
 Analyzing pulses...
 Total count:   79,  width: 38949                (155.8 ms)
 Pulse width distribution:
  [ 0] count:   37,  width:   123 [121;127]      ( 492 us)
  [ 1] count:   42,  width:   367 [365;368]      (1468 us)
 Gap width distribution:
  [ 0] count:   78,  width:   243 [241;245]      ( 972 us)
 Pulse period distribution:
  [ 0] count:   36,  width:   366 [364;370]      (1464 us)
  [ 1] count:   42,  width:   610 [608;612]      (2440 us)
 Level estimates [high, low]:  15881,      2
 Frequency offsets [F1, F2]:   -1699,      0     (-6.5 kHz, +0.0 kHz)
 Guessing modulation: Pulse Width Modulation with fixed gap
 Attempting demodulation... short_limit: 245, long_limit: 246, reset_limit: 246, demod_arg: 0
 pulse_demod_pwm(): Analyzer Device
 bitbuffer:: Number of rows: 1
 [00] {79} fe bc 64 74 bc 02 04 21 d4 f2
 
 ^CSignal caught, exiting!
 
 User cancel, exiting...

La ligne qui nous interresse ici est [00] {79} fe bc 64 74 bc 02 04 21 d4 f2. Pour information, la station est à environ 20m du récepteur.

Analyse

Vient ensuite le moment d'analyser cette suite hexadécimale. Pour cela, j'ai laissé tourner l'enregistrement des données reçues (une redirection de la sortie de rtl_433 vers un fichier). 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.

meteo_graph.py
#!/bin/python3
 
from sys import argv
from pylab import *
import numpy as np
 
data_file = argv[1]
 
 
def col2array(dico, col):
    temp_liste = list()
    for line in dico:
        temp_liste.append(int(dico[line][col], 16))
    return(np.array(temp_liste))
 
 
with open(data_file, 'r') as data:
    data = data.read().splitlines()
data_dict = {}
count = 0
for line in data:
    if "[00] {79}" in line:
        data_dict.update({count: tuple(line.replace('[00] {79} ','').split())})
        count += 1
x = np.array(list(data_dict.keys()))
y0 = col2array(data_dict, 0)
y1 = col2array(data_dict, 1)
y2 = col2array(data_dict, 2)
y3 = col2array(data_dict, 3)
y4 = col2array(data_dict, 4)
y5 = col2array(data_dict, 5)
y6 = col2array(data_dict, 6)
y7 = col2array(data_dict, 7)
y8 = col2array(data_dict, 8)
y9 = col2array(data_dict, 9)
 
figure(figsize=(21,10), dpi=100)
# plot(x, y0, label="col 0")
# plot(x, y1, label="col 1")
plot(x, y2, label="col 2 (temp)")
print('temp1 : ', y2)
plot(x, y3, label="col 3 (temp)")
print('temp2 : ', y3)
plot(x, y4, label="col 4 (hum)")
print('hum : ', y4)
plot(x, y5, label="col 5 (vent ?)")
plot(x, y6, label="col 6 (vent ?)")
plot(x, y7, label="col 7 (pluie ?)")
plot(x, y8, label="col 8 (?)")
# plot(x, y9, label="col 9")
legend(loc='best')
# savefig("/tmp/meteo-graph.svg", dpi=100)
show()
close('all')

 graphique des données reçues

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'analyse tend vers une relation linéaire entre données reçues et données affichées. Pour cette analyse numérique, je vais faire de la régression linéaire.

Avec python, c'est la fonction linregress du module stats de scipy qui va me servir.

linregress(x, y=None)
    Calculate a linear least-squares regression for two sets of measurements.

    Parameters
    ----------
    x, y : array_like
        Two sets of measurements.  Both arrays should have the same length.
        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
       correlation coefficient
    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.

Discussion

Entrer votre commentaire. La syntaxe wiki est autorisée:
O A K N V
 
domotique/retro-ingenierie_d_une_station_meteo.1564866820.txt · Dernière modification : 03/08/2019 21:13 de antoineve