ble-sniffer doesn't follow the device

I'm trying to capture a ble connection with nrfutil.

What I've done:

- installed nrfutil on my arch based linux machine

- install ble-sniffer

- setup the nRF52840 Dongle with the given firmware.

- the device itself (usb, tty, etc) works

I can start sniffing the advertising paket with 

nrfutil ble-sniffer sniff --port /dev/ttyACM1 --log-level=info --log-output=stdout --json

It works fine an gives several devices like this:

{"type":"log","data":{"level":"INFO","message":"Device added: {\"address\":{\"address\":\"f8:55:48:13:9c:a9\",\"type\":\"Public\"},\"name\":{\"name\":\"DEMO9CA9\",\"ty\":\"ShortenedLocalName\"},\"rssi\":-57,\"is_followed\":false}","timestamp":"2026-04-21T10:11:38.484Z"}}

But if I try to follow the device of interest I got the following output:

$nrfutil ble-sniffer sniff --port /dev/ttyACM1 --follow f8:55:48:13:9c:a9 --log-level=info --log-output=stdout --json
{"type":"log","data":{"level":"INFO","message":"nrfutil-ble-sniffer (version = 0.18.0, platform = x86_64-unknown-linux-gnu, classification = nrf-external) invoked with sniff --port /dev/ttyACM1 --follow f8:55:48:13:9c:a9 --log-level=info --log-output=stdout --json ","timestamp":"2026-04-21T10:12:39.446Z"}}
{"type":"log","data":{"level":"INFO","message":"Attempt opening serial port at /dev/ttyACM1","timestamp":"2026-04-21T10:12:39.447Z"}}
{"type":"log","data":{"level":"INFO","message":"Subscribing to event DEVICE_ADDED","timestamp":"2026-04-21T10:12:39.448Z"}}
{"type":"log","data":{"level":"INFO","message":"Sending version request","timestamp":"2026-04-21T10:12:39.448Z"}}
{"type":"log","data":{"level":"INFO","message":"Sending ping request","timestamp":"2026-04-21T10:12:39.448Z"}}
{"type":"log","data":{"level":"INFO","message":"Sending timestamp request","timestamp":"2026-04-21T10:12:39.448Z"}}
{"type":"log","data":{"level":"INFO","message":"Sending advertisement hop sequence request for channels [37, 38, 39]","timestamp":"2026-04-21T10:12:39.451Z"}}
{"type":"log","data":{"level":"INFO","message":"Changing state from IDLE to SCANNING","timestamp":"2026-04-21T10:12:39.452Z"}}
{"type":"log","data":{"level":"INFO","message":"Sending scan packet","timestamp":"2026-04-21T10:12:39.452Z"}}
{"type":"log","data":{"level":"INFO","message":"Sending request to use temporary key [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]","timestamp":"2026-04-21T10:12:39.453Z"}}
{"type":"log","data":{"level":"INFO","message":"Changing state from SCANNING to FOLLOWING","timestamp":"2026-04-21T10:12:39.454Z"}}
{"type":"log","data":{"level":"WARN","message":"No device with address f8:55:48:13:9c:a9 random found. Still sending the follow request call, but no device is registered as followed.","timestamp":"2026-04-21T10:12:39.454Z"}}
{"type":"log","data":{"level":"INFO","message":"Sending follow request to follow device with address f8:55:48:13:9c:a9 random","timestamp":"2026-04-21T10:12:39.454Z"}}

In the resulting pcap file there are only advertising pakets.

There is the warning ""WARN","message":"No device with address f8:55:48:13:9c:a9 ... The ble-sniffer doesn't scan and add the device before it starts following.


Whats wrong here?

