Category: Electronics



The USR-HTW Unit


The USR-HTW unit is a US$40 wifi enabled temperature & humidity sensor being produced in China. Out of the box it has an easy to use webpage to configure the wireless settings and runs a TCP server on port 8899. On connecting to this port, every 20-21 seconds it sends an 11 byte data string containing the current temperature and humidity sensor value in an easy to decode format.


I’ve decided to write this post with a considerable amount of detail, just so some users new to this can get a grasp of how I approached the problem. Whilst I admit I don’t see this as a challenge, as someone great once said “Nothing is hard when you know how to do it!”.

The Unit

This sensor is just one of the many wifi enabled devices starting to show up at very reasonable cost from the usual channels (AliExpress, eBay). It typically seems to be running at about US$40 per unit, and availability slowly seems to be improving. I ordered my unit a few weeks ago when I first spied them, thinking they looked like a good unit suitable for mounting on the wall for that distributed thermostat project that I have been meaning to get around to for awhile…

Anyway, the unit finally arrived today and I must say that I am actually pleasantly surprised at the build and assembly quality. This one even looks like the board was cleaned after the surface mount assembly process! The only thing to be somewhat careful of when opening the case was the RF cable running to the wireless antenna. The antenna uses a standard U.FL connector, so upgrading would be easy if required – just remove a dab of hot glue.

Inside the rear cover.

Inside the rear cover.

The Wifi Antenna

The Wifi Antenna

For those that are interested, the sensor is the AM2302 (DHT22) connected to an STM8S105 microcontroller, a Holtek HT1621B LCD Controller, and power is provided by an M2303ADN voltage regulator, allowing the board to accept an advertised 5-24V in. Wireless comms is handled by a USR-WIFI232-T module.

After the obligatory teardown, it was time to power the unit up for the first time, power connection is easy with screw terminals on the back. When the unit initially powers up, the wifi module acts as an access point, allowing easy web-based configuration of the module. Simply connect your favourite wireless-accessing device to the network broadcast as USR-HTW, open a browser and go to, enter admin/admin and you are greeted with the configuration interface. If your native language is closer to English, there is a link provided with a translation. I must admit, I found that sometimes it was necessary to refresh the page a couple of times to get it to load, but after not too long I had the device on my resident wifi connection.

Factory Software

Smart IOT

My first point of call was to test the device with the manufacturer software “USR LonHand Setup Software”, found at This install was pretty seamless, after guessing my way through the Chinese installer. It extracted a single file into the Program Files folder, and after running this program it successfully found my sensor, and reported to me it’s current Temperature and Humidity value. It’s at this point that it is probably pertinent to mention that a brief press on the “Refresh” button on the front of the unit sends an update to the software as well. Like the web interface, there is an English version of this user interface should you click on EN in the bottom left hand corner. It’s also possible to change the name of both the Temperature and Humidity sensors by clicking on the text just to the left of their value.

Satisfied that the device worked to the specifications, it was really time for the fun to begin! Whilst there was a considerable amount of information available about the AT commands used in the module, there wasn’t any available about the actual protocol that transfers the temperature. My aim was to be able to use this for data logging with the minimal amount of effort possible, so I wanted to run with completely default parameters on the unit itself. If it’s good enough for them, it’ll do for me!

Protocol Discovery

I downloaded and fired up Wireshark, my packet sniffer of choice and setup a capture on my main network adapter. Of course, this results in a huge number of events so I set a filter of “ip.src== or ip.dst==” (where was the IP address of the USR-HTW unit on my network, found from DHCP logs or the device URL easily accessed from clicking “Device URL from “Smart IOT” software.). This results in a lot less traffic.  I set a capture to begin, then clicked the button to refresh the devices list. After my sensor appeared, I selected it and waited for the temperature to display.  This yielded roughly the following events:


The single UDP packet is a response to a UDP multicast broadcast looking for devices sent on Port 1901. This is handy for the future, but not essential at the moment, and certainly won’t contain data. Looking through the rest of the TCP packets, the first thing to pickup is that comms seem to be occurring on ports 80 and 8899. Port 80 will be the webserver, though what function it plays in this I haven’t looked at. Port 8899 sounded much more interesting, so I had a poke through the packets. There was a few with data, though nothing easy to discern. The only ASCII characters of note were the name of the sensor that I had set earlier in the Smart IOT software. At this point I had the idea to setup another trace session in Wireshark, this time waiting until after the device was found in the software to begin capturing packets whilst I pressed the “Refresh” button on the unit repeatedly. This was much more fruitful, with a single pair of packets starting to become far more prevalent – exactly what I was hoping for.


So based on this, it looks the unit will send the current data every time it is updated to any listener that is connected on port 8899. Bingo. Examining the packet data yielded a rather cryptic “aa:55:00:06:00:c0:01:e2:00:f9:a2” that varied with temperature and humidity, so it seemed pretty likely that this was the data I was looking for.


Data Decoding

My first point of call was to setup a client in my programming language of choice, LabVIEW. It’s deliciously simple to setup, consisting of opening up a TCP listener, reading data from the client and closing the listener. See below for my test code. In this case it was a client listening to Port 8899 on, waiting for 11 bytes to be written. The real question that I needed to answer at this time was if all those TCP packets that I had ignored earlier were used to configure the device, or if they were just used to download device information to the Smart IOT software. With great delight, the first time I executed my LV code I was greeted with 11 bytes of text, no configuration required!

