Category Archives: Raspberry Pi

Using SDRplay RSPduo with RTLSDR-Airplay and a RaspberryPi

One of the side projects I have is rebroadcasting local ATC (Air Traffic Control) audio from my local airport to I previously had an RTL-SDR dongle connected to a RaspberryPi 1 Model B, which then rebroadcasted to LiveATC via IceCast. While I've had success the past few years broadcasting, overhead plans were really the only thing that was clear; being distant from the airport, receiving broadcasts from the tower were a slim to none at best.

In doing a bit of research I settled on purchasing a SDRplay RSPduo and Raspberry Pi 4, which seems to help with noise. Pairing the SDRplay with the newest version of RTLSDR-Airplay, I was able to achieve much clearer audio/hear things I couldn't before. While I'm using the SDRplay RSPduo, this guide can be used for their other devices such as the Rsp1a and RSPdx as well (likely others as this guide ages). Here's a reflection on how I got things setup.

Update Raspbian packages

First, update your Linux packages to latest version. I'm running the latest version of Raspbian / Debian.

sudo apt-get update && sudo apt-get upgrade

Disable WiFi/Bluetooth

This is optional, but I figured I'd disable the radios on the RaspberryPi to further mitigate as much possible noise as possible. First, you can disable both radios by editing /boot/config.txt via the vi text editor (this can actually be configured by placing this file on your SD-Card you attach to your Raspberry Pi during first-time boot). Official details on the boot overlays can be found here.

sudo vi /boot/config.txt

Once in vi, press i to insert the following lines:


Press the escape key and then type :wq to write the changes to the file and exit vi.

Lastly, execute the following command to disable the UART bluetooth service.

sudo systemctl disable hciuart

Download & Install RSP Control Library + Driver

First, you will want to grab the latest SDRplay Drivers and Libraries. You can do this by navigating to SDRplay's website and selecting RSPduo and ARM Raspberry Pi OS for the download. Then click the API button. Now this is kinda difficult if you are SSHed into the Pi, so I'd find the latest version from their website and then use the following commands below to remotely download the software (substituting in the version number to grab the latest download) and install it and reboot after install (rebooting after installation is strongly recommended).

Execute the following commands:

# Navigate to home directory
cd ~
# Download latest API Library + Driver
# Provide execution rights to install the software
chmod 755 ./
# Run the installer
# Reboot the machine
sudo reboot now

Build and install SoapySDR from source

In this section, we need to install SoapySDR which is a vendor and platform neutral SDR support library. Essentially this means that instead of needing a bunch of developers to write integrations into all the different SDRs, other software can leverage these interfaces to skip worrying about device compatibility and focus on what the application needs to do. As we'll see later, RTLSDR-Airband does exactly this to provide support for tons of different SDRs. Kudos to the PothosWare team for enabling developers all over the world to build all sorts of SDR projects!

So, to get this installed, we need to clone the source code from their GitHub repo and compile the project. Official documentation on this process can be found on their wiki, but I'm going to try and simplify everything here.

Since Raspberry Pi doesn't come with Git, I am going to use wget and unzip to do this, but if you don't mind installing Git, that'd be the easier way to "clone" down the latest source code from GitHub (make sure you replace versions where appropriate, at time of writing this, 0.8.0 is the latest version).

# Install dependencies needed to build this project
sudo apt-get install cmake g++ libpython-dev python-numpy swig
# Make sure we are back in our home directory
cd ~
# Grab latest tarball from GitHub
wget -O soapy-sdr-0.8.0.tar.gz
# Extract the tarball (this is like unzipping a .zip on Windows)
tar xvfz soapy-sdr-0.8.0.tar.gz

# Change directories into the new SoapSDR folder
cd SoapySDR
# Make a new folder called build
mkdir build

# Change directories into the build folder
cd build

# Execute cmake build automation
cmake ..

