If you are using a Raspberry Pi with Sonoff Zigbee 3.0 Dongle Plus (ZBDongle-P) as a Zigbee coordinator to manage your zigbee smart home devices, as I am, then you can easily update (flash) the firmware on the dongle without even unplugging it from the Pi.
This Sonoff Zigbee dongle comes with firmware pre-installed, so its only necessary to do this to update the firmware to a new version. You can do all of the following steps by opening a terminal on your Pi (either the terminal app on the desktop GUI or over SSH).
Python should already be installed on the Pi, but you can check by running
python --version. It should output something like
Python 3.9.2. If not, you need to first install Python on your Pi by running this command:
sudo apt install python3
Next, we need to update the
pip package manager and install some 3rd party packages to allow us to run the scripts we need to do the firmware update:
python -m pip install --upgrade pip pip install wheel pyserial intelhex python-magic zigpy-znp
Now we need to find which port the dongle is plugged into. In linux, USB devices are mounted in the
/dev filesystem so we can easily find it by opening the /dev directory and checking for a device name that looks like ours:
cd /dev/serial/by-id/ ls -lah
I only have one USB device plugged in, so the output looks like this for me:
lrwxrwxrwx 1 root root 13 Feb 8 12:17 usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_029ea6556029ec125f3440c9ce8d-if00-port0 -> ../../ttyUSB0
Depending how many USB devices you have plugged in, you may see more than one item here. Find the one that has the sonoff zigbee name. This output shows that the device is symlinked to the
/dev/ttyUSB0 path. Remember this or note it down because we will use it in later commands.
Create a new folder in your home directory (or somewhere else) to store the firmware file and scripts that we will use:
mkdir ~/zigbee-dongle cd ~/zigbee-dongle
Note: All future commands will be run from this directory
If something goes wrong while flashing the firmware, the dongle will be bricked and it won't be usable, so it is very important that we take a backup first. You can use this command to take a backup of the raw nvram state of the dongle:
python -m zigpy_znp.tools.nvram_read /dev/ttyUSB0 -o dongle_nvram_backup.json
Lots of text will be written to the screen and a JSON file called
dongle_nvram_backup.json will be created in the folder that you ran the script in.
Note: if nothing happens for a while, and then a strange timeout error occurs (eg.
asyncio.exceptions.CancelledError) it probably means that the USB device is in use by another process. I use zigbee2mqtt and I suspected that was using the device, so I stopped zigbee2mqtt and then ran the above command again and it worked.
Next, we need to download two things:
cc2538-bsl- A python script for applying firmware to a device via the serial boot loader
- The firmware itself
Download and unzip
cc2538-bsl using these commands:
wget https://github.com/JelmerT/cc2538-bsl/archive/refs/heads/master.zip unzip master.zip
Then, find the new firmware that we are going to install. Open this Github page and find the file that has "launchpad_coordinator" in the name (usually the one at the top) and click on it. In the page that opens, there will be a small download button in the middle right corner. Right click on the link and copy it, type
wget in your terminal and paste the link. For example:
Note: This firmware is for a coordinator device. If your sonoff zigbee dongle is being used as a router, then you need to find the
launchpad_routerfile from here instead.
If you don't know if your device is a coordinator or a router: is this zigbee dongle being used as your main zigbee hub, or is another device? If this dongle is your main hub, then it is a coordinator. Otherwise its probably a router.
If the device doesn't work after updating the coordinator firmware, try downloading and installing the router firmware instead.
Unzip the downloaded zip file (replace the filename with the one you downloaded), and we should be left with a
.hex file into the
cc2538-bsl-master directory (replace the filename with the one you downloaded), and switch into that directory:
cp CC1352P2_CC2652P_launchpad_coordinator_20221226.hex ./cc2538-bsl-master/ cd cc2538-bsl-master
Now we're ready to start flashing the USB device. Run this command, replacing the path to the USB device as we determined earlier, and replacing the hex file name with the one you unzipped a moment ago:
python cc2538-bsl.py -e -v -w -p /dev/ttyUSB0 --bootloader-sonoff-usb CC1352P2_CC2652P_launchpad_coordinator_20221226.hex
If all goes well, you'll see a few messages appear including
Write done and
Verified. And that's it - the device firmware is updated. Now we can restart the process that was using the USB device before (eg. zigbee2mqtt) and everything should continue to work as before.
If something went wrong during the firmware flashing, you can restore the backup we took earlier to the device by using these commands:
cd ../ python -m zigpy_znp.tools.nvram_write /dev/ttyUSB0 -i dongle_nvram_backup.json