One of the issues with the rtl_433 application is that it is not
possible to connect it to a remote rtl_tcp server using syntax supported
by other SDR application like gqrx. One of proposed solutions is to use the TCP enabled version of the librtlsdr which is a bit complicated. There's actually a much simpler solution.
The idea is to connect a simple client to a remote rtl_tcp server and redirect its standard output stream to the standard input of locally started rtl_433. I've implemented a simple rtl_tcp client in bash:
2. Now I want to show the temperature in the terminal window and also on a graph in real time:
There are couple of problems here on the graph:
The resulting command:
3. The command above also stores decoded samples in the sensors.log file. Using this file I can always recreate the graph for a specific sensor and for example add an integrating filter:
All mentioned scripts are available here
The idea is to connect a simple client to a remote rtl_tcp server and redirect its standard output stream to the standard input of locally started rtl_433. I've implemented a simple rtl_tcp client in bash:
#!/bin/sh # A simple bash rtl_tcp client SET_FREQUENCY=1 SET_SAMPLE_RATE=2 SET_GAIN_MODE=3 SET_GAIN=4 SET_FREQUENCY_CORRECTION=5 SET_AGC_MODE=8 show_error_exit() { echo "$1" >&2 echo "For help: $0 -h" exit 2 } show_usage() { cat <<HEREDOC Usage: $1 [options] Options: -h, show this help message and exit -f FREQUENCY, Frequency in Hz to tune to -a ADDRESS, Address of the server to connect to (default: localhost) -p PORT, Port of the server to connect to (default:1234) -s SAMPLERATE, Sample rate to use (default: 2400000) -g GAIN, Gain to use (default: 0 for auto) -P PPM, PPM error (default: 0) HEREDOC } byte() { printf \\$(printf "%03o" $1) } int2bytes() { byte $(($1>>24)) byte $(($1>>16&255)) byte $(($1>>8&255)) byte $(($1&255)) } set_frequency() { byte $SET_FREQUENCY int2bytes $1 } set_sample_rate() { byte $SET_SAMPLE_RATE int2bytes $1 } set_gain() { if [ $1 -eq 0 ]; then # automatic gain control byte $SET_GAIN_MODE int2bytes 0 byte $SET_AGC_MODE int2bytes 1 else byte $SET_GAIN_MODE int2bytes 1 byte $SET_AGC_MODE int2bytes 0 byte $SET_GAIN int2bytes 0 byte $SET_GAIN int2bytes $1 fi } set_ppm() { byte $SET_FREQUENCY_CORRECTION int2bytes $1 } address='localhost' port=1234 frequency=0 samplerate=0 gain=0 ppm=0 OPTIND=1 #reset index while getopts "ha:p:f:s:g:P:" opt; do case $opt in h) show_usage $(basename $0); exit 0; ;; a) address="$OPTARG" ;; p) port="$OPTARG" ;; f) frequency="$OPTARG" ;; s) samplerate="$OPTARG" ;; g) gain="$OPTARG" ;; P) ppm="$OPTARG" ;; \?) exit 1 ;; :) echo "Option -$OPTARG requires an argument" >&2;exit 1 ;; esac done shift $((OPTIND-1)) [ ! "$frequency" -eq 0 ] || show_error_exit "Wrong frequency" [ ! "$samplerate" -eq 0 ] || show_error_exit "Wrong sample rate" (set_frequency $frequency; set_sample_rate $samplerate; set_gain $gain; set_ppm $ppm) | nc $address $port
Usage examples
1. Using default rtl_433 parameters for frequency, sample rate and automatic gain for it to work:
$ rtlclient.sh -f 433920000 -a 192.168.1.153 -P 46 -s 250000 -g 0 | rtl_433 -G -r /dev/stdinHere I'm connecting to the rtl_tcp server at address 192.168.1.153 and enable all rtl_433 decoders. My dongle ppm is 46.
2. Now I want to show the temperature in the terminal window and also on a graph in real time:
$ rtlclient.sh -f 433920000 -a 192.168.1.153 -P 46 -s 250000 -g 0 | \ rtl_433 -G -r /dev/stdin -F json | tee /dev/stderr | grep --line-buffered ^{ | \ jq --unbuffered -c 'select(.temperature_C!=null)|.temperature_C' | \ bin/gp/gnuplotwindow.sh 200 "0:20" "Outside temperature"
Figure 1. Last 200 temperature samples |
- There are single wrong values produces by sensors sometimes
- The X axis shows number of processed samples and there's no relation to the time, i.e. samples appear asynchronously but I want to plot one sample per minute
The resulting command:
$ bin/rtlclient.sh -f 433920000 -a 192.168.1.153 -P 46 -s 250000 -g 0 | \ (while true; do rtl_433 -G -r /dev/stdin -F json; done) | tee /dev/stderr | \ grep --line-buffered ^{ | jq --unbuffered -c '.time |= (now|gmtime|mktime)' | \ tee -a sensors.log | jq --unbuffered -c 'select(.temperature_C!=null)|.temperature_C'| \ awk -v n=5 'BEGIN{m=int(n/2)+1}{if(1==i){for(j=1;j<n;++j){a[j]=a[j+1]}a[n]=$1}else{for(j=1;j<=n;++j){a[j]=$1};i=1}asort(a,b);print(b[m]);fflush()}' | \ bin/gp/syncpipe.pl 60 0 | bin/gp/gnuplotwindow.sh "$((24*60))" ":" "Outside temperature"
Figure 2. Temperature samples for the last 24 hours |
3. The command above also stores decoded samples in the sensors.log file. Using this file I can always recreate the graph for a specific sensor and for example add an integrating filter:
$ stdbuf -oL tail -n+1 -F sensors.log | grep --line-buffered Acurite |\ jq --unbuffered -r 'select(.temperature_C!=null)|[.temperature_C,.time]|@csv' |\ awk -v n=5 'BEGIN{m=int(n/2)+1}{if(1==i){for(j=1;j<n;++j){a[j]=a[j+1]}a[n]=$0}else{for(j=1;j<=n;++j){a[j]=$0};i=1}asort(a,b);print(b[m]);fflush()}' |\ awk -F, '{if(firstTime==""){firstTime=$2;temp=$1};while($2-firstTime>0){firstTime+=60;print temp}temp=$1;fflush()}' |\ bin/gp/addaverage.sh 15 1 |bin/gp/gnuplotwindow.sh "$((24*60))" ":" "Acurite Sensor" "Acurite Sensor averaged"
Figure 3. Acurite sensor temperature samples for the last 24 hours |
All mentioned scripts are available here
4 comments:
Do you have any suggestions on how to get the rtlclient.sh to exit when using an execution time limit within rtl_433. The time limit is set using the -T option
example: rtlclient.sh -f 433920000 -a 127.0.0.1 -p 1234 -s 250000 | rtl_433 -R 40 -F json -T 15 -U -r /dev/stdin
will this do?
timeout 15 rtlclient.sh -f 433920000 -a 127.0.0.1 -p 1234 -s 250000 | rtl_433 -R 40 -F json -U -r /dev/stdin
Thanks a lot! Works great.
rtl_433 has rtl_tcp support built in now: https://github.com/merbanan/rtl_433/pull/894
Post a Comment