Remote USB Z-Wave Controller over TCP

This post may contain affiliate links. Please read my disclaimer for more info.

We know that Z-Wave works best when devices are close together to create a good mesh network. But what if your Home Automation software is in the basement and all your devices are a floor up? Or maybe you virtualized your Home Automation server and can’t pass through USB. How can you still use your Z-Wave USB stick to communicate with your devices?

In today’s article, we look at deploying a Raspberry Pi with a Z-Wave stick anywhere in your house. The data is routed on your network back to your central Home Automation platform over TCP and emulated as a USB device. This allows us to have a remote USB Z-Wave controller. This is all done in software on Linux using the program remserial. Let’s get started.

Network Layout

First, let’s step back and look at how data will be moving in this network.

Z-Wave Over TCP Network

Our Home Automation server can now be sitting anywhere in our house, it doesn’t need to be physically close to any Z-Wave devices. The Raspberry Pi 3 can be in a central location to create a good mesh network. The USB Z-Wave controller will be plugged into it. The Raspberry Pi then creates a TCP server to route data from the Home Automation server to the USB connection. On the Home Automation server side, the TCP server is mounted as a pseudo USB device. So most applications won’t realize they are communicating over a TCP connection rather than a native USB connection.

One thing to keep in mind is the latency between your Home Automation server and the Raspberry Pi hosting the Z-Stick. In my testing with Home Assistant, I didn’t see any lag between controlling devices in Home Assistant and physically changing state. But if you’re Raspberry Pi 3 is on WiFi, or is doing lots of other tasks, you might increase your latency which would reduce the responsiveness.

Installing the Software

First off, you’ll need a Raspberry Pi (I’m using a Raspberry Pi 3) and a Z-Wave USB Stick (I’m using the Aeotec Z-Stick Gen 5). Go to the remserial website and download and extract the source code of remserial. If you only have access to your devices over ssh, you can download and extract using the following commands.

Now we need to compile the source code. While this can be challenging sometimes depending on a program’s dependencies, remserial is pretty small and easy to build. You only need the programs make and gcc to run the build process and compile the code. On Ubuntu, Debian and Raspbian you can make sure you have these installed by running the following.

Now that the dependencies are installed, you can go into the directory you downloaded and make the software.

You should see the program compile and a new file named remserial is now sitting in the current directory. You can either run the program from this directory or copy it to someplace like /usr/bin/ which will be on your PATH allowing you to call it from anywhere. Repeat the steps on your Raspberry Pi and Home Automation server so that both have a compiled version of remserial. Because they are different CPU architectures, you need to compile it on both platforms rather than compile once and copy it over.

Running the Software

Okay, the software is built, how do we actually run it. First, plug in the Z-Stick into your Raspberry Pi and determine which device it is by running ls -la /dev/tty*. This will show all the tty devices added and you’re USB stick will most likely be something like /dev/ttyACM0. When you’ve found your device, you can startup the remserial server by running:

  • -d puts remserial in daemon mode
  • -p 23000 defines the port we want to broadcast this device on
  • -x 2 turns on more verbose logging. Remserial writes to the system log which you can view by running tail -f /var/log/syslog.
  • -s "115200 raw" sets the tty parameters. For the Aeotec Z-Stick we can run it in raw mode with a 115200 baud rate. Run man tty to see more parameters.
  • /dev/ttyACM0 is the device we want to share on the network.

Next, we need to start the device on the client side. The call to remserial is similar, make sure to change the ports if you used a different port on the server side.

The only differences are:

  • sudo needs to be prepended because we are making a new USB device on the system, which requires admin access
  • -r <IP_ADDRESS> tells remserial the IP Address of the server hosting the USB device. In our case, it’s the Raspberry Pi.
  • -l /dev/zwave is the name of the device you want to create.
  • /dev/ptmx is a special device to create pseudo terminals. You can find more information here.

Now if you run ls -la /dev/* you should see the new device showing up! All applications on the server will interact with the device as if it’s local to the server. You probably need to restart Home Assistant or whatever Home Automation software you’re using to work with the new device.

Advanced Topics

Running in Docker

If you’re running Home Assistant or whatever your Home Automation software is in Docker you might need to change how you launch Docker so that it can properly use the device. The new device you created, in our case /dev/zwave, is actually a symlink to another device in /dev/pts. The problem is, Docker doesn’t seem to understand these symlinks when added to the container. However, you can use the privledged mode and mount your /dev on the hose side as a volume into the container. In a Docker compose file it would look like:

An alternative would be to create a Docker image with remserial installed and launching it as part of the bootup process. That way the USB device is added on the container side from the start.

SSH Tunnel

One downside to the setup listed is that communication all happens over the air in plain TCP data. So someone sniffing your network could see the data coming over TCP and use that to control your Z-Wave network. You could, however, create an ssh tunnel to hide the data.

On the client side you can create an SSH tunnel by running:

This creates a tunnel on your local port 23000 to the server. You then change your remserial command to use localhost as the “remote” server.

Automated Startup

There is a multitude of ways to get this to automatically happen at startup. You can go with something simple like cron or follow my article on how to create a systemd service for an alternative bootup method.


Hope this helped a problem you’re trying to solve like running your Z-Wave stick in a remote location. Of course, this really works with any serial device so if you have a Zigbee USB stick or anything else the same process should apply.

Enjoy the holidays and make sure to subscribe to the email list and social media to get all the latest articles! Leave a comment below if you’re already using remserial or a similar method.