Archive for December, 2012

AcuRite Acu-Link Internet Bridge (09150TRX): Accessing Local Data

AcuRite has been threatening the release of this product for well over a year, and it’s finally out.  Being a bit obsessive about data in and around my home, (check-out my IP Thermostat install and custom interface) I *HAD* to have one of these.

The “idea” is that you buy the Internet Bridge from AcuRite, and either with your existing sensors from their other products (many are compatible), or with the purchase of additional sensors, live data is transmitted to their “MyBackyardWeather” web site and you can view the data while you’re away and track trends etc.  They even offer a “forecasting” widget.

To get started, I ordered the internet bridge, a tower sensor, and a floating pool sensor.   The bridge is 80 bucks, and the sensors are very reasonably priced at ~ $8 for the tower sensor and $20 for the floating sensor.  They’re shipping is a bit slow, but everything arrived well packed and the build quality of all the devices is quite good.  The tower sensor supplies both temperature and humidity data, and honestly 8 bucks for one of these is a great price.   You’d be hard-pressed to buy just the sensors for an arduino or pi build for that money.

The bridge has a flip-up antenna and two connections, one RJ-45 for a network cable, and one jack for the power plug.  Since the protocol and any real info about how the bridge “talks” to their web site is unpublished and unknown, I figured I’d give it the full packet capture and analysis treatment.   To do this, I added a static DHCP IP mapping for the MAC address of the Internet Bridge to my router/firewall so as soon as it came online, I’d know the IP address.  The MAC address of the Internet Bridge can be found right on the bottom of the unit.  This MAC address is also the “ID” that AcuRite uses to associate your data sources with your account on MyBackyardWeather, but I’ll get to that later.  After setting up the static IP mapping, I enabled packet capture for any TCP/UDP connections from that IP out to the net.  Time to plug it in!

Once connected, the Internet Bridge did two things:

1) started sending sensor data to the Acu-Link web app

2) started downloading new firmware line-by-line with a POST for each new line as one completed

I pulled the connection before the firmware update could complete (just in case), and started to take a closer look at the data sent to the Acu-Link web app via the packet capture.  To my surprise, it looked like the sensor data was being sent  cleartext in a simple HTTP POST, one POST for each sensor in range of your Internet Bridge.  Next, I tried reconnecting the bridge, but this time with WAN access blocked, and ran a full port scan.  Only port 80 was open, and a visit to the Bridge’s local IP in a browser yielded a simple status page informing me that a firmware update was in process.   In the hope that more useful data would be presented when not in the “firmware-update” state, I permitted WAN access and let the firmware update complete.

Once the firmware update completed, the simple status page showed the sensors in range, their signal, and the option to send a POST to the bridge to toggle the LED’s on and off, but no actual sensor data was shown, and there’s nothing to click on, save for the LED toggle.  I tried forcing an error that might yield useful information with various POST’s and GET’s to the simple web interface on the Internet Bridge, but never got more than a 404 or the same status page.

Since querying the data directly from the Internet Bridge seemed unlikely without new information, I returned to looking at the data the Internet Bridge POST’s to Acu-Link, which was a little different now after the update.  The actual variables had additional digits and letters, but the values were still cleartext within this group of digits.  Here’s what the HTTP POST looks like when my Internet Bridge sends data for my tower sensor:

id=############&sensor=11423&mt=tower&humidity=A0590&temperature=A018000000&battery=normal&rssi=4

. . . . . let’s break it down and look at each piece:

id=############

I obfuscated the actual value here, but this is the MAC address of your Internet Bridge

sensor=11423

This is the sensor identifier, and appears to be unique for each sensor, though I only have one tower sensor, so I can’t be sure

mt=tower

This is the type of sensor, probably stands for “model type” if I had to guess

humidity=A0590

The 3rd-5th digits are the relevant ones here, with a decimal point required between the 4th and 5th digits, yielding a value of 59.0 for humidity

temperature=A018000000

Again, the 3rd-5th digits are the important ones here, but the 2nd digit serves the role of  denoting a positive or negative reading as well.  If the reading is positive, it’s a “0″, if it’s negative, it’s a “-”.  This value is also in Celsius, so if you want Fahrenheit, you’ll need to convert it.

battery=normal

This one seems fairly obvious, but I didn’t try inserting an older set of batteries to see what it reports when not “normal”

rssi=4

This denotes the received signal level for the specific sensor, and varies from 0-4

All of this data is super-easy to parse in just about any language.  I’m no programmer, but I’m “dangerous” with BASH scripting, so I figured I could probably whip something up, but how do we get the data if you can’t request it?  TCP dumps are nice for post-analysis. but a pain to do anything with real-time.  An HTTP proxy server with some customization would be an option to intercept the data, as well as IDS with some custom rules that took actions like parsing the data and writing out values that could be sucked up from something else, but I had something even “dirtier” in mind.

Let’s dig into what happens for data to get from the Internet Bridge to Acu-Link’s site from power-on to data.