With a few more minutes of coding, I had decoded this 11 bytes represented as a string into an array of bytes, displayed in both Hexadecimal and Binary. Now it was time to crack the code!

With some basic experiments using a broad spectrum localised humidity generator (my breath) and a low entropy temperature source (a can of freezer spray) it quickly became obvious that only about 5 of these bytes contained any varying data. The rest seemed to remain constant all the time, so they were subsequently ignored. From this initial examination it looked like Bytes 7 & 8 seemed to be linked to the Humidity, Bytes 9 & 10 seemed to be linked to the Temperature and Byte 11 seemed to be linked to both (a checksum perhaps?).

Having never worked with a DHT22 sensor before, I was not familiar with their data protocol and representation, a quick Google yielded this helpful resource, with information on how the data was read out of the protocol. Four bytes of data, with a CRC check. I don’t believe in coincidences, so a few minutes later I had some code that would decode the 4 bytes of data provided by a DHT22 into Temperature & Humidity respectively. I plugged in the values from the datastream and it worked! The only value that didn’t match up was the CRC value, so a quick check of some basic checksum approaches calculated it out to be the sum of the first 10 bytes, plus 1.  Byte 7 is the MSB, as is Byte 9.





I also finally measured the readout frequency, and on this particular unit it reports data about every 20-21 seconds, or every time you push the update button.

Finally, I did register an account using the Smart IOT software, but it didn’t gain me any useful configuration settings (such as refresh rate).

Note: this was all done with firmware version V1.0.04a. I don’t know if this is likely to change things in the future or not.

EDIT: I’ve just tested out some Python code, you can find it here:

Continuing on from my previous post where I laser cut a helical antenna for basic radio astronomy, I wanted a way to mount this. Whilst most people that are into these hobbies seem to have  a mast that they can dump another antenna on, I didn’t. Also, I rent so adding a mast wasn’t really a great idea. Also, I’m impatient and have been known to be a bit lazy.  Finally, because I am not receiving terrestrial signals, the antenna does not need a clear view of the horizon, just a clear view of the sky. An idea was thus born.

My logic was along the lines of “take antenna, put on post, attach giant paperweight”. Nice and simple, as long as I could lift said paperweight – it would be portable and easy to work with. Questions then included, what sort of post and what sort of paperweight? The post I wanted to be galvanised so it could handle a considerable time in the outdoors, and the paperweight I wanted to be easy and cheap – hence, premix concrete!

A quick visit to Fyshwick (the home of all things useful industrial in the Canberra region) and I returned with:

  1. ~800mm long, 2″ square, galvanised fence post ($4,  an offcut – check out MetalMart)
  2. a 2″ end cap to make it look swish ($2.50, MetalMart)
  3. a collection of M8 galvanised bolts for reinforcing (about $4, Bunnings)
  4. a 79c plastic bucket ($0.79, Bunnings)
  5. and a bag of premix concrete ($5.50, Bunnings)

Not bad for less than $20.

The bucket, and a drill for scale.

The bucket, and a drill for scale.

The plan was to fill the bucket with concrete, put the post in after  mounting the bolts for reinforcing, let the concrete go off and finally have a portable antenna mount! My calculations based on typical concrete densities were in the ballpark of 24kg for a 10L bucket, so I bought 2 bags just in case. The final product weighs in at about 22kg including the post – pretty good in my opinion, given how much concrete densities vary.

The post and bolts, with holes drilled.

The post and bolts, with holes drilled.

The post with bolts mounted, held in position to demonstrate the "reinforcing".

The post with bolts mounted, held in position to demonstrate the “reinforcing”.

Anyway, I’m happy with the results – I now need to mount the antenna and start looking for a signal!

The post in place, professionally supported and awaiting the concrete to harden.

The post in place, professionally supported and awaiting the concrete to harden.

Finally, a photo of the finished product:

The finished product, awaiting antenna.

The finished product, awaiting antenna.

The process for generating fabrication files is the same for nearly all Chinese fab services in my experience, and I just wanted to share some of the configuration settings that I use in Altium, hopefully easing the process for others.

Altium requires two operations to output the required files for all boards, these settings have been tested exhaustively with Mitch @ Hackvana.

First, the NC Drill File:

Next, the Gerber Files:




Please note: The layers output shows me exporting Mechanical 2, not Mechanial 1. Due to a few problems I generally use Mechanical 2 for board outlines. This file must be renamed prior to zipping. 

After both of these Fabrication Output’s have been run, it is simply a matter of navigating to the output directory, renaming the GM2 file to GM1 if required, selecting the Gerbers and the .TXT drill file and zipping them all together.

If further information is needed, please get in touch and I will add some more details!

Happy Gerbering!

Some of the undertakings demonstrated on this website are dangerous and should not be attempted by unskilled persons.
I take no responsibility for any damage done to persons, property or relationships as a result of this information.
Information is provided on the understanding that it is correct, but without any such warranty.
Any undertakings based on the contents of this site are done so at your own risk.