[JSR223][Jython] USR-R16-T 16-channel Web Relay Lonhand Protocol reverse engineered

The USR-R16-T is a 16-channel web relay sold on AliExpress and other places. I bought one, and spent hours building it into a box with 16 power outlets, all the while assuming that there was documentation available, and that it would be easy to control with a simple telnet-style protocol. Boy, was I wrong! I’ve wasted hours trying to follow broken links to get the Lonhand Protocol documentation… no dice.

Finally, now that I’ve gotten into openHAB and learned Python, I realized what I needed to do – so I reverse engineered the control protocol, with the help of wireshark. I’m posting this here hoping that google will help other people who are trying to find out how to control this relay.

I did not bother with reading the state of the relay – I was happy to set the state of each relay, one at a time. openHAB will be maintaining the state anyway.

Here is the solution.

Python script:

from core.rules import rule
from core.triggers import when

from core.log import logging, LOG_PREFIX
log = logging.getLogger(LOG_PREFIX + ".ruletest")

import socket
import time



def LonhandPower(strIP, strPassword, iChannelNumber, bPowerState):

	command=bytearray.fromhex("55 AA 00 03 00")
	command.append(2 if bPowerState else 1)
	command.append(iChannelNumber)

	iChecksum=0

	for x in range(2,7):
		iChecksum += command[x]

	command.append(iChecksum)

	sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	sock.connect((strIP,8899))
	sock.sendall(strPassword+"\r\n")
	sock.recv(256)
	sock.sendall(command)
	sock.recv(256)
	time.sleep(0.05)
	sock.close()
	del sock


@rule("Kvm1")
@when("Member of Kvm1 received update")
def KvmUpdateHandler(event):
	
	iChannel=int(event.itemName[-2:])
	bState=True if event.itemState==ON else False

	LonhandPower("172.22.22.232","admin",iChannel,bState)

Items:

Group Kvm1				"KVM 1" <poweroutlet>

Switch Kvm1_01 	"Unit 01" 	<switch> (Kvm1)
Switch Kvm1_02 	"Unit 02" 	<switch> (Kvm1)
Switch Kvm1_03 	"Unit 03" 	<switch> (Kvm1)
Switch Kvm1_04 	"Unit 04" 	<switch> (Kvm1)
Switch Kvm1_05 	"Unit 05" 	<switch> (Kvm1)
Switch Kvm1_06 	"Unit 06" 	<switch> (Kvm1)
Switch Kvm1_07 	"Unit 07" 	<switch> (Kvm1)
Switch Kvm1_08 	"Unit 08" 	<switch> (Kvm1)
Switch Kvm1_09 	"Unit 09" 	<switch> (Kvm1)
Switch Kvm1_10 	"Unit 10" 	<switch> (Kvm1)
Switch Kvm1_11 	"Unit 11" 	<switch> (Kvm1)
Switch Kvm1_12 	"Unit 12" 	<switch> (Kvm1)
Switch Kvm1_13 	"Unit 13" 	<switch> (Kvm1)
Switch Kvm1_14 	"Unit 14" 	<switch> (Kvm1)
Switch Kvm1_15 	"Unit 15" 	<switch> (Kvm1)
Switch Kvm1_16 	"Unit 16" 	<switch> (Kvm1)

Hope it helps somebody. :slight_smile:

3 Likes

Now that’s a cool device. I don’t know that I’d trust it with mains voltages though. I have one of those boards without the onboard smarts and there are no cutouts between the traces, and I’m fairly sure those screw terminals are not rated for mains isolation.

Would you be willing to keep poking around with wireshark to get the read command and response packets figured out?

I don’t remember if it has cutouts between the traces, but other web relays do, I think this one probably did as well – but it’s not accessible so I cannot check. I only have one of this type of web relay, and it’s inside here:

In case anyone notices, plug #16 (the one on the right side) is in fact properly grounded, by me having inserted a grounding rod into the “french hole” of the schuko plug!
image

Sure, if you can think of a good reason to.

The only reason I can think of would be to still use the original app in combination with openHAB control… and the app is quite frankly abysmal.

It looks nice enough:

What the image doesn’t show is:

  1. It (lightly) encrypts the password in the ini-file, using a formula that is somehow time-based so it changes every couple of months, thus suddenly complaining “incorrect password” and forcing you to re-enter it … despite the fact that it then goes right ahead and sends it in plaintext over the network
  2. It lets you name the outlets, very nice feature, and it even stores the name in the web relay, and transfers it to the app when you connect, and then, probably due to a race condition in the app, neglects to actually display the name and instead displays “No name”… I see the names in wireshark but they’re not displayed in the app, except for one or two times out of hundreds of launches when it randomly happened to work. Because the names aren’t displayed, and the devices are not otherwise numbered, i literally had to slowly scroll the list while counting with my index finger to get to the correct device in the middle of the list and not make a mistake…

