BLE Communication Protocol
Part of OpenDisplay Flex standard
Overview
The OpenDisplay BLE Communication Protocol is part of the OpenDisplay Flex standard. It is an open standard for communication between clients and e-paper display devices. This protocol can be implemented by any firmware that wishes to be compatible with OpenDisplay clients. This page documents the complete protocol specification, including connection establishment, configuration management, and image transfer.
Protocol Standard
This is an open protocol standard. Any firmware implementation that follows this specification will be compatible with OpenDisplay clients, including the Python module, web tools, and Home Assistant integration.
For a simpler protocol option, see OpenDisplay.
BLE Connection Establishment
1. Device Discovery
Scan for Devices
The client scans for BLE devices with names starting with "OD" (OpenDisplay prefix).
Devices advertise with the service UUID 0x2446.
Service UUID: 0x2446
Characteristic UUID: 0x2446
Device Name: OD[chip_id]
2. GATT Connection
Connect to GATT Server
Once a device is selected, the client connects to the device's GATT server and discovers the primary service.
1. Connect to GATT Server
2. Get Primary Service (0x2446)
3. Get Characteristic (0x2446)
4. Start Notifications
3. Notification Setup
Enable Notifications
The client enables notifications on the characteristic to receive responses from the device. All device responses are sent via notifications.
Configuration Reading Flow
1. Send Read Command
Command: 0x0040
The client sends a read config command to request the device's current configuration.
Command: 0x00 0x40
2. Receive Config Chunks
Chunked Response
The device responds with configuration data in chunks. The first chunk contains:
- Response type:
0x00(success) - Command:
0x40 - Chunk number:
0x0000for first chunk - Total length: 2 bytes (little-endian)
- Config data: variable length
Subsequent chunks contain chunk number and data only. Each chunk is up to 512 bytes (minus headers).
3. Reconstruct Configuration
Assemble Chunks
The client collects all chunks and reconstructs the complete configuration packet. The configuration is validated using CRC16-CCITT checksum.
4. Parse Configuration
Decode Packet Structure
The reconstructed bytes are parsed according to the protocol specification:
- Length (2 bytes)
- Version (1 byte)
- Packets (variable, sequence of single packets)
- CRC (2 bytes)
Each single packet contains a packet number, packet ID, and payload specific to that packet type. See the Packet Structure section for detailed information.
Display Configuration Requirement: The configuration must contain a display packet (Packet Type 32) that specifies the display dimensions, color scheme, and refresh capabilities. Without this information, clients cannot properly format and send image data to the device. See the YAML Configuration Documentation for details on packet structure.
Configuration Writing Flow
1. Prepare Configuration
Build Packet
The client builds a configuration packet containing all required and optional packet types. The packet is encoded with length, version, packet sequence, and CRC.
Required Packet: The configuration must include a display packet (Packet Type 32) with display dimensions, color scheme, and refresh mode. This is essential for the device to know how to process incoming image data. See the YAML Configuration Documentation for details on all packet types.
2. Send Configuration
Write Command: 0x0041
For small configurations (<200 bytes), the entire packet is sent in one command:
Command: 0x00 0x41
Payload: [config bytes]
For larger configurations, chunked transmission is used:
- First chunk (0x0041): Contains total size (2 bytes) + first 200 bytes
- Subsequent chunks (0x0042): Contains remaining data in 200-byte chunks
3. Device Processing
Apply Configuration
The device validates the configuration, checks CRC, and stores it in non-volatile memory. A reboot command (0x000F) may be sent to apply the new configuration.
Image Transfer Flow
1. Direct Write Mode (Recommended)
Start Direct Write: 0x0070
The client initiates direct write mode, which sends image data directly to the display buffer without intermediate storage. The image dimensions and color scheme must match the display configuration that was previously read or written.
Command: 0x00 0x70
Payload: [width (2 bytes), height (2 bytes), color_scheme (1 byte), refresh_mode (1 byte)]
The device responds with 0x0070 (ACK) if ready to receive data. The width, height, and color_scheme
must match the display configuration (Packet Type 32) for the transfer to succeed.
2. Send Image Data
Data Chunks: 0x0071
Image data is sent in chunks using the direct write data command. Each chunk contains:
Command: 0x00 0x71
Payload: [chunk data, up to 230 bytes]
The device responds with 0x0071 (ACK) after each chunk is received.
3. Complete Transfer
End Direct Write: 0x0072
When all image data has been sent, the client sends the end command:
Command: 0x00 0x72
The device responds with 0x0072 (ACK) and refreshes the display with the new image.
Command Reference
0x0040- Read configuration0x0041- Write configuration (first chunk or small config)0x0042- Write configuration (subsequent chunks)0x0043- Read firmware version0x000F- Reboot device0x0070- Direct write start0x0071- Direct write data0x0072- Direct write end0x0064- Send data info (block-based)0x0065- Send block part (block-based)
Response Codes
0x00 [command]- Success response0xFF [command]- Error response0x00C4- Block part acknowledged0x00C5- Request next block part0x00C6- Request block0x00C7- Upload complete0x00C8- Image already displayed
Error Handling
If a command fails, the device responds with 0xFF followed by the command code.
The client should handle errors gracefully and may retry operations if appropriate.
Connection timeouts and GATT errors should also be handled with retry logic.