Christian Fetzer2024-02-11T20:04:47+00:00https://fetzerch.github.ioChristian Fetzer[email protected]Sun and Moon Datasource Plugin for Grafana2016-07-03T00:00:00+00:00https://fetzerch.github.io/2016/07/03/grafana-sunandmoon-datasource<p>While working on <a href="/2015/05/20/atmeteo/">atMETEO</a>, I found it useful to bring the measured
temperature and atmospheric pressure values into relation with the position
of the sun or the current moon phase and see how they correlate.
Back then when <a href="https://grafana.com">Grafana</a> only supported the <a href="https://graphiteapp.org">Graphite</a>
datasource this was done with a simple script that calculated those
values every minute and stored them in the Graphite database along with the
other measurements.</p>
<p>Now that Grafana supports a sophisticated plugin framework (<a href="https://grafana.com/blog/2016/05/11/grafana-3.0-stable-released">starting
with v3.0</a>), I have created the <a href="https://grafana.com/grafana/plugins/fetzerch-sunandmoon-datasource"><em>Sun and Moon Datasource Plugin for
Grafana</em></a> which uses <a href="https://github.com/mourner/suncalc">SunCalc</a> to calculate the position
of sun and moon on demand when rendering on the frontend. Additional features
are the calculation of the moon illumination and annotations for various events
such as sunrise or sunset.</p>
<p><a href="/assets/grafana-sunandmoon-datasource.png" data-lightbox="Sun and Moon Datasource Plugin for Grafana" title="Grafana screenshot showing the Sun and Moon Datasource Plugin.">
<img src="/assets/grafana-sunandmoon-datasource.png" alt="Grafana screenshot showing the Sun and Moon Datasource Plugin." />
</a></p>
<p>Like all Grafana plugins the <a href="https://grafana.com/grafana/plugins/fetzerch-sunandmoon-datasource"><em>Sun and Moon Datasource Plugin</em></a> is
now hosted on <a href="https://grafana.com">Grafana.net</a> and the source code is available in a
<a href="https://github.com/fetzerch/grafana-sunandmoon-datasource">GitHub repository</a>. An <a href="https://grafana.com/grafana/dashboards/630">example dashboard</a> can be found
as well.</p>
<h2 id="technical-aspects">Technical aspects</h2>
<p>The main advantage of doing the calculation in a datasource on the client side
is that the values don’t have to be pregenerated which is not optimal with
Graphite because it does not allow to submit future values and therefore the
calculation has to be done just in time.</p>
<p>From a technical point of view the plugin is interesting because as of today
it is the only Grafana plugin that doesn’t rely on a server providing the data.
Therefore it might be a useful example for new plugin authors.</p>
<h2 id="feedback">Feedback</h2>
<p>When submitting the plugin to <a href="https://grafana.com">Grafana.net</a> I received very
positive feedback from <a href="https://raintank.io">raintank</a>, the company behind Grafana and
<a href="https://github.com/torkelo">Torkel Ödegaard</a> even demoed the datasource in his talk at this year’s
<a href="https://monitorama.com">Monitorama</a> which happened to take place two days after I
created the Pull Request on GitHub. Thanks for this! A recording is available
on <a href="https://www.youtube.com/embed/1SlljMU9V5k?start=6748&end=6810">YouTube</a>.</p>
<h2 id="outlook-and-further-work">Outlook and further work</h2>
<p>The current version of the plugin implements all features that <a href="https://github.com/mourner/suncalc">SunCalc</a>
currently offers. Nevertheless there are already a few ideas for future
improvements.</p>
<p>I could imagine that the plugin might be useful when monitoring
photovoltaic systems (maybe even solar parks). For this the calculation
of the clear sky radiation could be added. Additionally the annotations could
be extended to be able to show additional astronomic events such as full and
new moon or solstices/equinoxes and perihelion/aphelion.</p>
<p>If you have additional ideas or want to help out for example with the
calculation of the mentioned values, please use the
<a href="https://github.com/fetzerch/grafana-sunandmoon-datasource/issues">issue tracker on GitHub</a>.</p>
Monitoring sensor values of an HP ProLiant MicroServer G7 N54L2015-11-15T00:00:00+00:00https://fetzerch.github.io/2015/11/15/hp-n54l-drivers<p>I’m running a small Linux server (<em>HP ProLiant MicroServer G7 N54L</em>) in my
home network as backup drive for desktops and notebooks. The health of the
server is critical and therefore I wanted to keep track of some system
metrics such as temperatures, voltages and system fan speed in the hope that
they can detect hardware problems in advance.</p>
<p>These metrics are typically offered by hardware monitor chips and can
be accessed in Linux with the <em>lm-sensors</em> utilities (<code class="language-plaintext highlighter-rouge">sensors-detect</code> and
<code class="language-plaintext highlighter-rouge">sensors</code>). Unfortunately <code class="language-plaintext highlighter-rouge">sensors-detect</code> was not able to detect the
respective chip (<em>Nuvotem/Winbond W83795ADG</em>). After a bit of research, it
turned out that the SMBus/I2C driver for the chipset failed to detect the
sensor. Luckily there was already a <a href="https://www.mail-archive.com/[email protected]/msg06757.html">patch</a> available that fixed
the driver but supported only an older kernel version. The patch was never
merged into the mainline Linux kernel and meanwhile a few things have changed
in that module. Since I think it’s a valuable change, I ported it to the
current kernel version, cleaned it up and re-sent it to the
<a href="http://vger.kernel.org/vger-lists.html#linux-i2c">mailing list</a> where it’s currently being reviewed. (<em>UPDATE</em>: The
patch has been merged and is included in Linux 4.5.)</p>
<p>For the time being, the patched driver can be found in this <a href="https://github.com/fetzerch/hp-n54l-drivers">GitHub
repository</a> including a more detailed description and
installation instructions. This should make it simple for anyone
interested to test it and use it on their systems.</p>
<p>After installation of the updated driver and loading the modules, <code class="language-plaintext highlighter-rouge">sensors</code> is
able to show the measurements:</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dg-i2c-1-2f
Adapter: SMBus PIIX4 adapter SDA2 at 0b00
Vcore: +0.88 V (min = +0.50 V, max = +1.40 V)
Vdimm: +1.51 V (min = +1.42 V, max = +1.57 V)
+3.3V: +3.30 V (min = +2.96 V, max = +3.63 V)
3VSB: +3.26 V (min = +2.96 V, max = +3.63 V)
System Fan: 679 RPM (min = 329 RPM)
CPU Temp: +34.8°C (high = +109.0°C, hyst = +109.0°C)
(crit = +109.0°C, hyst = +109.0°C) sensor = thermal diode
NB Temp: +43.2°C (high = +105.0°C, hyst = +105.0°C)
(crit = +105.0°C, hyst = +105.0°C) sensor = thermal diode
MB Temp: +20.8°C (high = +39.0°C, hyst = +39.0°C)
(crit = +44.0°C, hyst = +44.0°C) sensor = thermistor
</code></pre></div></div>
<p>The sensor readings can be easily aggregated with <a href="https://collectd.org">collectd’s</a>
<a href="https://collectd.org/wiki/index.php/Plugin:Sensors">sensor</a> plugin. Unfortunately the current version of the
plugin has one minor limitation and tracks the sensor readings only by
metric names (e.g “temp1”) but not by the more descriptive labels
(e.g. “CPU Temp”). To address this shortcoming I’ve created a
<a href="https://github.com/collectd/collectd/pull/1239">pull request on GitHub</a>. (<em>UPDATE</em>: The pull request has been
merged and the feature is included in collectd 5.6.0.)</p>
<p>The following <a href="https://grafana.com">grafana</a> screenshot shows the result:</p>
<p><a href="/assets/hp-n54l-drivers_grafana.png" data-lightbox="Monitoring sensor values of an HP ProLiant MicroServer G7 N54L" title="Grafana screenshot showing sensor data from an HP ProLiant MicroServer G7 N54L">
<img src="/assets/hp-n54l-drivers_grafana.png" alt="Grafana screenshot showing sensor data from an HP ProLiant MicroServer G7 N54L" />
</a></p>
<p>The drive temperatures were collected using the <a href="https://collectd.org/wiki/index.php/Plugin:HDDTemp">HDDTemp</a> plugin.</p>
atMETEO - An ATmega based weather station2015-05-20T00:00:00+00:00https://fetzerch.github.io/2015/05/20/atmeteo<p>Besides logging and visualizing <a href="/2014/08/23/fritzcollectd/">internet connection statistics</a>
I wanted to track also local weather conditions and later eventually integrate
the data into a home automation system. While today there are proprietary and
free projects available that facilitate this, the topic seemed to be a perfect
candidate for a small spare time open source project, which I called
<em><a href="https://github.com/fetzerch/atMETEO">atMETEO</a></em>.</p>
<p><a href="/assets/atmeteo_logo.svg" data-lightbox="atMETEO - An ATmega based weather station" title="atMETEO - An ATmega based weather station">
<img src="/assets/atmeteo_logo.svg" alt="atMETEO - An ATmega based weather station" />
</a></p>
<h2 id="project-goals-and-introduction">Project goals and introduction</h2>
<p>Programming an ATmega based weather station not only allowed to deepen my
knowledge in electronics and microcontrollers, at the same time the project
served as practical accompaniment while reading Modern C++ Design and
C++ Templates and enabled me to explore the advantages and limits of
<em>modern C++ on 8 bit hardware</em>.</p>
<p>The essential concept of <em>atMETEO</em> is to read and interpret data from
sensors connected to the microcontroller and to transfer this
information to a connected PC for further processing, storing and
visualization.</p>
<p>Ideally <em>atMETEO</em> should hereby be able to access my already existing Hideki
TS53 RF sensors. Therefore a preliminary step was to
<a href="/2014/11/15/reveng433/">reverse engineer</a> their data format.</p>
<p>Conducting test automation is essential in order to develop a stable
product which can be left running unattended. For this purpose a <a href="https://www.jenkins.io">Jenkins</a>
server has been set up that runs <a href="https://clang-analyzer.llvm.org/">Clang Static Analyzer</a>, builds all commits
and executes unit tests (including code coverage generation). In addition it
flashes new software periodically and maintains statistics on successful and
failed attempts to read sensor data for a given time range to identify possible
race conditions.</p>
<h2 id="technical-aspects">Technical aspects</h2>
<p>Even though microcontroller projects are usually hardware centric, the
main emphasis has been placed on the software part. My current setup utilizes
an <a href="https://docs.arduino.cc/hardware/uno-rev3">Arduino Uno</a>, but <em>atMETEO</em> is prepared to be built for different
ATmega boards with only minor adaption. Currently there are 5 sensor types
supported: Hideki TS53 Thermo/Hygrometer, DHT22 / AM2302 temperature and
humidity module, Bosch BMP180 Digital pressure sensor, Melexis MLX90614
Infrared thermometer and Figaro TGS 2600 air contaminant sensor. The RF
receiver as well as the other sensors are connected to the microcontroller as
shown in the following breadboard circuit (created with <a href="https://fritzing.org">Fritzing</a>).</p>
<p><a href="/assets/atmeteo_breadboard.png" data-lightbox="atMETEO - An ATmega based weather station" title="atMETEO sensor setup on breadboard">
<img src="/assets/atmeteo_breadboard.png" alt="atMETEO sensor setup on breadboard" />
</a></p>
<p>On the software side the project is divided into two main parts.
A <em>libsensors</em> library contains the target / platform independent
functionality and algorithms and ships with unit tests that can be executed
on the host. All utilities for accessing ATmega hardware features (such as
pins, timers, UART, I2C (TWI), SPI) as well as an Ethernet driver
(WIZnet W5100) are part of <em>libtarget</em>. The main application makes then use of
both libraries in order to send the measured sensor data in JSON format over
UART or Ethernet (UDP) to the host.</p>
<p><em>atMETEO</em> uses the <a href="https://www.cmake.org">CMake</a> build system which controls cross compilation
(including flashing) as well as unit tests (including code coverage
generation) and <a href="https://www.doxygen.nl/index.html">Doxygen</a> documentation.</p>
<p>Detailed information can be found in the project’s <a href="https://github.com/fetzerch/atMETEO/blob/master/README.md">readme</a> and the
<a href="https://fetzerch.github.io/atMETEO">documentation</a>.</p>
<h2 id="graphical-user-interface">Graphical user interface</h2>
<p><a href="https://graphiteapp.org">Graphite</a> and <a href="https://grafana.com">grafana</a> are two excellent tools for logging and graphing time
series data. With the command line client <em>atMETEO</em> integrates nicely into
this setup as it can be configured to transfer measurements to graphite’s
carbon daemon.</p>
<p>The following screenshot shows the <em>atMETEO</em> dashboard I am using to access
the measurements from PC, tablet or phone.</p>
<p><a href="/assets/atmeteo_grafana.png" data-lightbox="atMETEO - An ATmega based weather station" title="Grafana screenshot showing data from atMETEO">
<img src="/assets/atmeteo_grafana.png" alt="Grafana screenshot showing data from atMETEO" />
</a></p>
<h2 id="outlook-and-further-work">Outlook and further work</h2>
<p><em>atMETEO</em> provides weather data now since more than 10 months, even though
hardware and circuit are still just built on a breadboard. One of the very
next steps therefore is to solder the sensors on a circuit board and fit
everything into a small enclosure.</p>
<p>The measurements are transferred to the host in JSON format. While this is
relatively easy to generate on the microcontroller, it requires to run an
<em>atMETEO</em> client application on the host to interpret the data and process it.
Therefore it would be beneficial to switch to a standard format such as <a href="https://en.wikipedia.org/wiki/MQTT">MQTT</a>.</p>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://fetzerch.github.io/atMETEO">Documentation</a></li>
<li><a href="https://github.com/fetzerch/atMETEO">GitHub repository</a></li>
</ul>
Reverse engineering 433 MHz sensors2014-11-15T00:00:00+00:00https://fetzerch.github.io/2014/11/15/reveng433<p>This article focuses on how to decode data sent by proprietary
RF 433 MHz sensors using the example of a wireless
thermo/hygrometer. Understanding how the sensor works is a first step towards
logging and analyzing the data on a computer.</p>
<p>Note that there are already implementations for many popular sensors
available online so that there’s a good chance that you will not have to
reverse engineer or implement anything on your own.</p>
<h2 id="visualizing-the-data">Visualizing the data</h2>
<p>At the very beginning it is essential to understand how the basic RF signal
being transmitted looks like. This can be accomplished either with an
oscilloscope/logic analyzer or simply with a sound card, <a href="https://www.audacityteam.org/">Audacity</a> and a
voltage divider circuit limiting the 5V from the RF receiver to <1V.</p>
<p><a href="/assets/reveng433-receiver.jpg" data-lightbox="Reverse engineering 433 MHz sensors" title="RF 433 MHz receiver for analyzing with Audacity (with an Arduino Uno as 5V power supply)">
<img src="/assets/reveng433-receiver.jpg" alt="RF 433 MHz receiver for analyzing with Audacity (with an Arduino Uno as 5V power supply)" />
</a></p>
<p>When the experimental setup is functional the first step is to collect a set
of meaningful samples for the subsequent analysis. An essential part thereby
is that the original receiver is available so that the samples can be annotated
with the reference values from the receiver’s display.
It proved to be useful to record samples that differentiate only in exactly one
value. This technique allows to easily isolate length and position of that
metric in the raw signal. Assuming that the length of a metric remains constant
for the whole message it can be used to split the message into blocks.</p>
<p>For the example sensor the first analysis reveals the position of temperature
and humidity as well as a block size which is illustrated by reference lines in
the figure below. It is also noticeable that the two last blocks change as soon
as temperature or humidity changes. This indicates that these blocks contain
CRC values.</p>
<p><a href="/assets/reveng433-audacity.png" data-lightbox="Reverse engineering 433 MHz sensors" title="Audacity showing the recorded RF 433 MHz signal">
<img src="/assets/reveng433-audacity.png" alt="Audacity showing the recorded RF 433 MHz signal" />
</a></p>
<p>The recordings should also give a good overview on how often the sender
transmits and in which time periods. The exemplary thermo/hygrometer sensor
sends three times in a row every 43 seconds.</p>
<h2 id="modulation-bit-decoding-and-interpreting-the-payload">Modulation, bit decoding and interpreting the payload</h2>
<p>The next step in the analysis is to determine which modulation is used.
Typically RF 433 MHz sensors use line codes such as <a href="https://en.wikipedia.org/wiki/Manchester_encoding">Manchester</a>,
<a href="https://en.wikipedia.org/wiki/Biphase_mark_code">Differencial Manchester</a> or <a href="https://en.wikipedia.org/wiki/Biphase_mark_code">Biphase Mark</a> coding. Other sensors use
<a href="https://en.wikipedia.org/wiki/On-off_keying">On-off keying</a>.</p>
<p>Decoding the particular sections from the example above using
<a href="https://en.wikipedia.org/wiki/Biphase_mark_code">Biphase Mark coding</a>, where a long pulse represents a binary 1 and a
short pulse a binary 0, yields the following results.</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>111110010 000001001 011100111 011110011 001010101 010000111 101001001 110111111 000111001 011111100
111110010 000001001 011100111 011110011 001010101 010000111 011001001 110111111 110111001 101111010
111110010 000001001 011100111 011110011 011010100 010000111 011001001 110111111 100111000 101100100
</code></pre></div></div>
<p>The binary representation consists of ten blocks each with nine bits, which
indicates that there are eight data bits followed by one parity bit. A cross
check reveals that even parity is used.</p>
<p>Subsequently the binary representation has to be transformed into data bytes
by applying the correct bit numbering such as <a href="https://en.wikipedia.org/wiki/Bit_numbering">MSB</a> or <a href="https://en.wikipedia.org/wiki/Bit_numbering">LSB</a>. Electronic
systems commonly use <a href="https://en.wikipedia.org/wiki/Binary-coded_decimal">Binary-coded decimal</a> encoding a decimal digit in
four bits (nibble). Therefore bit numbering variants with reversed nibbles are
further viable options.</p>
<table>
<thead>
<tr>
<th style="text-align: right">#1</th>
<th style="text-align: center">Display</th>
<th style="text-align: center">MSB 0</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">1</td>
<td style="text-align: center">25.4° - 25%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">F9 04 73 79 2A 43 A4 DF 1C 7E</code></td>
</tr>
<tr>
<td style="text-align: right">2</td>
<td style="text-align: center">25.4° - 26%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">F9 04 73 79 2A 43 64 DF DC BD</code></td>
</tr>
<tr>
<td style="text-align: right">3</td>
<td style="text-align: center">25.6° - 26%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">F9 04 73 79 6A 43 64 DF 9C B2</code></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th style="text-align: right">#2</th>
<th style="text-align: center">Display</th>
<th style="text-align: center">MSB 0 (reversed nibbles)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">1</td>
<td style="text-align: center">25.4° - 25%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">9F 40 37 97 A2 34 4A FD C1 E7</code></td>
</tr>
<tr>
<td style="text-align: right">2</td>
<td style="text-align: center">25.4° - 26%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">9F 40 37 97 A2 34 46 FD CD DB</code></td>
</tr>
<tr>
<td style="text-align: right">3</td>
<td style="text-align: center">25.6° - 26%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">9F 40 37 97 A6 34 46 FD C9 2B</code></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th style="text-align: right">#3</th>
<th style="text-align: center">Display</th>
<th style="text-align: center">LSB 0</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">1</td>
<td style="text-align: center">25.4° - 25%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">F9 02 EC E9 45 2C 52 BF 83 E7</code></td>
</tr>
<tr>
<td style="text-align: right">2</td>
<td style="text-align: center">25.4° - 26%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">F9 02 EC E9 45 2C 62 BF B3 DB</code></td>
</tr>
<tr>
<td style="text-align: right">3</td>
<td style="text-align: center">25.6° - 26%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">F9 02 EC E9 65 2C 62 BF 93 D4</code></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th style="text-align: right">#4</th>
<th style="text-align: center">Display</th>
<th style="text-align: center">LSB 0 (reversed nibbles)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">1</td>
<td style="text-align: center">25.4° - 25%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">9F 20 CE 9E 54 C2 25 FB 38 7E</code></td>
</tr>
<tr>
<td style="text-align: right">2</td>
<td style="text-align: center">25.4° - 26%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">9F 20 CE 9E 54 C2 26 FB 3B BD</code></td>
</tr>
<tr>
<td style="text-align: right">3</td>
<td style="text-align: center">25.6° - 26%</td>
<td style="text-align: center"><code class="language-plaintext highlighter-rouge">9F 20 CE 9E 56 C2 26 FB 39 4D</code></td>
</tr>
</tbody>
</table>
<p>For the LSB bit numbering a closer look on the values in hex shows already the
expected decimal values. The humidity can be found in byte seven (0x25 for
25%) and the temperature is located in bytes five and six. Therefore
LSB 0 with reversed nibbles seems to be the appropriate candidate for all
further proceedings.</p>
<p>The step of working out the correct modulation and bit numbering can be very
time consuming because the process only succeeds when at the end a correlation
between the byte value and the reference data can be found. This can make
several iterations with different parameter combinations necessary.</p>
<p>At the end of this process the complete user payload can be decoded which lays
the foundation for starting a basic implementation. The transmitted data
typically contains more information which can make the implementation simpler
or more robust. Examples of this are described in the next section.</p>
<h2 id="additional-information-encoded-in-the-payload">Additional information encoded in the payload</h2>
<h3 id="header">Header</h3>
<p>RF 433 MHz receivers usually perform automatic gain control to adjust
the reception level to a suitable value. While this is needed to receive data
over longer distances and to support weaker signals, it also increases the
noise level and complicates detecting the beginning of a message. Especially
because messages are only transmitted rarely in order to save energy. To
compensate this effect the messages are usually prefixed by a static pattern.
For the exemplary sensor every message starts with 0x9F.</p>
<h3 id="distinguishing-sensors">Distinguishing sensors</h3>
<p>If the original proprietary receiver supports multiple senders at the same
time, the protocol needs to be capable of distinguishing sensors using an ID.
The thermo/hygrometer sensor sends its ID in the second byte. The ID changes
when the battery is removed or when pushing the sensor’s reset button.</p>
<h3 id="checksums-crcs">Checksums (CRCs)</h3>
<p>CRCs are used to ensure that the data has been received correctly. Depending
on the used algorithms, they not only allow to recognize transmission errors
but also in which area of the payload it appeared and in some cases CRCs even
allow to recalculate the correct bit value. These criteria makes it interesting
trying to reverse engineer the CRCs as well.</p>
<p>An indication for a CRC value is a byte that changes as soon as any other bit
in the payload changes. For the exemplary sensor, this is true for the last two
bytes.</p>
<p>The CRC mechanisms being used can be reverse engineered using
<a href="https://sourceforge.net/projects/reveng">CRC RevEng</a> by just feeding the tool with some recorded samples.</p>
<p>Using the example data from the thermo/hygro sensor to decipher first CRC1 in
byte nine and then CRC2 in byte ten outputs the following CRC algorithms that
can later be implemented as explained in <a href="https://barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code">this article</a>.</p>
<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ reveng -w8 -s 9F20CE9E54C225FB38 9F20CE9E54C226FB3B 9F20CE9E56C226FB39
width=8 poly=0x01 init=0x9f refin=false refout=false xorout=0x00 check=0xae name=(none)
width=8 poly=0x01 init=0xf9 refin=true refout=true xorout=0x00 check=0xae name=(none)
$ reveng -w8 -s 9F20CE9E54C225FB387E 9F20CE9E54C226FB3BBD 9F20CE9E56C226FB394D
width=8 poly=0x07 init=0xf9 refin=true refout=true xorout=0x00 check=0x58 name=(none)
</code></pre></div></div>
<h3 id="sensor-specific-data">Sensor specific data</h3>
<p>In addition to the fields mentioned above proprietary RF 433 MHz
protocols eventually contain more data. These are highly sensor specific so
that there is no general approach for reverse engineering those. The data
includes:</p>
<ul>
<li>Sensor type (for generic protocols supporting different sensor types)</li>
<li>Payload length (if sensor sends different message types)</li>
<li>Sensor status</li>
<li>Battery information</li>
<li>Message id (current number of message for repeated transmission)</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Reverse engineering proprietary RF 433 MHz sensors is possible even
with basic knowledge in electronics if the illustrated aspects are taken into
account. Especially for a first preliminary implementation not all the protocol
details are required and it is often enough to start with only the reference
data decoded. More advanced specifics like CRCs can be introduced in a later
step or left out completely if the implementation matches the quality criteria.</p>
fritzcollectd - A collectd plugin to monitor FRITZ!Box routers2014-08-23T00:00:00+00:00https://fetzerch.github.io/2014/08/23/fritzcollectd<p>Recently I set up <a href="https://collectd.org">collectd</a>, <a href="https://graphiteapp.org">graphite</a> and <a href="https://grafana.com">grafana</a> to gather and visualize
statistics for the home network.</p>
<p>At this, I was particularly interested in monitoring my AVM FRITZ!Box router,
especially because I experience some stability problems lately.</p>
<p>The router exposes its status information via UPnP and fortunately there was
already a Python package available which allows to access the data from Python
scripts: <a href="https://github.com/kbr/fritzconnection">fritzconnection</a>. Hence I decided to implement a module that can feed
the data into collectd for further processing: <a href="https://github.com/fetzerch/fritzcollectd">fritzcollectd</a>.
(see the <a href="https://github.com/fetzerch/fritzcollectd">GitHub page</a> for installation instructions)</p>
<p>Since a picture is worth a thousand words, this is how it looks:</p>
<p><a href="/assets/fritzcollectd_grafana.png" data-lightbox="fritzcollectd - A collectd plugin to monitor FRITZ!Box routers" title="Grafana screenshot showing data from fritzcollectd">
<img src="/assets/fritzcollectd_grafana.png" alt="Grafana screenshot showing data from fritzcollectd" />
</a></p>
<p>This dashboard is accessible on <a href="https://grafana.com/grafana/dashboards/713">Grafana.net</a>.</p>
<h2 id="alternatives">Alternatives</h2>
<p>At the time of writing, there were mainly two alternative approaches documented
that are worth mentioning.</p>
<p>At first, there was only a snippet available which is based on a Perl script.
Besides the statistics available over UPnP the example also collects
additional data scraped from the router’s web interface.
Unfortunately even the simple version wasn’t fast enough in my environment to
retrieve the data reliably using a 10 second interval.</p>
<p>Secondly, if you cannot use Python or Perl plugins it is also possible to use
collectd’s <a href="https://github.com/collectd/collectd/wiki/Plugin-cURL-XML-Config#fritzbox-internet-router">cURL-XML</a> plugin to call the respective SOAP actions directly and
parse the results with XPath.</p>