<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Hi Stephen.</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
What a cool project. I would never have thought to sniff the data from the weather station like that.</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<span style="background-color:rgb(255, 255, 255);display:inline !important">I am impressed.</span><br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<span style="background-color:rgb(255, 255, 255);display:inline !important"><br>
</span></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Yet another project to add to my list ðŸ˜‰</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Cheers,</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Rudy</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Chchrobotics <chchrobotics-bounces@lists.ourshack.com> on behalf of Stephen Irons <stephen@irons.nz><br>
<b>Sent:</b> Thursday, 5 May 2022 8:53 pm<br>
<b>To:</b> Christchurch Robotics <chchrobotics@lists.ourshack.com><br>
<b>Subject:</b> [chbot] No-code weather-station to web dashboard</font>
<div> </div>
</div>
<div>
<div id="x_geary-body" dir="auto">
<div>An interesting little project I got going over the past few Covid recovery days: connecting a weather-station to a web dashboard, without writing any code.</div>
<div><br>
</div>
<div><a href="https://iot.irons.nz/dashboard/cfd3f2f0-c9cf-11ec-820b-4b7d98d3a1b6?publicId=6e6c2c50-a97a-11ec-9bda-613c875470bf">https://iot.irons.nz/dashboard/cfd3f2f0-c9cf-11ec-820b-4b7d98d3a1b6?publicId=6e6c2c50-a97a-11ec-9bda-613c875470bf</a></div>
<div><br>
</div>
<div>I have a wireless weather-station, one of those ones that sends data from an outside sensor (wind speed and direction, temperature and humidity and rain-gauge) to an indoor console over a 433 MHz link. My system is the cheap version where the console has
 no PC/USB interface, and does not have Wi-Fi to upload to online weather services; more expensive versions do.</div>
<div><br>
</div>
<div>I also have a Realtek RTL2832U DVB dongle, often used for cheapo software-defined radios.</div>
<div><br>
</div>
<div>Duck-duck-going led me to RTL-433, a project that combines an SDR project with the RTL dongle, and includes a whole bunch of decoders for common 433 MHz devices: garage-door openers, car locks, remote controls, and, of course, weather stations.</div>
<div><br>
</div>
<div>Installed the available package (sudo apt install rtl-433), fired it up, waited a minute (the weather station sends data every 45 s or so), and, sure enough, there was the decoded data: temperature in Â°C, humidity in %, wind speed in Â°, wind direction
 in km/h.</div>
<div><br>
</div>
<div>There are options to</div>
<div>
<ul>
<li>restrict the type of messages decoded, so I don't hear any other devices</li><li>format the output as JSON rather than human-readable text</li></ul>
<div>Now, I have been playing around with Thingsboard, an 'IoT' telemetry platform, which takes data from external devices, stores and processes the data, and has a clicky control centre to create dashboards with graphs, tables, etc.</div>
<div><br>
</div>
<div>You push data to Thingboard using either an HTTP rest-like API, or using MQTT. In either case, the data must be a specific JSON format.</div>
<div><br>
</div>
<div>The JSON format from rtl-433 is not the same as expected by Thingsboard.</div>
</div>
<div><br>
</div>
<div>jq to the resque.</div>
<div><br>
</div>
<div>jq is a command-line JSON processor, which can reformat incoming JSON, changing the structuring, filtering out unnecessary fields, etc. A little bit of playing go the rtl-433 JSON into Thingsboard JSON format. It treats each input line as a single JSON
 document, and transforms that into an output line of a single JSON document.</div>
<div><br>
</div>
<div>mosquitto_pub is a command-line tool to publish data to a MQTT broker. It can send each line of input as a separate message to the broker.</div>
<div><br>
</div>
<div>A single rather long command line does the whole thing: rtl_433 | jq | mosquitto_pub</div>
<div><br>
</div>
<div>So, a bunch of environment variables and a single command line serves to receive data from the weather-station and push the data to the Thingsboard MQTT broker.</div>
<div><br>
</div>
<div>
<ul>
<li>RTL_SERIAL, MQTT_VER, MQTT_HOST, MQTT_PORT, MQTT_TOPIC, MQTT_TOKEN are set for your specific device, then</li><li>rtl_433 -d:$RTL_SERIAL -F json -M time:unix:utc -M protocol -M level -C si | tee -a rtl-thing.log | jq --compact-output --monochrome-output --unbuffered '{ ts: (.time | tonumber * 1000), values: {battery_ok, temperature_C, humidity, wind_dir_deg, wind_avg_km_h,
 wind_max_km_h, rain_mm, rssi, snr, noise}}' | mosquitto_pub -V $MQTT_VER --host $MQTT_HOST --port $MQTT_PORT --topic $MQTT_TOPIC --username $MQTT_TOKEN -l</li></ul>
</div>
<div>This runs on a Linux media server sitting near the TV.</div>
<div><br>
</div>
<div>A simple systemd .service file starts this up and keeps it going if it crashes.</div>
<div><br>
</div>
<div>There was a bit of clicking around in Thingsboard to create the 'device' that receives the MQTT data and stores it. Then much clicking around to create the dashboard at
<a href="https://iot.irons.nz/dashboard/cfd3f2f0-c9cf-11ec-820b-4b7d98d3a1b6?publicId=6e6c2c50-a97a-11ec-9bda-613c875470bf">
https://iot.irons.nz/dashboard/cfd3f2f0-c9cf-11ec-820b-4b7d98d3a1b6?publicId=6e6c2c50-a97a-11ec-9bda-613c875470bf</a></div>
<div><br>
</div>
<div><b>Updates that need code</b></div>
<div><br>
</div>
<div>Depending on when you look at the dashboard, you might see</div>
<div>
<ul>
<li>Wind-speed in knots rather than km/h, as I think of wind in knots. There is a one-line Javascript function in Thingboard to do this conversion for the wind-speed graph widget and the wind-speed numeric display. I guess I could have done this in the jq transformation
 step.</li><li>The wind-direction is very noisy. I had to add my own smoothing calculation. Thingsboard can do averaging, etc. However, smoothing a compass reading is not a simple average: if the wind is hovering around north, jumping from say 355° to 5°, a normal average
 gives 180°, rather than 0°, definitely not what you want. DDG-ing leads to <a href="https://en.wikipedia.org/wiki/Circular_mean">https://en.wikipedia.org/wiki/Circular_mean</a>. Essentially, convert the angle to cartesian coordinates, smooth the x and y-coordinates
 separately, then use atan2 to convert back to angle.</li><li>The rain gauge reports a single accumulated value since power-on. I have processing to calculate rain in the past 1 hour and the past 24 hours. There was a tiny bit of rain yesterday evening.</li><li>Pressure comes from a different sensor via a different channel.</li></ul>
<div><br>
</div>
</div>
<div>Stephen Irons</div>
</div>
</div>
</body>
</html>