Zigbee Sniffing from an Apple Mac

A Zigbee dongle

I recently installed powered window blinds that use Somfy motors. Having a dislike of proprietary bridges, I figured I would connect them up to my home automation using Zigbee2MQTT (the subject of a subsequent post).

Unfortunately, the blinds were not yet supported by Zigbee2MQTT, so I needed to manually add them. Part of this required sniffing the Zigbee packets that the blinds were sending and receiving. Getting the packet sniffing working on a Mac took some trial and error. To save others the time, this post documents how I made it work.

I started with a Sonoff Zigbee dongle (available from Amazon) Plugging it into a spare USB port on the Mac showed it was recognized, but the dongle requires a kernel extension to convert to a virtual serial device. The driver for this is availble from WCH.

Once the driver is installed the dongle should show under /dev/tty :

% ls -l /dev/tty.*
crw-rw-rw-  1 root  wheel  0x9000004 Jul 29 20:51 /dev/tty.Bluetooth-Incoming-Port
crw-rw-rw-  1 root  wheel  0x9000002 Aug  5 14:01 /dev/tty.usbserial-202302202015061
crw-rw-rw-  1 root  wheel  0x9000000 Aug  5 14:01 /dev/tty.wchusbserial202302202015061

The next step is to convert the serial comms to a loopback device that Wireshark can connect to. The ZSmartSystems Java app will do this. However, if you’re running an ARM Mac and use the pre-compiled JAR, you’ll get an InvocationTargetException:

Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
This is because the Java Serial Comms library package hasn’t been updated in the downstream Sniffer package. The quick fix is to switch out the JAR file. Download the latest release of JSSC, rename it to the version in the precompiled sniffer:

cp jssc-2.9.4.jar jssc-2.8.0.jar 

Then update the Sniffer Jar:

jar uf ZigBeeSniffer.jar jssc-2.8.0.jar

Once you’ve done this, the Sniffer should start up with a command similar to:

%java  -jar ZigBeeSniffer.jar -port "/dev/tty.wchusbserial202302202015061" -baud 115200  -flow software

Once you’ve installed Wireshark, point it at the loopback device and set a filter to lower the amount of traffic WireShark is dealing with: Loopback Connection

Now WireShark is connected, follow the instructions in on the Zigbee2MQTT site to configure the encryption keys for Zigbee in WireShark.

Packet Capture

In the screenshot above, I’m limiting the search to comms between my coordinator ZigBee2MQTT (0x0000) and a single Somfy Blind (0x544f)

Futher information on the expected payloads can be found in the Zigbee Spec. WireShark does a pretty good job of teasing the packets apart.

Once this was all working, I was able to figure out what commands the Somfy’s respond to. Release 15.50 of Zigbee-Herdsman-Converters includes my converters for these blinds. Kudos to Koen Kanters for such a well maintained and updated library.