For future reference, I’ll try to summarize this thread:
Two different dongles
First of all, it’s important to acknowledge that Sonoff sells two different dongles with almost the same name and almost the same housing. This thread is only about the “P” dongle. Don’t try to update an “E” dongle with the information from this thread! For completeness:
- The SONOFF Zigbee 3.0 USB Dongle Plus is the “P” dongle and is based on Texas Instruments chips: TI CC2652P + CP2102N
- The Zigbee 3.0 USB Dongle Plus–ZBDongle-E is the “E” dongle that is based on a chip from Silabs: EFR32MG21. Due to the different chips, the instructions here cannot be used to update the firmware.
(If you follow any of the two links, the page will have a handy comparison table of both sticks.)
Different update mechanisms
Searching the internet, you’ll find different ways of updating the firmware of the Sonoff P dongle:
- One involving taking apart the dongle and using specific I/Os to put it in.
- One involving a GUI tool.
- One involving some scripts.
All of these method are also referenced in this thread. I did only test the third option, so the remainder of this post will discuss that.
Updating the firmware with scripts
Prerequisites
For this approach, you can leave the dongle attached to your Home Assistant machine. I tested it with Home Assistant OS, I ran the script while logged in to HA OS via SSH. To be able to SSH to your HA machine, you need to install the SSH addon.
To be clear: I tested with a pre-installed image of Home Assistant, I believe this is called a “supervised” installation, but I’m not entirely sure about the right terminology here.
Step 1. Preparing the script
- Copy the contents of this file, and paste them into a new file, e.g. in your
config
directory. For the remainder of the instructions, let’s assume you call that filefirmware_sonoff.sh
. - Make the script executable, typing the following command in the shell while logged in to your HA machine:
chmod ug+x firmware_sonoff.sh
Step 2. Python virtual environment
- Create a Python virtual environment, using the following command:
This will create the virtual environment in a subdirectory of the current directory.python3 -m venv ./venv-for-firmware-update
- Activate the virtual environment:
./venv-for-firmware-update/bin/activate
- Edit the
firmware_sonoff.sh
script from step 1 to use the Python version from the virtual environment. To do so:- replace all occurences of
python
with/path/to/venv-for-firmware-update/bin/python
. In my case that was/root/config/venv-for-firmware-update/bin/python
. - replace all occurences of
pip
with/path/to/venv-for-firmware-update/bin/pip
.
- replace all occurences of
Step 3. Disable ZHA
Before running the script, you should disable the ZHA integration, to prevent it from accessing the dongle during the update process.
Step 4. Run the script
Run the script with the right arguments. If you’re not sure about the arguments, run the script without any arguments and it will print a short usage message.
Victory!
A successful run of the script should end with something like this:
Opening port /dev/ttyUSB0, baud 500000
Reading data from /root/config/zigbee-firmware/tmp/master/CC1352P2_CC2652P_launchpad_coordinator_20230507.hex
Your firmware looks like an Intel Hex file
Connecting to target...
CC1350 PG2.0 (7x7mm): 352KB Flash, 20KB SRAM, CCFG.BL_CONFIG at 0x00057FD8
Primary IEEE Address: --8<---snip--->8--
Performing mass erase
Erasing all main bank flash sectors
Erase done
Writing 360448 bytes starting at address 0x00000000
Write 104 bytes at 0x00057F988
Write done
Verifying by comparing CRC32 calculations.
Verified (match: 0xe83aa727)
Don’t forget to re-enable the ZHA integration!
I hope this is helpful to anyone. It will at least be helpful to a future me… Let me know if anything is unclear or if I made an error in my description. (I didn’t make notes when I did all this, so I wrote this up afterwards from the top of my head…)