Add to that the fact that in order to receive the state, the script would have to maintain the connection to the device instead of just hit and run the way it is currently, and we’re talking at least a couple of hundred lines of code instead of twenty.

So, willing? If you can think of a good reason then yes, otherwise I will pass and spend that time on something more productive, because I cannot for the life of me think of a reason why I would want to continue using the POS app that I just managed to remove the need for just by controlling things from openHAB instead. :slight_smile:

If you don’t already have an USR-R16-T and you’re looking to acquire a web relay then for the love of god don’t buy this particular one. It works, but you can do better. Get the one that looks like this instead. If it has a name, it’s “ZMWEBRELAY”. I have 6 of this kind:

Stock photo:

Own photo:

I figured you’d want to see the underside. This one is great, it’s reliable, reasonably well documented, and supports several ways of accessing it out of the box!

You can get it from here and from many other places.

Also… I used to think web relays were so cheap. The ZMWEBRELAY is $35, and the USR-R16-T is $55.

But, an 8-channel relay module + a NodeMCU (ESP8266) is $6 and you won’t even need a network cable since it supports wifi. It’s quite insane, really.

If you’re looking for a web relay to AVOID LIKE THE PLAGUE, here’s one:

There are 16-channel variants as well but the same microcontroller board. This microcontroller randomly freezes up when you send commands to it, and so is completely unusable. Luckily the microcontroller and relay boards are separate, so I’m using the relay board with another MCU.

Where did you get that case? AliExpress as well?

Not having to set the relays to know their state, and to be able to confirm the requested action was completed.
Password encryption isn’t an issue, there are plaintext passwords in other openhab config files.
I don’t think we would need to keep a connection alive. A periodic poll would suffice, with the ability to call it manually to force a refresh.
Setting and getting the names probably won’t be needed for openhab, so no need to fuss with that.

I also have no immediate need for a device like this, but can definite see a use for it. If you don’t have the time then don’t bother. I have the impression reverse engineering it’s command protocol took you long enough lol.

That one also has the same minimal cutouts as my plain 16 relay board. The separation between the relay common and signal pins is good, but there are no cutouts between to high voltage traces to reduce the chance of arching. I don’t have any example images on my phone, but the sonoff devices (while not certified) have better isolation.

1 Like

That one was bought at the local building materials store, from the electrics aisle.

image

It’s just a standard gray plastic box. Took a lot of work with a dremel + a lot of hot glue to get the sockets in there. :slight_smile:

Okay good point, it would make sense to verify that the requested action was completed. I’ll get to it one day :).

Counting from when I first deployed this relay for use, until I completed the reverse engineering, it took 7 months. On the other hand, if I had to do it again, it would only take a few minutes, now that I know how. That “Follow” feature in wireshark is pretty crucial, ain’t it. :wink:

I see what you mean now.


Didn’t know that was a thing. You learn something new every day.

Man I wish we had stores like that where I live.

Indeed. AC power will arc very easily across FR4 PCBs compared to open air. Even such a narrow air-gap as that Sonoff Basic has will offer magnitudes more isolation despite the bare solder.

Now don’t take that to mean I think your box is going to catch fire. If the AC arcs it’s because something went wrong and the current had to go somewhere. If you want to add a bit of protection you could get some Silicone Conformal Coating and put a coat or two on the traces for the relay contacts. I have some MG Chemicals stuff that says it provides about 150KV of isolation at 0.15in thickness.

1 Like

USR products seem generally well made and reliable (I have used a few gateway products) but like anything else you are at the mercy of software devs.

It’s surprising/disappointing that they don’t offer some local control standard. I note that their current 4- and 8-channel roughly equivalent products support Modbus, but they’re built around a different processor.

There is a Lonhand Development document referenced from some places, but all the links to it are dead. From here for example:
http://www.zeedless.com/shop/index.php?route=product/product&product_id=51

I have spent hours and hours trying to find it through internet archive, chinese search engines, their web sites, even put in a support request on their site, and I have absolutely nothing to show for it. No response after several months.

There’s no reference to the USR-R16-T on their site either, it’s like it never existed… although several other related files are mirrored in other places, just not the development doc.

