Getting started

Enhanced ShockBurst is a wireless communication protocol designed by Nordic Semiconductor and supported by a set of wireless system-on-chips including the nRF24 and nRF5x series. See Nordic Semiconductor ESB documentation for more details.

Scan available devices

Use the whad.esb.connector.scanner.Scanner class to instanciate a BLE device scanner and detect all the available devices.

from whad import UartDevice
from whad.esb import Scanner

scanner = Scanner(UartDevice('/dev/ttyUSB0'))
scanner.start()
for device in scanner.discover_devices():
    print(device)

Sniffing for Enhanced ShockBurst frames

Use the whad.esb.connector.sniffer.Sniffer to sniff for frames:

from whad.device import WhadDevice
from whad.esb import Sniffer

# Create a sniffer tied to an existing compatible interface
sniffer = Sniffer(WhadDevice.create('uart:/dev/ttyUSB0'))

# Sniff on channel 5
sniffer.channel = 5

# Start sniffing
sniffer.start()

# Capture frames and display them
for frame in sniffer.sniff():
    frame.show()

The whad.esb.Sniffer.sniff() method yield Scapy packets that can be processed like any other Scapy packets.

In the example above, our sniffer captured frames on a specific channel but it also can loop on every available channels and capture frames by setting its channel property to None, as shown below:

from whad.device import WhadDevice
from whad.esb import Sniffer

# Create a sniffer tied to an existing compatible interface (nRF52840)
sniffer = Sniffer(WhadDevice.create('uart:/dev/ttyUSB0'))

# Loop on all available channels
sniffer.channel = None

# Start sniffing
sniffer.start()

# Capture frames and display them
for frame in sniffer.sniff():
    frame.show()

Receiving Enhanced ShockBurst frames sent by a device

It is also possible to configure a compatible WHAD device to receive frames sent to a specific device address by setting it in receiver mode (also known as PRX mode). In the following example, we configure our compatible WHAD device (nRF52840) to receive and display Enhanced ShockBurst frames sent to address 11:22:33:44:55 on channel 5:

from whad.device import WhadDevice
from whad.esb import PRX

# Create a receiver tied to a compatible interface (nRF52840)
receiver = PRX(WhadDevice.create('uart:/dev/ttyUSB0'))

# Wait for packets on channel 5
receiver.address = '11:22:33:44:55'
receiver.channel = 5

# Show received frames
for frame in receiver.stream():
    frame.show()

In PRX mode, our compatible WHAD device behaves as a normal Enhanced Shockburst receiver and will send acks if required by the transmitter. A small ESB stack is implemented and used by our whad.esb.PRX connector to send these acks.

Warning

If a WHAD device is set in PRX mode while another compatible receiver is also active, there is a risk that both of them will send acks that overlap and avoid correct reception by the transmitter expecting an ack.

Sending Enhanced ShockBurst frames to a device

Similarly, a compatible WHAD device can send frames to a target Enhanced ShockBurst device when set in transmitter mode (or PTX mode):

from whad.device import WhadDevice
from whad.esb import PTX

# Create a receiver tied to a compatible interface (nRF52840)
transmitter = PTX(WhadDevice.create('uart:/dev/ttyUSB0'))

# Configure transmitter to send to device with address 11:22:33:44:55 on
# channel 5
transmitter.address = '11:22:33:44:55'
transmitter.channel = 5

# Send data
transmitter.send_data(b"This is a payload")

When the device’s channel is unknown, there is a procedure defined in Nordic Semiconductor’s Enhanced ShockBurst protocol that allows a transmitter to discover a target device’s channel. This pocedure is known as a ping procedure, and consists in basically sending ping frames on all channels and listening to detect an answer. This procedure is available in PTX and can be used as follows:

from whad.device import WhadDevice
from whad.esb import PTX

# Create a receiver tied to a compatible interface (nRF52840)
transmitter = PTX(WhadDevice.create('uart:/dev/ttyUSB0'))

# Configure transmitter to send to device with address 11:22:33:44:55
transmitter.address = '11:22:33:44:55'

# Synchronize with device (find device channel)
if transmitter.synchronize()
    # Send data once synchronized
    transmitter.send_data(b"This is a payload")
else:
    print("Cannot synchronize with target device")