Setting up the connection
BLE capabilities of the hub
The LEGO® SPIKE™ Prime Hub exposes a BLE GATT service containing two characteristics: one for receiving data (RX), and one for transmitting data (TX).
The table below shows the UUIDs for the service and characteristics.
Item |
UUID |
---|---|
Service |
|
RX |
|
TX |
|
Note
“Receiving” and “transmitting” are from the perspective of the hub.
The hub includes the service UUID in the advertisement data, so that it can be used to filter scan results.
To send data to the hub, perform a write-without-response operation on the hub’s RX characteristic.
Any data from the hub will be delivered as a notification on the TX characteristic.
Hint
Make sure to enable notifications on the TX characteristic.
Handshake and negotiation
Upon connecting, the client should always initiate communication by sending an InfoRequest to the hub. The hub will respond with an InfoResponse, detailing the capabilities of the hub.
Of particular interest are the maximum sizes for packets and chunks:
- Max. packet size:
The largest amount of data that can be written to the RX characteristic in a single operation.
- Max. chunk size:
The maximum number of bytes allowed in the payload of a TransferChunkRequest.
The examples below show how these limits may be applied in Python:
async def send_message(message: BaseMessage) -> None:
print(f"Sending: {message}")
payload = message.serialize()
frame = cobs.pack(payload)
# use the max_packet_size from the info response if available
# otherwise, assume the frame is small enough to send in one packet
packet_size = info_response.max_packet_size if info_response else len(frame)
# send the frame in packets of packet_size
for i in range(0, len(frame), packet_size):
packet = frame[i : i + packet_size]
await client.write_gatt_char(rx_char, packet, response=False)
running_crc = 0
for i in range(0, len(EXAMPLE_PROGRAM), info_response.max_chunk_size):
chunk = EXAMPLE_PROGRAM[i : i + info_response.max_chunk_size]
running_crc = crc(chunk, running_crc)
chunk_response = await send_request(
TransferChunkRequest(running_crc, chunk), TransferChunkResponse
)