Bluetooth Thermometers

A BLE thermometer

A few years ago, I bought the XIAOMI Mijia LYWSDCGQ which was nice but not really cheap. Its fun characteristic was its ability to broadcast the data (temperature, humidity, battery) as well as having a connected/polled mode.


And another one

Then XIAOMI released a smaller & cheaper version (LYWSD03MMC) running on 3V lithium batteries. Trouble was, they also introduced a "bindkey". Apparently the idea behind was two-fold: To force people to use the official app only and to avoid broadcasting unencrypted data. Well.... whatever...


It wasn't long before someone found a way to intercept the key. The method was awkward at the begining but the process rapidly became easier.

Alternative firmware

Then, the masterstroke came from Aaron Christophel (aka atc1441) who astonished people by releasing an alternative firmware (removing the need of a key) for these device and providing a way to flash them directly from a Chrome browser on a mobile!

Security aspects aside, this is absolutely awesome!!!

ESPHome and OpenMQTTGateway

So I decided to try them and started using ESPHome. Even if the technology is Bluetooth Low Energy, the reaching distance is quite impressive.

ESPHome ecosystem is not bad (far from it) but one needs to define all bluetooth addresses and push a new configuration to the gateway everytime a new thermometer is added (or switched from one protocol to another). I quickly grew tired of it and started to use OpenMQTTGateway instead.

The documentation and the different websites/blog/repositories/libraries make it a little bit messy but the product works quite well and the basic idea is simple:

One board (predominantly ESP8266/ESP32 based) is acting as a gateway between a type of device (RF or BLE mainly -- others are also available) and a MQTT broker.

I'll come back to the RF gateway another time but right now, we are taking about an ESP32 devkit listening to BLE broadcasts and forwarding them as MQTT messages.

The result is something along the lines of:

OpenMQTTGateway_ESP32_BLE/BTtoMQTT/A4C138123456 {"id":"A4:C1:38:12:34:56","name":"ATC_123456","rssi":-30,"model":"LYWSD03MMC_ATC","tempc":21.4,"tempf":70.52,"hum":66,"batt":76,"volt":2.894}

There is nothing to change on the gateway to add new sensors or if you switch from ATC to Xiaomi native protocol (or vice-versa). You only have to select the MQTT messages you want to keep (although there is a white-list feature, should the local laws require filtering).

From an Android Mobile

Aside from the gateway, there is (on Google Play) a handy application called MijiaTemp which is useful to debug and/or check what the sensors are doing.

For information, an new paying one Theengs BLE as appeared recently. I haven't tested it, so I am only mentioning it.

Ecosystem as a diagram

The ecosystem is now:


    Fridge Sensor

    The rain gauge receiver's code, described last time was running happily on a ESP8266 + antenna RXB6 when the next challenge came up:

    While shopping for a Zigbee receiver (more about it another time), I spotted a fridge sensor Telldus (312716) looking exactly like my F007TH sensors but with a cable and measuring temperature only.

    Telldus thermometer for indoor/outdoor


    Honestly, the information gathered on different sources about these was totally unclear but I decided to buy one for my chest freezer.

    And... obviously, the casing is identical BUT the protocol (F007TP here) is absolutely not compatible with the F007TH. To be clear: they have nothing in common!

    Yet, this new sensor was recognised by my RTL-SDR adapter running rtl_433 (but with the wrong temperature -- according to the source code there may be a conflit bitween WH2 & WH5 which are part of the same family).


    It appears that the protocol was described more than 10 years ago by Luc Small on his blog, so at least the heavy lifting was done. I only had to use the decoding and CRC calculation in my own code.


    As I didn't want to requisition a specific ESP8266 just for one sensor and because it was in the same area as the rain gauge, I decided to merge the decoding functions even if there is very little in common between these 2 applications.

    It is unfortunate that the WH2/F007TP protocol doesn't have an easy synchronisation preamble but at least the rain gauge do, so the main loop now checks if there are a number of ~500ns pulses followed by one ~1500ns or if it detects one ~7500ns pulse.

    If it's the latter, then it records 64 pulses then calls the rain gauge decoder. If it's the former, then it records 40 pulses then calls the F007TP decoder.

    Overall, the routing mechanism is similar to the solution used for 433Mhz remote sockets.


    The code is available online (Plateform.IO format this time).

    Ecosystem as a diagram

    This now brings the ecosystem to:


    Rain Gauge

    Having bought a Wireless Rain Gauge from Pearl Diffusion, and since they looked alike, I was hoping that even if the model number was different, its protocol would be similar to the TFA DROP 47.3005 which is implemented/documented by rtl_433.

    It turns out that they are similarities (they might come from the same factory) and also quite a few differences.

    • For reference, here is the inFactory FWS-275 (aka NX-6331-675):


    • And here the TFA 47.3005 (aka TFA 30.3233.01):

    TFA 47.3005

    Looking for the data


    I decoded several protocols in the past, mainly using dumps of timing on Arduino serial port. Here, the author of the TFA device's code (helped by one of the maintainers of rtl_433) gives a few clues in how to proceed rapidly in the issue associated.

    rtl_433 -A

    manages to collect the format of the signal and a way to display some formated information:

    rtl_433 -X 'n=rain,m=OOK_PWM,s=996,l=2700,r=2684,g=0,t=0,y=7352'

    The signal seems to be composed of 2700µS and 970µS pulses with 7340µS synchronisation pulses. One suprising thing is that it doesn't seem to be regular (for example long HIGH + short LOW or the opposite). It is a mix of long HIGH + short/long LOW or short HIGH + short/long LOW). But it we take into account only the HIGH side, it doesn't matter much.


    When decoded (PWM slicer), the first chunk is always different (values divided by 2), probably due to a shifted bit. The second and the third are almost identical, except the last byte. Best is to ignore it and see.

    bitbench is another handy tool to carry on with the decoding.


    One (obvious) difference between the two gauges mentionned above is that the one I own also a outdoors temperature display, so the protocol has to transmit the value.

    The 2 first bytes never change except after a change of batteries on the outdoor unit, so it is certainly a random ID.

    The third byte follows the pattern 00, 02, 04, 06, 08, 0a, 0c, 0e already found in the TFA unit. Like on the TFA, bit 7 is the battery indicator (tested using a variable power supply to lower the voltage) and bit 6 a reset indicator.

    The fourth and fifth bytes seem to be the counter of the bucket tips, using the same weird initial value (-10). More about it later

    The sixth and seventh values are the temperature. Since, they didn't really match the Celcius display, I switched the display to Farenheit and in this case a change of value is also a change of display. This mean the transmission is in Farenheit (like in the F007TH protocol) but the encoding is diffent. After toying a bit, it appeared that the format is 16 bits Little Endian and that the value is in tenth of degrees Farenheit with an offset of 900.

    Last but not least, the checksum... I was expecting something like on the TFA unit (it took me a while to understand zuckschwerdt's answers to be honnest) but after trying the referenced tools it turns out that the checksum is just that... a sum of the first 7 bytes!

    All was fine... except that the main reason of this apparatus is to mesure the amount of rain, and there was not an obvious link between the counter values and the display!

    Knowing that the base is 25.4mm (top of the tube on the display), it is almost certain that the mesurement is with imperial units too.

    After tiping the bucket (by hand) a few hundred times, it seems that the value is 1 tip = 0.0425 in of rain. Converted in metric, this gives 1 tip = 0.108 mm.

    How on earth did they managed to select this kind of value??? Well never mind...

    Page 1 / 31 »