Digging in to the La Crosse C84428 Weather Station

For Christmas I received a home weather station which has a few IoT type features. Of note are: pushing sensor data to a La Crosse hosted application, NTP based time sync, and collection and display of weather report data from the National Weather Service APIs.

What I want is to be able collect all the sensor data for myself so I can make my own graphs.

With a Raspberry Pi I’ve setup a man-in-the-middle access point that I’ve connected my test phone and weather base station to.

On the Pi I’m running mitmproxy with iptables rules to intercept traffic to port 80 and 443 to the proxy.

Doing this I’ve noted the following things:

  1. Internet connectivity is powered by an ESP8266
  2. All of the APIs that it interacts with are hosted on Google Cloud (more of this to come in a future blog post)
  3. The ESP8266 does *not* perform a proper SSL certificate verification before shipping its sensor data.
  4. Sensor data gets shipped to the server in what looks like a string of hex data. Example: 2B52810E24B01D1C or 0BE6250EAAAAAA000AAAC6

My guess is that a simple https server with a self-signed certificate could easily intercept and maintain functionality through to the hosted API.

The primary challenge now is decoding the hex data shipped to the server.

Temperature / Humidity Sensors

I logged a pile of data and found some related work (note this one even includes the constant I discover myself later on).

The data appeared to be hexadecimal numbers and based on other prior decoding efforts I expected the temp to be transmitted in Celsius.

Here is one Data string from my sensor with my analysis so far

2B528108295020D7
2B5281 08 295 0 20 D7
Station ID Counter increments by two until 0E then rolls over Temp data Padding Humidity CRC-8

This is my guess for structure.

This data corresponded to a temp of 79F and 32% humidity.

Getting the Temp.

295 hex converted to base-10 is 661. 79F in is 26.1C.

(26.1*10) => 261

661 – 221 = 400

Base10 temp data = (Tc*10) + 400

Convert the base10 value to hex

I validated this conversion is correct against another reading.

Getting the humidity

This is very straightforward. See the ’20’ byte above. That translates directly to 32 which was the reading at the moment.

Checksum (CRC-8)

This took me a while even though I found the the final answer on a post about the TX-29 protocol. I struggled to find an implementation of CRC-8 which I understood and could get it to compute the right answer.

I was able to use the reveng tool to accomplish a successful CRC check. I ran the following command:

$ ./reveng -a 4 -w 8 -b -p 31 -c 2B528108295020
d7

Note I stripped the last to characters off the original data from above and that the command returned d7 as I expected.

This means that its a CRC calculation with 4 bits per character, 8 bits in its register, big-endian, and uses a polynomial of 31.

My next step for this is to write a python implementation to parse these packets.

Comments are closed.