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: 0x0000 for 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).

Required Configuration: The configuration must include a display packet (Packet Type 32) that defines the display dimensions, color scheme, and other display-specific parameters. This is mandatory for the protocol to function correctly. See the YAML Configuration Documentation for complete packet definitions.

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

Response Codes

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.

Example 1: Configuration Reading (Chunked)

CLIENT
DEVICE
Connect
GATT connection
Connected
Ready
Write: 0x00 0x40
Read Config
Notify: 0x00 0x40
Chunk 0, Total: 1280
508 bytes
Notify: 0x00 0x40
Chunk 1
512 bytes
Notify: 0x00 0x40
Chunk 2 (final)
260 bytes
Disconnect

Example 2: Image Transfer (Direct Write Mode)

CLIENT
DEVICE
Connect
GATT connection
Connected
Ready
Write: 0x00 0x70
800×600, B/W, full refresh
Notify: 0x00 0x70
Ready for data
Write: 0x00 0x71
Chunk 1: 230 bytes
Notify: 0x00 0x71
ACK
Write: 0x00 0x71
Chunk 2: 230 bytes
Notify: 0x00 0x71
ACK
Write: 0x00 0x71
Chunk 3...N: 230 bytes
Notify: 0x00 0x71
ACK (repeated)
Write: 0x00 0x71
Final chunk: 150 bytes
Notify: 0x00 0x71
ACK
Write: 0x00 0x72
End transfer
Notify: 0x00 0x72
Display refreshed
Disconnect

Example 3: Configuration Writing (Chunked)

CLIENT
DEVICE
Connect
GATT connection
Connected
Ready
Write: 0x00 0x41
Total: 900, Chunk 1: 198 bytes
Notify: 0x00 0x41
ACK
Write: 0x00 0x42
Chunk 2: 200 bytes
Notify: 0x00 0x42
ACK
Write: 0x00 0x42
Chunk 3: 200 bytes
Notify: 0x00 0x42
ACK, Config saved
Disconnect