1) The Internet Bridge powers up and gets an IP, gateway and DNS servers via DHCP (your router typically hands out this info)

2) The Internet Bridge resolves “http://www.acu-link.com” using DNS

3) The Internet Bridge starts making regular HTTP POST’s to the Acu-Link web service at: “http://www.acu-link.com/messages”

4) The Acu-Link web service responds back to each POST from the Internet Bridge with a SUCCESS, and the current firmware version.  (presumably if the FW version is higher than installed on the Internet Bridge, this is what initiates the downloading and install of new firmware).

Knowing the above, I figured the easiest way to get sensor data locally would be to “trick” the Internet Bridge into sending it to me instead of Acu-Link.  To do this, I configured my router/firewall (I use pfSense) to “override” www.acu-link.com by having the local DNS service resolve the hostname to a local IP on my network instead of the “real” IP on Acu-Link’s network.   If you can’t override hostnames or zones on your router/firewall with the local DNS service, or your router/firewall doesn’t offer a local DNS services, there’s several freeware DHCP/DNS software pkgs that you could run on a PC on your network to accomplish that same thing.

Now that I have my Internet Bridge sending it’s data to an IP on my network, I needed something to receive it.  I wrote a simple BASH script to replace the functionality of the “messages” web service at Acu-Link:

#!/bin/sh
echo “Content-type: text/html”
echo

echo “SUCCESS”

POSTDATA=$(cat | tr -d ‘ ‘)

FIELD=1
while [ $FIELD -le 15 ]
do

DATA=$(echo $POSTDATA | cut -d”&” -f$FIELD)
VARIABLE=$(echo $DATA | cut -d”=” -f1)
VALUE=$(echo $DATA | cut -d”=” -f2)

if [ $VARIABLE = id ]
then
ID=$VALUE

elif [ $VARIABLE = sensor ]
then
SENSOR=$VALUE
echo “$VARIABLE=$VALUE” > ../weather_data/”$ID”_$SENSOR.txt

elif [ $VARIABLE = temperature ]
then
WHOLE=$(echo $VALUE | cut -c 2-4)
DECIMAL=$(echo $VALUE | cut -c 5)
CELSIUS=$(echo $WHOLE.$DECIMAL)
VALUE=$(echo “$CELSIUS * 1.8 + 32″ | bc -l)
echo “$VARIABLE=$VALUE” >> ../weather_data/”$ID”_$SENSOR.txt

elif [ $VARIABLE = humidity ]
then
WHOLE=$(echo $VALUE | cut -c 3-4)
DECIMAL=$(echo $VALUE | cut -c 5)
VALUE=$(echo $WHOLE.$DECIMAL)
echo “$VARIABLE=$VALUE” >> ../weather_data/”$ID”_$SENSOR.txt

elif [ $VARIABLE = battery ]
then
echo “$VARIABLE=$VALUE” >> ../weather_data/”$ID”_$SENSOR.txt

elif [ $VARIABLE = rssi ]
then
echo “$VARIABLE=$VALUE” >> ../weather_data/”$ID”_$SENSOR.txt

else
sleep 0
fi

(( FIELD++ ))

done

This reads the raw POST data, then steps through “if” handlers I kludged together to look for each data type.  Grabbing additional data from other sensors would be done just be adding additional handlers for each data type (wind speed, rainfall, etc.).  The script then dumps the data out to files named based on the MAC address and sensor ID’s to a writable directory. I can then query this data from other scripts, or POST it elsewhere (like weather underground, etc.).  Personally, I have a whole web app I’ve written for my IP thermostat that I WAS using external data for the display of outdoor temp/humidity.  Now I’m using ACTUAL data from my AcuLink sensors.   The above script returns just a simple SUCCESS to the Internet Bridge, but the bridge doesn’t seem to care, it just keeps on truckin’ sending more data.  A side-effect to this setup is that your bridge won’t update it’s firmware (possibly breaking any reliance you have on the current behavior) unless you remove your custom DNS entries and let it talk to the “real” Acu-Link web service.

Now, you could stop there and call it a day, but the obvious con to this setup is that Acu-Link’s MyBackyardWeather no longer gets your weather data, and the out-of-the-box graphing, weather forecast’s, mobile apps, etc. are pretty cool.   With a SIMPLE addition to my script, I added the original functionality back in by using curl to POST the data to the “real” web service (in addition to stepping through it locally).  Here’s the addiiton:

curl -d “$POSTDATA” http://acu-link.com/messages/ > /dev/null

Notice I used “acu-link.com” instead of “www.acu-link.com”.  This means our override of the www hostname won’t affect our scripts ability to reach the “real” web service.  A quick visit to MyBackyardWeather confirmed it was again getting fresh data.

In summary, AcuRite makes some great weather hardware, and their Internet Bridge and associated sensor’s are no exception.  I wish they would have built this system a bit more “open” and permitted a simple GET request to the bridge for sensor data, but this product is also very new, and they are very encouraging to their users to suggest new features, etc.  There is even mention that they may offer the ability to query this data directly in the future, but in the meantime: hack-on :P