Install on macOS and BSD - oshri-almog/esp32c5-kismet-wifi-interface GitHub Wiki
This page is for using the boards with a Mac, or with a FreeBSD, OpenBSD or NetBSD machine. Nothing on it has been tested: nobody has run either helper, or built Kismet with the ESP32-C5 source, on these systems. What follows is what the code is written to do, and each point is marked for checking. If you try it, please report what happened (Contributing).
Warning: macOS and the BSDs are untested. The tested setups are a Raspberry Pi or Linux machine with the boards plugged in, and Windows feeding Kismet in WSL2, in Docker Desktop or on a Pi across the network (Choosing a Setup).
| macOS | FreeBSD, OpenBSD | NetBSD | |
|---|---|---|---|
| The board's port |
/dev/cu.usbmodem1101 (the number depends on the USB port it is in) |
/dev/cuaU0 |
/dev/dtyU0 |
| Python remote helper | Should work, and should find the boards and read their MACs by itself | Should work when you name the port; cannot find boards by itself | As FreeBSD |
C helper (kismet_cap_esp32c5) |
Written with macOS in mind, never compiled there; you always name the port | As macOS | As macOS |
| Kismet server | Kismet supports macOS, but has to be built from source with the ESP32-C5 source added | Kismet has no install page for the BSDs; not tried | As FreeBSD |
The route with the fewest unknowns is the Python remote helper on the Mac or BSD machine, feeding a Kismet server that runs somewhere tested: a Raspberry Pi or a Linux machine (Docker Desktop was tested on Windows, not on macOS). It needs only Python and three pip packages (pyserial, msgpack and websocket-client), and no Kismet build on the untested system. The same route, a Python remote helper on one machine feeding a Pi across the network, has been run from Windows.
flowchart LR
subgraph M["Mac or BSD machine"]
B["Board on /dev/cu.usbmodem1101"] -- USB --> H["Python remote helper"]
end
H -- "remote capture, websocket on TCP 2501" --> K["Kismet server<br/>Raspberry Pi or Linux"]
The helper needs Python 3.10 or newer, because its websocket package (websocket-client 1.9.1 or newer) does. Check the version:
python3 --versionIf it prints 3.9 or older, pip install below fails. The python3 that comes with Xcode's command line tools is 3.9. Install a newer Python with Homebrew, or from python.org:
brew install pythonThen create the virtual environment below with that Python, by its version number: for example python3.12 -m venv .venv in place of python3 -m venv .venv. Inside the virtual environment, python is then that version.
On the BSDs there is no python3 until you install a Python package. Install Python 3.10 or newer from the system's packages or ports, and use its command (for example python3.11) the same way.
Get the project and install its three packages in a virtual environment, which keeps them apart from the system's Python:
git clone https://github.com/oshri-almog/esp32c5-kismet-wifi-interface.git
cd esp32c5-kismet-wifi-interface
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements.txtIn every new terminal, cd into the project folder and run . .venv/bin/activate again before using the helper. There is no package to install: the helper runs as python -m esp32c5_kismet.remote from the project folder. Install on Windows explains the packages and the helper's messages in more detail; apart from the port names and the points under What differs from Linux and Windows, the helper behaves the same everywhere.
macOS. Let the helper list the boards:
python -m esp32c5_kismet.remote --listWith one board plugged in, the output should look like this, with your port and MAC:
/dev/cu.usbmodem1101 F0:F5:BD:01:02:03
--source esp32c5-cu.usbmodem1101
--source esp32c5zigbee-cu.usbmodem1101
--source esp32c5btle-cu.usbmodem1101
One source per board: it captures with one radio at a time. Every ESP32 on its native USB port has this USB ID, so a board listed here need not be an ESP32-C5 sniffer.
The helper finds boards through pyserial, which on macOS reads each port's USB ID and serial number from the system; the board's USB serial number is its MAC. pyserial names the port by its call-out device, /dev/cu.…. macOS also has a /dev/tty.… name for the same port; use the cu. one. Without the helper, ls /dev/cu.usbmodem* shows the ports.
FreeBSD, OpenBSD, NetBSD. On these systems pyserial lists port names only, without USB IDs or serial numbers, so the helper cannot tell which port is a board. --list prints No Espressif USB-Serial-JTAG device (USB ID 303a:1001) found. even with a board plugged in, and a definition that names no port cannot find one. Find the port yourself: plug the board in and look for the new device.
ls /dev/cuaU*On NetBSD, look for /dev/dtyU* instead.
You need a Kismet server with the esp32c5 source and an API key from it with the datasource role; Remote Capture shows how to make the key. The examples use a server at 192.168.1.50: change it to yours. Change the key too. (For Kismet in Docker Desktop on the same Mac it would be 127.0.0.1:2501, but that has not been tried; see Docker Desktop on macOS.)
On macOS:
export KISMET_CAP_APIKEY=3F9A6C1E07B24D58A1C9E2F4608B7D35
python -m esp32c5_kismet.remote --connect 192.168.1.50:2501 --source esp32c5-cu.usbmodem1101On the BSDs, name the port the same way. Change cuaU0 to your port (dtyU0 on NetBSD):
export KISMET_CAP_APIKEY=3F9A6C1E07B24D58A1C9E2F4608B7D35
python -m esp32c5_kismet.remote --connect 192.168.1.50:2501 --source esp32c5-cuaU0--source 'esp32c5:device=/dev/cuaU0,mode=wifi' means the same.
Why the port has to be in the definition there: both helpers take the part of a source name after the first - as the port /dev/<name> when it starts with tty, cu., cua, dty or pts/, whether or not that port exists at the moment. So esp32c5-cuaU0 is /dev/cuaU0 and esp32c5-dtyU0 is /dev/dtyU0, plugged in or not. If the board is not there, the Python remote helper logs /dev/cuaU0 is not there; is the board plugged in? (waiting for it) and tries again every 5 s. Any other name, such as a bare esp32c5 or esp32c5-kitchen, names no port, and the helper then has to find the board by itself, which it cannot do on a BSD.
For the other radios, use the names esp32c5zigbee-cu.usbmodem1101 and esp32c5btle-cu.usbmodem1101 on macOS, esp32c5zigbee-cuaU0 and esp32c5btle-cuaU0 on the BSDs, or mode=zigbee and mode=btle with device=. Repeat --source for more boards; each is one board on one radio. Source Definitions has every form.
The key in KISMET_CAP_APIKEY stays off the helper's command line, which other users of the machine may be able to read in the process list. To stop the helper, press Ctrl+C, or send it SIGTERM (kill with its process ID). It closes its connections, releases the ports and exits with status 0.
Note: Only capture on networks and devices you own or are authorised to test.
-
The source's ID in Kismet. On macOS the helper should read the board's MAC, so its Kismet ID is the usual
E5C50001-0000-0000-0000-<MAC>(1 for Wi-Fi, 2 for 802.15.4, 3 for Bluetooth LE). On the BSDs it has no MAC: the ID is made from a hash of the device path, and Kismet shows the hardware as plainESP32-C5. The same board on another port then becomes another source in Kismet. To keep one ID, give it yourself withuuid=, for exampleesp32c5:device=/dev/cuaU0,mode=wifi,uuid=E5C50001-0000-0000-0000-000000000001. - A board that comes back on another port. On Linux and Windows the helper checks, by MAC, which board is on a port it reopens, and follows a board that moved. On macOS it cannot check which board is on a port that opens, and trusts the port name; only when that port does not open does it look for the board's MAC among the ports pyserial lists, and follow it there. On the BSDs it knows no MAC, so it only waits for the port it was given.
-
One program per port. The helper takes an exclusive
flockon the port, the same lock as the C helper and esptool, so they keep out of each other's way. Like the C helper it also puts the port in exclusive mode (TIOCEXCL), which on these systems keeps out every other open of it except by root. A second capture on the same board gets... is already in use by another capture (an esp32c5 source or another program holds it); a board captures with one radio at a time. Close serial terminals before starting the helper: on these boards the DTR and RTS lines drive reset and boot mode, and a terminal that raises them can reboot the board. The helper itself clears them in a safe order. -
Permissions. Your user needs read and write access to the port.
ls -l /dev/cuaU0(or the macOS port) shows its owner and group. On the BSDs the dial-out ports usually belong to the groupdialer: add your user to it (on FreeBSDpw groupmod dialer -m <user>, on OpenBSD and NetBSDusermod -G dialer <user>), then log out and back in. On macOS thecu.ports are usually open to every user. -
Quoting. In zsh, bash and sh, put a definition with double quotes inside single quotes:
--source 'esp32c5-cu.usbmodem1101:channels="1,6,11",name=desk'.
Kismet runs on macOS and documents a Homebrew install and a source build (Kismet on macOS). No Kismet release contains the ESP32-C5 source yet, so a Homebrew Kismet cannot use these boards, not even from the Python remote helper: the server has to know the esp32c5 source type. For a Kismet server on the Mac itself, build it from source with the source added. None of this has been tried.
-
Install Xcode and Homebrew, and the packages Kismet's macOS page lists. Add the two tools
add-to-kismet.shneeds (it also needspython3):brew install autoconf automake
-
Get Kismet at the tested commit and add the ESP32-C5 source, as on Linux:
git clone https://github.com/kismetwireless/kismet.git ~/src/kismet git -C ~/src/kismet checkout cfe427074 sh ~/esp32c5-kismet-wifi-interface/kismet/add-to-kismet.sh ~/src/kismet
Change
~/esp32c5-kismet-wifi-interfaceto where you cloned this project. -
Configure with the options from Kismet's macOS page, plus a folder in your home to install into:
cd ~/src/kismet LDFLAGS=-L$(brew --prefix)/lib CPPFLAGS="-I$(brew --prefix)/include -I$(brew --prefix openssl)/include" ./configure --with-openssl=$(brew --prefix openssl) --prefix=$HOME/kismet-install --disable-python-tools
Check that the summary says
ESP32-C5: yes. -
Compile and install:
make -j4 make install INSTUSR=$(id -un) INSTGRP=$(id -gn) SUIDGROUP=$(id -gn)
The three variables make every installed file yours, so the install needs no root, as on Install on Linux. On macOS Kismet's default group for its privileged helpers is
staff.
Building Kismet with ESP32-C5 Support explains what add-to-kismet.sh changes. Kismet Configuration covers the login and kismet_site.conf, which is the same on every system.
The C helper runs inside Kismet for boards plugged into the Kismet machine. Its code leaves out its Linux-only parts on other systems and knows the port names of macOS and the BSDs, but whether it compiles and runs there has not been checked. What it cannot do anywhere but Linux is find boards: that reads Linux's sysfs. So:
-
Always name the port. A definition that names none, such as a bare
esp32c5oresp32c5-kitchen, fails with:finding a board by itself needs Linux sysfs (/sys/class/tty), which this system does not have; name the port with device=/dev/... or a source name like esp32c5-cu.usbmodem1101 or esp32c5-cuaU0Kismet shows this as the source's error and retries every 5 seconds, which cannot succeed until the port is named.
-
Name it like this, with your port and radio:
~/kismet-install/bin/kismet --no-ncurses -c 'esp32c5-cu.usbmodem1101:name=mac-wifi' ~/kismet-install/bin/kismet --no-ncurses -c 'esp32c5zigbee-cuaU0:name=bsd-zigbee'
The C helper takes a name starting with
cu.,cua,dtyorttyas a port even when it is not there yet; Kismet then reportscannot open /dev/...: No such file or directoryand retries every 5 seconds until the board is plugged in.device=/dev/...works too. -
kismet_cap_esp32c5 --listprintsesp32c5 - No supported data sources found..., and Kismet's Data Sources panel does not offer the boards. Add sources with-corsource=lines instead. -
The source's ID comes from a hash of the device path, because the MAC is read from sysfs too, and the hardware shows as
ESP32-C5. So the C helper and the Python remote helper give the same board different IDs on macOS, and a board on another port is another source. Useuuid=for an ID that stays. -
A board that comes back on another port is not followed; the helper waits on the port it was given.
Kismet's documentation has install pages for Linux, macOS and Windows, and none for the BSDs, and this project has not tried to build Kismet there. add-to-kismet.sh adds the ESP32-C5 source to Kismet's build on every platform, and the C helper knows the BSD port names, so a Kismet that builds on a BSD should take -c 'esp32c5-cuaU0' (or esp32c5-dtyU0 on NetBSD), with the same limits as on macOS above. Until someone tries, run the Python remote helper on the BSD machine and Kismet on Linux.
Not tested. Docker Desktop on macOS presumably cannot pass USB boards into containers, as on Windows. The project's images are built for 64-bit Intel and ARM (linux/amd64 and linux/arm64), so the demo with the fake board should run on both kinds of Mac, and a Kismet container should accept the Python remote helper from the Mac at --connect 127.0.0.1:2501. See Install with Docker and Try It Without Hardware.
The web flasher needs only Chrome or Edge 89 or newer, which run on macOS; it has not been tried there. Flashing the Firmware also covers macOS for ESP-IDF 5.5 and esptool, with the board's /dev/cu.usbmodem… port. Stop the helper or Kismet first, because they hold the port. Flashing from a BSD has not been considered.
Please report what you found, working or not: the system and its version, the Python version, what --list printed, the port name, whether a source captured, and the helper's and Kismet's messages. Contributing says where.
| What you see | Cause | Fix |
|---|---|---|
finding a board by itself needs Linux sysfs ... |
The C helper, with a definition that names no port | Name the port: esp32c5-cu.usbmodem1101, esp32c5-cuaU0 or device=/dev/...
|
No Espressif USB-Serial-JTAG device (USB ID 303a:1001) found. from --list on a BSD |
pyserial on the BSDs has no USB information | Find the port with ls /dev/cuaU* and name it: esp32c5-cuaU0
|
no Espressif USB-Serial-JTAG device (USB ID 303a:1001) found; plug the board in, or give device= in the source definition from the Python remote helper on a BSD |
The definition names no port | Name the port: esp32c5-cuaU0 or device=/dev/cuaU0
|
/dev/cuaU0 is not there; is the board plugged in? (waiting for it) |
No board on that port right now | Plug the board in; ls /dev/cuaU* shows which port it got. The helper keeps waiting |
... is already in use by another capture ... |
Another program or source has the port | Close it, or stop the other source |
Permission denied for the port |
Your user cannot open the device | Check ls -l on the port and join its group |
On the Kismet server: Kismet could not find a datasource driver for incoming remote source 'esp32c5' ...
|
That Kismet lacks the ESP32-C5 source, for example one from Homebrew | Use a Kismet built with it |
Troubleshooting covers the helpers and Kismet in general.