Blog der Heimetli Software AG

Datenübernahme von rtl_433

Der Aussensensor sendet seine Messwerte im 433MHz-Band als Puls-Code. rtl_433 erkennt ihn als Prologue-Sensor und kann die Daten decodieren und darstellen.

Mit der Option -R wird bestimmt dass nur dieses eine Format ausgewertet wird. Alle anderen werden ignoriert.

> rtl_433 -R 03
rtl_433 version 18.12-112-g653fa56 branch master at 201902210921 inputs file rtl_tcp RTL-SDR
Trying conf file at "rtl_433.conf"...
Trying conf file at "/root/.config/rtl_433/rtl_433.conf"...
Trying conf file at "/usr/local/etc/rtl_433/rtl_433.conf"...
Trying conf file at "/etc/rtl_433/rtl_433.conf"...
Registered 1 out of 120 device decoding protocols [ 3 ]
Detached kernel driver
Found Elonics E4000 tuner
Exact sample rate is: 250000.000414 Hz
Sample rate set to 250000 S/s.
Tuner gain set to Auto.
Tuned to 433.920MHz.
Allocating 15 zero-copy buffers
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
time      : 2019-08-27 13:38:53
model     : Prologue sensor                        id        : 5
rid       : 63           Channel   : 1             Battery   : OK            Button    : 0             Temperature: 32.00 C     Humidity  : 21 %
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
time      : 2019-08-27 13:39:28
model     : Prologue sensor                        id        : 5
rid       : 63           Channel   : 1             Battery   : OK            Button    : 0             Temperature: 32.00 C      Humidity  : 21 %
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

Das sieht hübsch aus, ist aber unpraktisch wenn man die Angaben mit einem anderen Programm verarbeiten will.

Zum Glück ist rtl_433 flexibel bei der Ausgabe. Besonders das CSV-Format ist gut geeignet für die Datenübernahme:

> rtl_433 -R 03 -F csv 2> /dev/null
time,msg,codes,model,id,rid,channel,battery,button,temperature_C,humidity
2019-08-27 14:16:13,,,Prologue sensor,5,63,1,OK,0,32.200,21
2019-08-27 14:16:48,,,Prologue sensor,5,63,1,OK,0,32.200,21

Den Standard Error habe ich umgeleitet um die Meldungen beim Start loszuwerden.

Achtung: das Ausgabeformat sieht je nach Sensor anders aus! Die folgenden Scripts müssen deshalb an den ausgewählten Sensor angepasst werden.

Die einfachste Version der Uebernahme besteht darin, den Standard Output in ein File zu schreiben. Das kann man entweder per Redirection oder einer erweiterten Option machen:

> rtl_433 -R 03 -F csv 2> /dev/null > rtllog.txt
> rtl_433 -R 03 -F csv:rtllog.txt 2> /dev/null

Die zweite Version hängt die neuen Werte an ein bestehendes File an.

Das funktioniert recht gut, aber das Datenfile muss immer wieder gelesen werden um die aktuellen Messwerte zu bekommen.

Python

rtl_433 macht nach jeder Ausgabe ein flush um das Buffering von Linux zu umgehen. Dieses Verhalten erlaubt es, die Ausgaben ohne Verzögerung über eine Pipe zu schicken. Ein Programm in Python das den Standard Input liest, ist schnell geschrieben:

import sys

for line in sys.stdin:
    values = line.split( "," )
    if values[0] != "time":
        print( "Datum/Zeit: {} Temperatur: {}".format(values[0],values[9]) )

Die Bedingung sorgt dafür dass der Header ausgeblendet wird.

Gestartet wird der Prozess wie folgt:

> rtl_433 -R 03 -F csv | python3 prologue.py

Bei Bedarf kann man auch hier den Standard Error umlenken.

Python mit Subprozess

Wer den Start der Pipeline aufwendig findet, kann das auch direkt mit Python erledigen:

import subprocess

proc = subprocess.Popen( ["/usr/local/bin/rtl_433","-R","03","-F","csv"], stdout=subprocess.PIPE, universal_newlines=True )

while True:
    line   = proc.stdout.readline()
    values = line.split( "," )

    if values[0] != "time":
        print( "Datum/Zeit: {} Temperatur: {}".format(values[0],values[9]) )

Gestartet wird das so:

> python3 pipeline.py

bash

Fast ebenso einfach wie mit Python geht es mit der bash:

#!/bin/bash
IFS=','

while read -ra values
do
  if [ "${values[0]}" != "time" ]
  then 
    echo "Datum/Zeit: ${values[0]} Temperatur: ${values[9]}"
  fi
done

Die Kommandozeile für dieses Script:

> rtl_433 -R 03 -F csv | ./reader.sh