# Make installer (-j4 parameter increases build threads to make compilation quicker)
make -j4
# Make the installer copy files to right locations
sudo make install
sudo ldconfig #needed on debian systems
# Navigate back to home directory
cd ~
# Delete the SoapySDR folder since we are done with it
rm -R SoapySDR

At this point, you should be able to execute the SoapySDRUtil command and see the version you installed.

SoapySDRUtil --info

You should get something like this:

Build and install SoapySDR Play module from source

Now that we have SoapySDR installed, we need to install the module to allow it to control the SDRplay device. Similiar to SoapySDR install, we'll pull down the latest files from the SoapySDR Play Module GitHub repo, build the installer, execute it, and verify that all went well. Official instructions can be found on their wiki as well.

# Make sure we are back in our home directory
cd ~
# Grab latest tarball from GitHub
wget -O
# Unzip the archive
# Change directories into the new SoapSDR folder
cd SoapySDRPlay3-master
# Make a new folder called build
mkdir build
# Change directories into the build folder
cd build
# Execute cmake build automation
cmake ..
# Make installer
# Make the installer copy files to right locations
sudo make install
sudo ldconfig #needed on debian systems
# Navigate back to home directory
cd ~
# Delete the SoapySDR folder since we are done with it
rm -R SoapySDRPlay3-master

Plug in SDRplay RSPduo device and verify we see it

If you haven't already, go ahead and plug in your SDRplay RSPduo. Next, let's verify we see it using the SopaySDRUtil command.

SoapySDRUtil --probe="driver=sdrplay"

You should see something like this and you should see your device and hardware version (note the hardware hardware= value as you may need that later). In addition, one thing that is neat about the RSPduo is there are multiple tuners/antennas. You will be able to see these values in the probe output. Once you enable RTLSDR-Airplay, you'll notice active antennas are removed from the list of available devices.

pi@raspberrypi:~/RTLSDR-Airband-3.2.1 $ SoapySDRUtil --probe="driver=sdrplay"
##     Soapy SDR -- the SDR abstraction library     ##

Probe device driver=sdrplay
[INFO] devIdx: 0
[INFO] hwVer: 3
[INFO] rspDuoMode: 1
[INFO] tuner: 1
[INFO] rspDuoSampleFreq: 0.000000

-- Device identification

-- Peripheral summary
  Channels: 1 Rx, 0 Tx
  Timestamps: NO
  Other Settings:
     * RF Gain Select - RF Gain Select
       [key=rfgain_sel, default=4, type=string, options=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)]
     * IQ Correction - IQ Correction Control
       [key=iqcorr_ctrl, default=true, type=bool]
     * AGC Setpoint - AGC Setpoint (dBfs)
       [key=agc_setpoint, default=-30, type=int, range=[-60, 0]]
     * ExtRef Enable - External Reference Control
       [key=extref_ctrl, default=true, type=bool]
     * BiasT Enable - BiasT Control
       [key=biasT_ctrl, default=true, type=bool]
     * RfNotch Enable - RF Notch Filter Control
       [key=rfnotch_ctrl, default=true, type=bool]
     * DabNotch Enable - DAB Notch Filter Control
       [key=dabnotch_ctrl, default=true, type=bool]

-- RX Channel 0
  Full-duplex: NO
  Supports AGC: YES
  Stream formats: CS16, CF32
  Native format: CS16 [full-scale=32767]
  Antennas: Tuner 1 50 ohm, Tuner 1 Hi-Z, Tuner 2 50 ohm
  Corrections: DC removal
  Full gain range: [0, 48] dB
    IFGR gain range: [20, 59] dB
    RFGR gain range: [0, 9] dB
  Full freq range: [0.001, 2000] MHz
    RF freq range: [0.001, 2000] MHz
    CORR freq range:  MHz
  Sample rates: 0.0625, 0.096, 0.125, 0.192, 0.25, ..., 6, 7, 8, 9, 10 MSps
  Filter bandwidths: 0.2, 0.3, 0.6, 1.536, 5, 6, 7, 8 MHz

Build and install RTLSDR-Airband from source