Parents
  • Hello,

    I am currently investigating. It seems there may be a regression, as I am also experiencing issues with the following connections now, which I have not encountered before. Will update as soon as I know more.

    Best regards,

    Vidar

  • I was able to follow the device when I attempted this again today, but I am not sure what changed. Could you please try repeat this again but via Wireshark?

  • Wireshark doesn't work at all. The bel-sniffer interface is visible, but if I start capturing, it stops immediately without capturing any pakets. Sometimes it show one or two advertising pakets. I couldn't get it to work.

  • I have not been able to determine what the issue may be but have reported it to the developers who will hopefully have time to take a look at it next week.

  • Update: they were able to identify and fix a bug that is hopefully related to the problem you experienced. The fix is included in v0.19.0 of the sniffer command which was released just now. Run "nrfutil upgrade" to install this version, then "nrfutil ble-sniffer bootstrap" if you want to update the plugin in WS.

  • It seems that the bug is still present in v0.20.0, here are my findings;

    Environment

    - nrfutil: 8.2.0 (c910332, 2026-04-21)
    - nrfutil-ble-sniffer: 0.20.0 (1d77b74, 2026-06-02)
    - Dongle: nRF52840 Dongle PCA10059, serial 2E3B1D3B264894A2
    - Sniffer firmware: 4.1.1 (flashed via `nrfutil device program`)
    - Host: Raspberry Pi 5, aarch64, Linux 6.18
    - Target device: ESP32-based BLE peripheral, public address `84:1f:e8:51:8a:16`, advertises as `BlueLink:09271`

    What works

    Without `--follow`, the sniffer captures the target's advertisements correctly:


    $ ./nrfutil ble-sniffer sniff --port /dev/ttyACM0 --output-pcap-file test.pcap
    # -> 2785 packets in 15 seconds, target device visible in pcap


    $ tshark -r test.pcap -Y "btle.advertising_address == 84:1f:e8:51:8a:16"
    20 0.178367 Espressif_51:8a:16 → Broadcast LE LL 58 ADV_IND
    21 0.179867 Espressif_51:8a:16 → Broadcast LE LL 58 ADV_IND
    ...

    What fails

    With `--follow`, the target device is never captured:


    $ ./nrfutil ble-sniffer sniff --port /dev/ttyACM0 --follow 84:1F:E8:51:8A:16 \
    --output-pcap-file follow.pcap
    # -> 4000+ packets from OTHER devices, zero from the target

    Same result with `--follow-by-name "BlueLink:09271"`.

    Root cause (from trace log)

    Running with `--log-level trace --log-output stdout` reveals the exact problem:


    [05:43:16.329Z] INFO - Changing state from IDLE to SCANNING
    [05:43:16.329Z] INFO - Sending scan packet
    [05:43:16.330Z] INFO - Changing state from SCANNING to FOLLOWING
    [05:43:16.330Z] WARN - No device with address 84:1f:e8:51:8a:16 random found.
    Still sending the follow request call, but no device
    is registered as followed.
    [05:43:16.330Z] INFO - Sending follow request to follow device with address
    84:1f:e8:51:8a:16 random

    Two bugs visible here:

    1. Timing: The follow command is sent **1 ms after the scan command**, before the sniffer has discovered any devices. The state transitions `IDLE → SCANNING → FOLLOWING` within the same millisecond. The warning `"No device with address ... found"` confirms the device hasn't been seen yet.

    2. Address type: The follow request uses address type **random**, but the target device uses a **public** address (Espressif OUI `84:1F:E8`). The sniffer firmware then filters for a random-address device that doesn't exist. This is confirmed by the unfollowed capture where tshark shows `randomized_tx: False` for this device.

    The `--follow-by-name` variant has the same timing problem:


    [05:44:19.888Z] INFO - Changing state from IDLE to SCANNING
    [05:44:19.888Z] WARN - No device with name BlueLink:09271 found.
    Can't send follow request call.

    It also fires immediately, but unlike `--follow` it doesn't even send the follow command — it silently falls back to unfollowed mode.

    Expected behavior

    The sniffer should:

    1. Start scanning
    2. Wait until the target device is discovered (by address or name)
    3. Read the correct address type (public/random) from the discovered device
    4. **Then** send the follow command with the correct address type

    Workaround

    I wrote a Python script that talks to the sniffer firmware directly over the serial protocol, implementing the correct scan-then-follow sequence. It discovers the device, reads the address type, then sends the follow command:


    # Scan until target is found
    info = extract_adv_info(pkt)
    if info['addr_str'] == target_mac and not found:
    # Send follow with the DISCOVERED address type
    cmd_follow(target_display_bytes, info['addr_type'])

    With this workaround, the firmware correctly enters FOLLOWING state and tracks the device through a connection (I can see it transition from ADV_PDU events to empty-data-PDU events when the phone connects).

    The fix in v0.19.0 did not resolve the issue. The `--follow` and `--follow-by-name` options are non-functional in 0.20.0 because the follow command races the scan, and `--follow` additionally hardcodes the address type to random.

