BLE API¶
BLE Limitations¶
This module uses the RF24
class to make the nRF24L01 imitate a
Bluetooth-Low-Emissions (BLE) beacon. A BLE beacon can send data (referred to as
advertisements) to any BLE compatible device (ie smart devices with Bluetooth
4.0 or later) that is listening.
Original research was done by Dmitry Grinberg and his write-up (including C source code) can be found here As this technique can prove invaluable in certain project designs, the code here has been adapted to work with Python.
Important
Because the nRF24L01 wasn’t designed for BLE advertising, it has some limitations that helps to be aware of.
The maximum payload length is shortened to 18 bytes (when not broadcasting a device
name
nor the nRF24L01show_pa_level
). This is calculated as:32 (nRF24L01 maximum) - 6 (MAC address) - 5 (required flags) - 3 (CRC checksum) = 18
Use the helper function
len_available()
to determine if your payload can be transmit.the channels that BLE use are limited to the following three: 2.402 GHz, 2.426 GHz, and 2.480 GHz. We have provided a tuple of these specific channels for convenience (See
BLE_FREQ
andhop_channel()
).crc_length
is disabled in the nRF24L01 firmware because BLE specifications require 3 bytes (crc24_ble()
), and the nRF24L01 firmware can only handle a maximum of 2. Thus, we have appended the required 3 bytes of CRC24 into the payload.address_width
of BLE packet only uses 4 bytes, so we have set that accordingly.The auto-ack (automatic acknowledgment) feature of the nRF24L01 is useless when transmitting to BLE devices, thus it is disabled as well as automatic re-transmit (
get_arc()
) and custom ACK payloads (ack_payloads
) features which both depend on the automatic acknowledgments feature.The
dynamic_payloads
feature of the nRF24L01 isn’t compatible with BLE specifications. Thus, we have disabled it.BLE specifications only allow using 1 Mbps RF
data_rate
, so that too has been hard coded.Only the “on data sent” & “on data ready” events will have an effect on the interrupt (IRQ) pin. The “on data fail” is never triggered because auto-ack feature is disabled. Keep this in mind when using
mask_irq()
.
fake_ble
module helpers¶
-
pyrf24.fake_ble.address_repr(buf, reverse: bool =
True
, delimit: str =''
) str ¶ Convert a buffer into a hexlified string.
This method is primarily used to display how the address is used by the radio.
>>> from pyrf24.fake_ble import address_repr >>> address_repr(b"1Node") '65646F4E31'
- Parameters:
- buf : bytes,bytearray¶
The buffer of bytes to convert into a hexlified string.
- reverse : bool¶
A
bool
to control the resulting endianess.True
outputs the result as big endian.False
outputs the result as little endian. This parameter defaults toTrue
sincebytearray
andbytes
objects are stored in big endian but written in little endian.- delimit : str¶
A
chr
orstr
to use as a delimiter between bytes. Defaults to an empty string.
- Returns:
A string of hexadecimal characters in big endian form of the specified
buf
parameter.
- pyrf24.fake_ble.swap_bits(original: int) int ¶
This function reverses the bit order for a single byte.
- pyrf24.fake_ble.reverse_bits(original: bytes | bytearray) bytearray ¶
This function reverses the bit order for an entire buffer protocol object.
-
pyrf24.fake_ble.crc24_ble(data: bytes | bytearray, deg_poly: int =
1627
, init_val: int =5592405
) bytearray ¶ This function calculates a checksum of various sized buffers.
This is exposed for convenience and should not be used for other buffer protocols that require big endian CRC24 format.
- Parameters:
- data : bytearray,bytes¶
The buffer of data to be uncorrupted.
- deg_poly : int¶
A preset “degree polynomial” in which each bit represents a degree who’s coefficient is 1. BLE specifications require
0x00065b
(default value).- init_val : int¶
This will be the initial value that the checksum will use while shifting in the buffer data. BLE specifications require
0x555555
(default value).
- Returns:
A 24-bit
bytearray
representing the checksum of the data (in proper little endian).
-
pyrf24.fake_ble.chunk(buf: bytes | bytearray, data_type: int =
22
) bytearray ¶ This function is used to pack data values into a block of data that make up part of the BLE payload per Bluetooth Core Specifications.
- Parameters:
- buf : bytearray,bytes¶
The actual data contained in the block.
- data_type : int¶
The type of data contained in the chunk. This is a predefined number according to BLE specifications. The default value
0x16
describes all service data.0xFF
describes manufacturer information. Any other values are not applicable to BLE advertisements.
Important
This function is called internally by
advertise()
. To pack multiple data values into a single payload, use this function for each data value and pass alist
ortuple
of the returned results toadvertise()
(see example code in documentation aboutadvertise()
for more detail). Remember that broadcasting multiple data values may require thename
be set toNone
and/or theshow_pa_level
be set toFalse
for reasons about the payload size with BLE Limitations.
- pyrf24.fake_ble.whitener(buf: bytes | bytearray, coefficient: int) bytearray ¶
Whiten and de-whiten data according to the given coefficient.
This is a helper function to
FakeBLE.whiten()
. It has been broken out of theFakeBLE
class to allow whitening and dewhitening a BLE payload without the hardcoded coefficient.- Parameters:
- buf : bytes,bytearray¶
The BLE payloads data. This data should include the CRC24 checksum.
- coefficient : int¶
The whitening coefficient used to avoid repeating binary patterns. This is the index (plus 37) of
BLE_FREQ
tuple for nRF24L01 channel that the payload transits.rx_channel = radio.channel coef = ( index + 37 for index, chl in enumerate(BLE_FREQ) if chl == rx_channel )
Note
If currently used nRF24L01 channel is different from the channel in which the payload was received, then set this parameter accordingly.
-
pyrf24.fake_ble.BLE_FREQ =
(2, 26, 80)
¶ The BLE channel number is different from the nRF channel number.
This tuple contains the relative predefined channels used:
nRF24L01 channel
BLE channel
2
37
26
38
80
39
QueueElement class¶
- class pyrf24.fake_ble.QueueElement(buffer: bytes | bytearray)¶
A data structure used for storing received & decoded BLE payloads in the
rx_queue
.- Parameters:
- data : List[Union[bytearray, bytes, BatteryServiceData, TemperatureServiceData, UrlServiceData]]¶
A
list
of the transmitting device’s data structures (if any). If an element in thislist
is not an instance (or descendant) of theServiceData
class, then it is likely a custom, user-defined, or unsupported specification - in which case it will be abytearray
object.
FakeBLE class¶
- class pyrf24.fake_ble.FakeBLE(radio: RF24)¶
A class to implement BLE advertisements using the nRF24L01.
Per the limitations of this technique, only some of underlying
RF24
functionality is available for configuration when implementing BLE transmissions. See the Restricted RF24 functionality for more details.- Parameters:
-
advertise(buf: bytes | bytearray =
b''
, data_type: int =255
)¶ This blocking function is used to broadcast a payload.
- Returns:
Nothing as every transmission will register as a success under the required settings for BLE beacons.
- Parameters:
- buf : bytearray¶
The payload to transmit. This bytearray must have a length greater than 0 and less than 22 bytes Otherwise a
ValueError
exception is thrown whose prompt will tell you the maximum length allowed under the current configuration. This can also be a list or tuple of payloads (bytearray
); in which case, all items in the list/tuple are processed are packed into 1 payload for a single transmissions. See example code below about passing alist
ortuple
to this parameter.- data_type : int¶
This is used to describe the buffer data passed to the
buf
parameter.0x16
describes all service data. The default value0xFF
describes manufacturer information. This parameter is ignored when atuple
orlist
is passed to thebuf
parameter. Any other values are not applicable to BLE advertisements.
Important
If the name and/or TX power level of the emulated BLE device is also to be broadcast, then the
name
and/orshow_pa_level
attribute(s) should be set prior to callingadvertise()
.To pass multiple data values to the
buf
parameter see the following code as an example:# let UUIDs be the 16-bit identifier that corresponds to the # BLE service type. The following values are not compatible with # BLE advertisements. UUID_1 = 0x1805 UUID_2 = 0x1806 service1 = ServiceData(UUID_1) service2 = ServiceData(UUID_2) service1.data = b"some value 1" service2.data = b"some value 2" # make a tuple of the buffers buffers = ( chunk(service1.buffer), chunk(service2.buffer) ) # let `ble` be the instantiated object of the FakeBLE class ble.advertise(buffers) ble.hop_channel()
- available() bool ¶
A
bool
describing if there is a payload in therx_queue
.This method will take the first available data from the radio’s RX FIFO and validate the payload using the 24bit CRC checksum at the end of the payload. If the payload is indeed a valid BLE transmission that fit within the 32 bytes that the nRF24L01 can capture, then this method will decipher the data within the payload and enqueue the resulting
QueueElement
in therx_queue
.Tip
Use
read()
to fetch the decoded data.
-
begin(ce_pin: int | None =
None
, csn_pin: int | None =None
) bool ¶ Initialize the radio using BLE specifications.
Internally, this function also calls
begin()
, so there’s no need to initialized the radio’s hardware before calling this function.If dynamically specifying the radio’s GPIO pins, then 2 positional arguments are supported.
- hop_channel()¶
Trigger an automatic change of BLE compliant channels.
-
len_available(hypothetical=
b''
) int ¶ This function will calculates how much length (in bytes) is available in the next payload.
This is determined from the current state of
name
andshow_pa_level
attributes.
- property mac¶
This attribute returns a 6-byte buffer that is used as the arbitrary mac address of the BLE device being emulated.
You can set this attribute using a 6-byte
int
orbytearray
. If this is set toNone
, then a random 6-byte address is generated.
- property name¶
The broadcasted BLE name of the nRF24L01.
This is not required. In fact, setting this attribute will subtract from the available payload length (in bytes). Set this attribute to
None
to disable advertising the device name.Valid inputs are
str
,bytes
,bytearray
, orNone
. Astr
will be converted to abytes
object automatically.Note
This information occupies (in the TX FIFO) an extra 2 bytes plus the length of the name set by this attribute.
- read() QueueElement | None ¶
Get the First Out element from the queue.
- Returns:
A
QueueElement
object from the front of therx_queue
(like a FIFO buffer).
- rx_cache¶
The internal cache used when validating received BLE payloads.
This attribute is only used by
available()
to cache the data from the top level of the radio’s RX FIFO then validate and decode it.Hint
This attribute is exposed for debugging purposes.
- rx_queue : List[QueueElement]¶
The internal queue of received BLE payloads’ data.
Each Element in this queue is a
QueueElement
object whose members are set according to the its internal decoding algorithm. Theread()
function will remove & return the first element in this queue.Hint
This attribute is exposed for debugging purposes, but it can also be used by applications.
- property show_pa_level : bool¶
If this attribute is
True
, the payload will automatically include the nRF24L01’spa_level
in the advertisement.The default value of
False
will exclude this optional information.Note
This information occupies (in the TX FIFO) an extra 3 bytes, and is really only useful for some applications to calculate proximity to the nRF24L01 transceiver.
- whiten(data) bytearray ¶
Whitening the BLE packet data ensures there’s no long repetition of bits.
This is done according to BLE specifications.
- Parameters:
- Returns:
A
bytearray
of thedata
with the whitening algorithm applied.
Note
advertise()
andavailable()
uses this function internally to prevent improper usage.Warning
This function uses the currently set BLE channel as a base case for the whitening coefficient.
Do not call
hop_channel()
before callingavailable()
because this function needs to know the correct BLE channel to properly de-whiten received payloads.
Restricted RF24 functionality¶
The following RF24
functionality should not be used when FakeBLE
objects are instantiated with an RF24
object:
Service related classes¶
Abstract Parent¶
- class pyrf24.fake_ble.ServiceData(uuid)¶
An abstract helper class to package specific service data using Bluetooth SIG defined 16-bit UUID flags to describe the data type.
- Parameters:
- uuid : int¶
The 16-bit UUID “GATT Service assigned number” defined by the Bluetooth SIG to describe the service data. This parameter is required.
- __len__() int ¶
For convenience, this class is compatible with python’s builtin
len()
method. In this context, this will return the length of the object (in bytes) as it would appear in the advertisement payload.
- __repr__() str ¶
For convenience, this class is compatible with python’s builtin
repr()
method. In this context, it will return a string of data with applicable suffixed units.
- property buffer : bytes¶
Get the representation of the instantiated object as an immutable
bytes
object (read-only).
Service data UUID numbers¶
These are the 16-bit UUID numbers used by the Derivative Children of the ServiceData class
- pyrf24.fake_ble.TEMPERATURE_UUID = 0x1809¶
The Temperature Service UUID number
- pyrf24.fake_ble.BATTERY_UUID = 0x180F¶
The Battery Service UUID number
- pyrf24.fake_ble.EDDYSTONE_UUID = 0xFEAA¶
The Eddystone Service UUID number
Derivative Children¶
- class pyrf24.fake_ble.TemperatureServiceData¶
Bases:
ServiceData
This derivative of the
ServiceData
class can be used to represent temperature data values as afloat
value.See Also
Bluetooth Health Thermometer Measurement format as defined in the GATT Specifications Supplement.
- class pyrf24.fake_ble.BatteryServiceData¶
Bases:
ServiceData
This derivative of the
ServiceData
class can be used to represent battery charge percentage as a 1-byte value.See Also
The Bluetooth Battery Level format as defined in the GATT Specifications Supplement.
- class pyrf24.fake_ble.UrlServiceData¶
Bases:
ServiceData
This derivative of the
ServiceData
class can be used to represent URL data as abytes
value.See Also
Google’s Eddystone-URL specifications.