RTLSDR-Airband is an open source project that allows you to receive analog radio voice channels and produce audio streams which can be routed to various outputs, such as online streaming via Icecast server, PulseAudio server, Audio file, or Raw I/Q file. In our case, we are going to stream to an Icecast server in this example.

Similar to our previous section in SoapySDR, we need to download the latest source code, build and install RTLSDR, and then modify the configuration file. Official documentation can be found on the RTLSDR-Airplay GitHub Wiki.

# Install RTLSDR-Airplay dependencies
sudo apt-get install build-essential libmp3lame-dev libshout3-dev libconfig++-dev libfftw3-dev
# Navigate back to our home directory
cd ~
# Download the latest source from GitHub
wget -O RTLSDR-Airband-3.2.1.tar.gz
# Extract the tarball
tar xvfz RTLSDR-Airband-3.2.1.tar.gz
# Change directory into the RTLSDR-Airband folder
cd RTLSDR-Airband-3.2.1
# Make the installer; this is specify to armv7 (32-bit Raspberry PI) with SoapySDR support.
# This removes RTLSDR support to avoid another dependency install (WITH_RTLSDR=0)
# Install the program
sudo make install

Configure RTLSDR-Airband

For my particular setup, I want to stream to an external icecast server. To do that, I recommend creating a backup of the default configuration file (as a backup).

# Rename the original config file as a backup
sudo mv /usr/local/etc/rtl_airband.conf /usr/local/etc/rtl_airband.conf.bak

Next, we can create a new configuration file with the proper configuration. Execute the following command to open vi.

sudo vi /usr/local/etc/rtl_airband.conf