For the time you’ve spent on it I wonder if writing new software that uses modbus wouldn’t have been easier in the end. When I get to the point where I need devices like this, that’s probably the direction I’ll go.

1 Like

In hindsight, yes.
During the journey I found out there IS actually modbus software for this device. I haven’t gone that route, but that would have been my next step if I weren’t able to reverse engineer it. At this point the problem is solved for me:

1 Like

In case anyone needs the modbus firmware, it is here (as of 2019-06-19)

If the software is no longer available, try my own dropbox mirror of all the USR-R16-T related software I have: https://www.dropbox.com/sh/b8j1cpl185egofo/AACVP6VUB-AhoEMDGOs737haa?dl=0

…and in case the blog post is missing, here’s a copy for posterity:

Browsing Google didn't give me much infor but using Baidu (the chinese Google) i had more luck and found a [tutorial in chinese ](http://www.gu-wen.com/Faq/455.html)explaining how to flash that board with another firmware of the manufacturer in order to make it work with the [Modbus](https://fr.wikipedia.org/wiki/Modbus) protocol who is more likely to be implemented in the home automation softwares.

Basically those are the steps to achieve that :
Setup the board maintenance software
Download the firwmare mentionned in the tutorial : USR-TCP232-M4-V3013(V1.1.3)-20170208.bin
Upload the firmware on the board with the software
Reset the board contacting the points as shown in the tutorial
After reset the board is recognised by the software as USR-TCP232
Configure the board with the appropriate values to let it work in modbus as shown in the tutorial
To validate the configuration you can test it, modscan32 is a good tool for that, OpenHab can be used aswell to test the configuration.

Here’s a basic OpenHab configuration sample to use the relay board’s switches, you can later on apply scripted behavior with your inputs :
OpenHab/conf/items/modbus.items

Switch Bouton1 "Bouton 1" (ALL) {modbus="relayBoard1:0"}
Switch Bouton2 "Bouton 2" (ALL) {modbus="relayBoard1:1"}
Switch Bouton3 "Bouton 3" (ALL) {modbus="relayBoard1:2"}
Switch Bouton4 "Bouton 4" (ALL) {modbus="relayBoard1:3"}
Switch Bouton5 "Bouton 5" (ALL) {modbus="relayBoard1:4"}
Switch Bouton6 "Bouton 6" (ALL) {modbus="relayBoard1:5"}
Switch Bouton7 "Bouton 7" (ALL) {modbus="relayBoard1:6"}
Switch Bouton8 "Bouton 8" (ALL) {modbus="relayBoard1:7"}
Switch Bouton9 "Bouton 9" (ALL) {modbus="relayBoard1:8"}
Switch Bouton10 "Bouton 10" (ALL) {modbus="relayBoard1:9"}
Switch Bouton11 "Bouton 11" (ALL) {modbus="relayBoard1:10"}
Switch Bouton12 "Bouton 12" (ALL) {modbus="relayBoard1:11"}
Switch Bouton13 "Bouton 13" (ALL) {modbus="relayBoard1:12"}
Switch Bouton14 "Bouton 14" (ALL) {modbus="relayBoard1:13"}
Switch Bouton15 "Bouton 15" (ALL) {modbus="relayBoard1:14"}
Switch Bouton16 "Bouton 16" (ALL) {modbus="relayBoard1:15"}

OpenHab/conf/services/modbus.cfg

tcp.relayBoard1.connection=192.168.0.15:502
tcp.relayBoard1.type=coil
tcp.relayBoard1.id=17
tcp.relayBoard1.start=0
tcp.relayBoard1.length=16

poll=2000

OpenHab/conf/sitemaps/default.sitemap

sitemap demo label="Main Menu" {
    Switch item=Bouton1 label="Salon"
    Switch item=Bouton2 label="Cuisine"
    Switch item=Bouton3 label="Jardin"
    Switch item=Bouton4 label="Chambre"
    Switch item=Bouton5 label="Chambre 2"
    Switch item=Bouton6 label="Bureau"
    Switch item=Bouton7 label="Salle de bain"
    Switch item=Bouton8 label="Aquarium"
    Switch item=Bouton9 label="Cave"
    Switch item=Bouton10 label="VMC"
    Switch item=Bouton11 label="Marre à poissons"
    Switch item=Bouton12 label="Escalier"
    Switch item=Bouton13 label="Entrée"
    Switch item=Bouton14 label="TV"
    Switch item=Bouton15 label="Prise salon"
    Switch item=Bouton16 label="Prise cuisine"
}

That’s it, I’m done with this stupid board now. :slight_smile:

1 Like