Reply
  • It seems that the bug is still present in v0.20.0, here are my findings;

    Environment

    - nrfutil: 8.2.0 (c910332, 2026-04-21)
    - nrfutil-ble-sniffer: 0.20.0 (1d77b74, 2026-06-02)
    - Dongle: nRF52840 Dongle PCA10059, serial 2E3B1D3B264894A2
    - Sniffer firmware: 4.1.1 (flashed via `nrfutil device program`)
    - Host: Raspberry Pi 5, aarch64, Linux 6.18
    - Target device: ESP32-based BLE peripheral, public address `84:1f:e8:51:8a:16`, advertises as `BlueLink:09271`

    What works

    Without `--follow`, the sniffer captures the target's advertisements correctly:


    $ ./nrfutil ble-sniffer sniff --port /dev/ttyACM0 --output-pcap-file test.pcap
    # -> 2785 packets in 15 seconds, target device visible in pcap


    $ tshark -r test.pcap -Y "btle.advertising_address == 84:1f:e8:51:8a:16"
    20 0.178367 Espressif_51:8a:16 → Broadcast LE LL 58 ADV_IND
    21 0.179867 Espressif_51:8a:16 → Broadcast LE LL 58 ADV_IND
    ...

    What fails

    With `--follow`, the target device is never captured:


    $ ./nrfutil ble-sniffer sniff --port /dev/ttyACM0 --follow 84:1F:E8:51:8A:16 \
    --output-pcap-file follow.pcap
    # -> 4000+ packets from OTHER devices, zero from the target

    Same result with `--follow-by-name "BlueLink:09271"`.

    Root cause (from trace log)

    Running with `--log-level trace --log-output stdout` reveals the exact problem:


    [05:43:16.329Z] INFO - Changing state from IDLE to SCANNING
    [05:43:16.329Z] INFO - Sending scan packet
    [05:43:16.330Z] INFO - Changing state from SCANNING to FOLLOWING
    [05:43:16.330Z] WARN - No device with address 84:1f:e8:51:8a:16 random found.
    Still sending the follow request call, but no device
    is registered as followed.
    [05:43:16.330Z] INFO - Sending follow request to follow device with address
    84:1f:e8:51:8a:16 random

    Two bugs visible here:

    1. Timing: The follow command is sent **1 ms after the scan command**, before the sniffer has discovered any devices. The state transitions `IDLE → SCANNING → FOLLOWING` within the same millisecond. The warning `"No device with address ... found"` confirms the device hasn't been seen yet.

    2. Address type: The follow request uses address type **random**, but the target device uses a **public** address (Espressif OUI `84:1F:E8`). The sniffer firmware then filters for a random-address device that doesn't exist. This is confirmed by the unfollowed capture where tshark shows `randomized_tx: False` for this device.

    The `--follow-by-name` variant has the same timing problem:


    [05:44:19.888Z] INFO - Changing state from IDLE to SCANNING
    [05:44:19.888Z] WARN - No device with name BlueLink:09271 found.
    Can't send follow request call.

    It also fires immediately, but unlike `--follow` it doesn't even send the follow command — it silently falls back to unfollowed mode.

    Expected behavior

    The sniffer should:

    1. Start scanning
    2. Wait until the target device is discovered (by address or name)
    3. Read the correct address type (public/random) from the discovered device
    4. **Then** send the follow command with the correct address type

    Workaround

    I wrote a Python script that talks to the sniffer firmware directly over the serial protocol, implementing the correct scan-then-follow sequence. It discovers the device, reads the address type, then sends the follow command:


    # Scan until target is found
    info = extract_adv_info(pkt)
    if info['addr_str'] == target_mac and not found:
    # Send follow with the DISCOVERED address type
    cmd_follow(target_display_bytes, info['addr_type'])

    With this workaround, the firmware correctly enters FOLLOWING state and tracks the device through a connection (I can see it transition from ADV_PDU events to empty-data-PDU events when the phone connects).

    The fix in v0.19.0 did not resolve the issue. The `--follow` and `--follow-by-name` options are non-functional in 0.20.0 because the follow command races the scan, and `--follow` additionally hardcodes the address type to random.

Children
No Data
Related