Press i to go into insert mode and paste the following (replacing the values applicable to your environment; you may want to change the name of the stream, authentication parameters, and gain"). Also, note that we are using the first Antenna and specifying the hardware version of RSPduo from the previous step where we probed the SDRplay device (if you have a different SDRplay device, substitute that value accordingly).

# Configure IceCast Stream
  type = "soapysdr";
  index = 0;
  device_string = "driver=sdrplay,hardware=RSPduo";
  channel = 0;
  gain = 35;
  correction = 1;
  antenna = "Tuner 1 50 ohm";
  mode = "scan";
  channels: ( 
      freqs = ( 133.8 );
      outputs: ( 
             type = "icecast";
             server = "";
             port = 8010;
             mountpoint = "station"
             username = "username"
             password = "mypassword";
             name = "Tower";
             description = "Tower - 133.8Mhz";
             genre = "ATC";

Type :wq to write and save the changes to the file.

Validate RTLSDR-Airband Configuration

Once you have your configuration, you can validate everything is ready to go by running RTLSDR-Airplay in foreground mode.

From their wiki: you will see simple text waterfalls, one per each configured channel. This is an example for three devices running in multichannel mode. The meaning of the fields is as follows:

User interface screenshot
  • The number at the top of each waterfall is the channel frequency. When running in scan mode, this will be the first one from the list of frequencies to scan.
  • The number before the forward slash is the current signal level
  • The number after the forward slash is the current noise level estimate.
  • If there is an asterisk * after the second number, it means the squelch is currently open.
  • If there is a > or < character after the second number, it means AFC has been configured and is currently correcting the frequency in the respective direction.

Execute the following command to start running in foreground mode:

# Test in foreground mode
/usr/local/bin/rtl_airband -f

Press Cntrl+C to break out of the stream once you are satisfied with your testing.

Enable RTLSDR-Airband to autostart

To enable RTLSDR-Airband to automatically start up each time your Raspberry Pi is rebooted, you can execute the following commands from within the RTLSDR-Airband directory.

sudo cp init.d/rtl_airband.service /etc/systemd/system
sudo chown root.root /etc/systemd/system/rtl_airband.service
sudo systemctl daemon-reload
sudo systemctl enable rtl_airband

Hurray! We are done!

If you made it this far you have completed all the steps! Enjoy your new streaming SDR solution!

How to add buster-backports to a Raspberry Pi

What are backports?

Debian has a really good write up here on what backports are. Copying directly from their introduction paragraph:

You are running Debian stable, because you prefer the Debian stable tree. It runs great, there is just one problem: the software is a little bit outdated compared to other distributions. This is where backports come in.

Backports are packages taken from the next Debian release (called "testing"), adjusted and recompiled for usage on Debian stable. Because the package is also present in the next Debian release, you can easily upgrade your stable+backports system once the next Debian release comes out. (In a few cases, usually for security updates, backports are also created from the Debian unstable distribution.)

Backports cannot be tested as extensively as Debian stable, and backports are provided on an as-is basis, with risk of incompatibilities with other components in Debian stable. Use with care!

It is therefore recommended to only select single backported packages that fit your needs, and not use all available backports.

Once I enable backports will all packages use them?

No! Any new packages and updates to existing stable packages will prefer the stable releases. The only time you will leverage a new backport package is if you explicitly specify to pull from them.

How do I enable backports?

First you need to add the new backport source to your sources.list file. Edit the file in vi:

sudo vi /etc/apt/sources.list

Arrow down to the last row, press o to create a new line and then enter the following:

deb buster-backports main

Press escape and then type :wq to save the changes and exit via.

Next, we need to specify a keyserver to verify the authenticity of these packages. Note we use Ubuntu's key servers to validate the packages. Interestingly, Debian has a keyring to validate the packages, however the keyring doesn't contain the backports for buster on the raspberry pi at time of writing this. Ubuntu's servers will work fine to validate the authenticity of these packages and you will ultimately pull the packages from Debian rather than Ubuntu.

sudo bash
gpg --keyserver --recv-keys 04EE7237B7D453EC
gpg --keyserver --recv-keys 648ACFD622F3D138

gpg --export 04EE7237B7D453EC | sudo apt-key add -
gpg --export 648ACFD622F3D138 | sudo apt-key add -

How do I obtain a package from backport?

You can leverage one of the follow formats to specify the backport package:

apt install <package>/buster-backports
apt-get install <package>/buster-backports


apt install -t buster-backports <package>
apt-get install -t buster-backports <package>


aptitude install <package>/buster-backports

How to upgrade Home Assistant Z-Wave integration to Z-Wave JS for Docker

If you've been following my last two tutorials (Home Assistant + Docker + Z-Wave + Raspberry Pi | Jack Stromberg and How to update Home Assistant Docker Container | Jack Stromberg) on running Home Assistant via Docker and how to keep the container updated, you may have noticed that 2021 has been a big year for larger changes, with a surprising change coming to how Home Assistant handles Z-Wave Devices.

In Home Assistant v2021.2, Home Assistant announced the Z-Wave integration as deprecated in favor of a new integration called Z-Wave JS. In Home Assistant v2021.3, many fixes were implemented, with the notable limitation of Door Sensors being removed.

So why the change?

As per the Home Assistant v2021.2 announcement:

More and more people were concerned about the future of Z-Wave with Home Assistant; meanwhile the Z-Wave JS project was rapidly growing and gathering a large community around it. Long story short: Home Assistant and Z-Wave JS teamed up! And a lot of contributors jumped on the train!

This new integration is based on the same base principles as the OpenZWave integration: It is decoupled from Home Assistant. Instead of MQTT, the Z-Wave JS integration uses a WebSocket connection to a Z-Wave JS server.

This means, in order to use this new integration, you’ll need to run the Z-Wave JS server that sits in between your Z-Wave USB stick and Home Assistant. There are multiple options available for running the Z-Wave JS server, via Docker or manually, and there is also a Home Assistant add-on available.

So how do I upgrade?

This article reflects the steps I took to update my Z-Wave implementation.

Ensure you are running Home Assistant v2021.3.2 or greater

This will ensure you have support for most all sensors. You can find your Home Assistant version by selecting the Configuration gear on the left menu, and then selecting Info

Here you should see the version of Home Assistant (in my case 2021.3.2)

If you are not running the latest version, you can follow my upgrade steps here: How to update Home Assistant Docker Container | Jack Stromberg

Create a backup

It's rather critical to create a backup, especially in this case if you need to roll back to the older OpenZWave integration if you find many of your devices not being compatible. One downside in not using Home Assistant's OS is you don't have the "Supervisor" option to create a full backup.

To complete this step, I'd recommend checking out this blog post here which provides several options: Backing up Home Assistant | Tinkering with Home Automation (

Alternatively, you can be extremely lazy and less cautious by simply copying the configuration folder containing your docker config:

sudo cp /home/docker/home-assistant/ /home/docker/home-assistant-backup/ -R

Update your Operating System

Execute the following commands against your machine:

sudo sh -c 'apt update && apt upgrade'

Make sure you restart your machine to ensure your kernel updates to the latest version:

sudo shutdown -r -t now

Document Z-Wave entity IDs

The easiest way to do this is to navigate to Developer Tools (hammer icon on the left menu) and then type node_id into the Attributes column's filter.

In this case, you'll want to write down the node_id and the name of the entity it maps to. If you want to do this quickly, you can single click on the table, press Control + A to select all contents, or cmd+a on a Mac, and copy the contents into Word or Excel (Excel works remarkably well).

Document & Comment Z-Wave Stick Hardware ID and Network Key

SSH to your server and find your configuration.yaml file (if using my tutorial it should be /home/docker/home-assistant/configuration.yaml). Open the file in vi

sudo vi configuration.yaml

Find the section of code labeled zwave: and copy the information (we'll need it later) as well as comment out the following lines like so:

#  usb_path: /dev/ttyACM0
#  network_key: "0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99"

Type :wq to write the changes to the file and quit vi

Uninstall Z-Wave integration

Navigate to Configuration -> Integrations

Click the three dots on the Z-Wave integration and select Delete

Click OK when prompted

Click OK on the prompt that you should restart home assistant (it won't restart home assistant at this point)

Restart Home Assistant

While we can restart Home Assistant from the web UI, we need to ensure that the Docker container running home assistant no longer needs access to your Z-Wave stick directly (Z-Wave JS Server will be what interfaces with the device directly). In this case, you will need to SSH into your Home Assistant server and stop / remove / start the container accordingly.

Stop the Docker container

sudo docker stop home-assistant

Remove the container

sudo docker rm home-assistant

Deploy the new container configuration, which removes any device mappings to your Z-Wave stick/device

sudo docker run --init -d --restart=always --name="home-assistant" -e "TZ=America/Chicago" -v /home/docker/home-assistant:/config --net=host homeassistant/raspberrypi4-homeassistant:stable

Install Z-Wave JS Server

Create a new directory for the zwave-js server configuration files

sudo mkdir /home/docker/zwave-js/

Run the docker container (the first port listed is for the Z-Wave JS Web Interface, the second port is the Z-Wave JS WebSocket listener)

sudo docker run -d --restart=always  -p 8091:8091 -p 3000:3000 --device=/dev/ttyACM0 --name="zwave-js" -e "TZ=America/Chicago" -v /home/docker/zwave-js:/usr/src/app/store zwavejs/zwavejs2mqtt:latest

Configure Z-Wave JS Server

Navigate to the JS Web Server


On the settings page, enter the following configuration values (ensuring you substitute in the correct values obtained in the previous steps)

  • Serial Port: /dev/ttyACM0
  • Network Key: AABBCCDDEEFF00112233445566778899
    • Take your existing network key you obtained earlier and remove the 0x and "s to only leave one long hex string. For example:
      • Before
        • 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99
      • After
        • AABBCCDDEEFF00112233445566778899
  • Log Enabled: Disabled (toggled should be grayed)
  • Commands Timeout: 30 seconds
  • Disable MQTT Gateway: Can be enabled if you have no use for MQTT

Click the Home Assistant menu and set the following:

  • WS Server: Enabled
  • Server Port: 3000

Click SAVE

Verify you see devices

Click on the Control Panel icon on the top left of the Z-Wave JS Web UI. Verify that you see the amount of devices you previously had.

At this point, I would recommend waiting a few minutes / possibly hours to let the table populate with all the device information.

Install Z-Wave JS Integration

I would recommend a full refresh of the web page for Home Assistant and then navigate back to Configuration -> Integrations

Click the Add Integration button and search for Z-Wave JS

Click Submit to accept the URL as-is (assuming you are running the container on the same server running the Home Assistant container; if not, you can specify the IP address of the server hosting the Z-Wave JS Server container as well).

If all went well, you should see your Z-Wave devices and you can click Finish (Note: I wouldn't worry about specifying Areas since it's likely you have no idea what device is what at this point)

Update your Z-Wave Device Names in Home Assistant

The last step is to update your device names to match your existing device names. To do this, on the Configuration -> Integrations page, select the devices link on the Z-Wave JS integration tile

Next, select one of the items in your list. In my case, I'm going to select the first 1000W Dimmer I have.

On the device, you should see Node ID. This can be looked up on your list of devices you exported in the previous steps.

Click the Device Name (in my case 1000W Dimmer) and specify the correct information for the device. Once done, click Update

Rinse and repeat

Go through each of the devices you have and update their corresponding names. If you click Advanced settings, you can specify the area for the device as well.


If you've made it this far, you have successfully migrated to the latest Z-Wave integration for Home Assistant!

Home Assistant + Docker + Z-Wave + Raspberry Pi

Notice: Home Assistant has released a new integration called Z-Wave JS. You should be using that integration vs the older Z-Wave integration that this article covers. I will be updating this guide soon.

A few years back I had a SmartThings Hub and for the most part it worked great. It was simple to setup, can be accessed anywhere, and for the most part automatically updated itself. Unfortunately, with the acquisition of it by Samsung, it seems to have turned into bloatware with poor responsiveness, the mobile application's UI is horrific, and they have a less than desirable security/privacy policy.

Luckily, the open source community has thrown together Home Assistant, an open source home automation project backed by hundreds/thousands of individuals. Over the years, they have now brought native support for mobile devices, at time of writing this there are 1500+ integrations for dang near any device, and the software puts you in control of who has access to and where your data is accessible.

The one trade-off though is while Home Assistant works well and is very extensible, the documentation and usability of the application can be overwhelming to understand for someone new to home automation, unfamiliar with Linux/Open Source technologies, or new to debugging/command line interfaces.

In this case, I've tried to document a crash course in getting Home Assistant up and running as quickly as possible for those that want to get started with Z-Wave devices and Home Assistant.


You can leverage pretty much any hardware with Home Assistant, but here are the two items I used in my venture. Home Assistant has a full list of recommendations for what hardware to use for Home Assistant ( as well as what Z-Wave controllers are supported (

Update your Raspberry Pi

First things first, update your Raspberry Pi with the latest updates. Open up Terminal or SSH to your Raspberry Pi and execute the following command:

sudo apt-get update && sudo apt-get upgrade

Prepare your Z-Wave USB Stick

Plug in your Z-Wave USB stick. Once plugged in, we need to find the device path so that we can reference it for Home Assistant. Execute the lsusb command to find your device ID. In this case, you can see my device ID begins with 0658.

root@raspberrypi:/dev# lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0658:0200 Sigma Designs, Inc. Aeotec Z-Stick Gen5 (ZW090) - UZB
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Next, let's find what the device path is for the USB stick. You can do this by executing the following command: dmesg | egrep '0658|acm' Please note, if you purchased a difference device, 0658 may be a different number. In this case, you can see my device is presented on ttyACM0.

root@raspberrypi:/dev# dmesg | egrep '0658|acm'
[    1.405327] usb 1-1.2: New USB device found, idVendor=0658, idProduct=0200, bcdDevice= 0.00
[    3.468875] cdc_acm 1-1.2:1.0: ttyACM0: USB ACM device
[    3.471348] usbcore: registered new interface driver cdc_acm
[    3.471359] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

Install Docker

Home Assistant doesn't require Docker, but by leveraging Docker you can easily copy/backup your configuration and simply redeploy the container if something goes wrong. As updates are made, you can simply remove your container and redeploy. To install Docker, execute the following command:

curl -sSL | sh

Deploy Home Assistant Docker Container

Once Docker is installed, you can deploy the container from Docker Hub. Docker Hub is a public repository that has tons of different prebuilt containers to deploy. Here you can find the official homeassistant containers:

To deploy the container, execute the following line, replacing the following variables with your desired configuration:

  • --name="the name of your container"
  • -e "TM=YourTimezone"
  • --device=/dev/ttyACM0
    • This allows the container to leverage the Z-Wave USB device. Make sure you specify the path to your device found in the previous step
  • -v /home/docker/home-assistant:/config
    • This is the path that the home assistant configuration files should be stored to. You can specify a fileshare or other path to place your configuration files.
  • --net=host homeassistant/raspberrypi4-homeassistant:stable
    • The first half of this is the container you wish to deploy and the second half is the version. You can find all of Home Assistant's official containers here:
sudo docker run -d --restart=always --name="home-assistant" -e "TZ=America/Chicago" --device=/dev/ttyACM0 -v /home/docker/home-assistant:/config --net=host homeassistant/raspberrypi4-homeassistant:stable

Note: In newer versions of the docker container --init should not be specified in the docker run command. Specifying --init will result with the following error: "s6-overlay-suexec: fatal: can only run as pid 1". This was mentioned as a breaking change in: 2022-06-01 update: 2022.6: Gaining new insights! - Home Assistant (

Setup Home Assistant

Give the container a few minutes to deploy and configure itself for the first time. After a few minutes, try opening your web browser and navigating to the IP address assigned to your machine, using port number 8123:

When the page loads, it should first ask for your Name, Username, and Password. This is the username and password you will use to login to Home Assistant.

Next, specify the location of where your Home Assistant deployment is located. Oddly enough, you cannot type in a location, but you can place the pin near your location by dragging the map around and clicking once to set the pin.

Once you click Next, Home Assistant may have already found a few devices connected to your network. You can add them now or skip and add them later.

Tell Home Assistant to use your Z-Wave USB Stick

Although we granted access to the container to use the Z-Wave USB Stick, you need to tell Home Assistant how to leverage the device. To do so, you will need to open up Terminal or SSH to your machine and edit the configuration.yaml file to point to the device. Before we get into modifying the configuration.yaml file, first execute the following command to generate a Z-Wave Security Key. This key may be required by Z-Wave security devices (Door Locks, Keypads, etc), as an extra layer of security. More information on this can be found here:

Execute the following command via Terminal or SSH:

cat /dev/urandom | tr -dc '0-9A-F' | fold -w 32 | head -n 1 | sed -e 's/\(..\)/0x\1, /g' -e 's/, $//'

Once you execute the command, it should give you a string of characters that look something like:

"0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10"

Next, we need to edit the configuration.yaml file, which can be found in the path specified when the Docker container was deployed (using the -v parameter). For the purpose of this article, /home/docker/home-assistant/configuration.yaml is where the file is located. Using your favorite text editor, add the following lines of code:

  usb_path: /dev/ttyACM0
  network_key: "0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10"
configuration.yaml file with Z-Wave configuration

Once saved, go back to Home Assistant and click the Gear icon and then select Server Controls

Select the Restart button to restart Home Assistant. Any time you make a change to the configuration.yaml file, you will need to restart Home Assistant to pickup the configuration changes.

Click OK to Restart

Upon restart, navigate back to the Gear icon and you should see a new entry in the Config portal for Z-Wave. If you do not see the "Z-Wave" section, scroll down to the troubleshooting step at the end of this article.

Add a Z-Wave device

Once you see that your Z-Wave network has started, adding a device is a piece of cake. First click the Add Node button. When you click the button, nothing will happen, but go ahead and put your device in inclusion mode. Once the device is in inclusion mode, Home Assistant should automatically add the device.

At this point, if you navigate back to Configuration (Gear icon) and select Devices

You should see your newly added Z-Wave device!

At this point, you can select the Device to give it a friendly name or start to work on building your own home automation actions.

Hope this helped! If you have any comments or suggestions on how to improve this guide, please drop it below.

Troubleshooting Missing Z-Wave Configuration

The first time I ran through this, I noticed I was missing the Z-Wave configuration tile after making changes to the configuration.yaml file. It turned out I specified the wrong device path in the configuration file. To verify, you can check the logs from your Docker container by executing the following command in your Terminal or via SSH. (Replace home-assistant with the name of your container if you specified something else)

sudo docker logs home-assistant

In my case, I had the following error:

2020-02-16 21:08:01 INFO (MainThread) [homeassistant.components.scene] Setting up scene.homeassistant
2020-02-16 21:08:02 INFO (MainThread) [homeassistant.components.zwave] Z-Wave USB path is /dev/ttyACM01
2020-02-16 21:08:02 ERROR (MainThread) [homeassistant.config_entries] Error setting up entry Z-Wave (import from configuration.yaml) for zwave
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/openzwave/", line 78, in __init__
    raise ZWaveException(u"Can't find device %s : %s" % (device, traceback.format_exception(*sys.exc_info())))
openzwave.object.ZWaveException: "Zwave Generic Exception : Can't find device /dev/ttyACM01 : ['NoneType: None\\n']"

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/", line 215, in async_setup
    hass, self
  File "/usr/src/homeassistant/homeassistant/components/zwave/", line 369, in async_setup_entry
  File "/usr/local/lib/python3.7/site-packages/openzwave/", line 81, in __init__
    raise ZWaveException(u"Error when retrieving device %s : %s" % (device, traceback.format_exception(*sys.exc_info())))
openzwave.object.ZWaveException: 'Zwave Generic Exception : Error when retrieving device /dev/ttyACM01 : [\'Traceback (most recent call last):\\n\', \'  File "/usr/local/lib/python3.7/site-packages/openzwave/", line 78, in __init__\\n    raise ZWaveException(u"Can\\\'t find device %s : %s" % (device, traceback.format_exception(*sys.exc_info())))\\n\', \'openzwave.object.ZWaveException: "Zwave Generic Exception : Can\\\'t find device /dev/ttyACM01 : [\\\'NoneType: None\\\\\\\\n\\\']"\\n\']'

Here you can see I accidentally specified /dev/ttyACM01 vs /dev/ttyACM0. Simply updating the configuration.yaml file with the correct device path solved the issue.

Setting up a new Raspberry Pi via SSH

This is my super subpar tutorial on how to quickly setup a new Raspberry Pi via SSH (no mouse/keyboard/monitor directly attached to the device).

  1. Download the latest copy of the operating system (I personally prefer Raspbian Stretch Lite for the most minimal setup):
  2. Extract the download so you have a copy of the ****-**-**-raspbian-stretch-lite.img file
  3. Download Etcher to burn the image to an SD Card:
  4. Download a copy of Putty if you don't have a way to ssh:
  5. Open the SD card you just flashed and you should see the "boot" partition.  Create a file called ssh (no file extension or data needs to be written to the file)
    1. Note: ssh is disabled on all OS builds starting November 16 forward -- see here:
  6. Default credentials:
    1. Username: pi
    2. Password: raspberry
  7. Quick commands
    1. Configure Raspberry PI specific settings: sudo raspi-config
    2. Proper Shutdown (-h) / Restart (-r): sudo shutdown -h now

Unlike most laptops/desktops, the Raspberry Pi doesn't have a shutdown button, so always use the commands above to prevent SD Card corruption!