Reader BT Developer Documentation
This document describes the Bluetooth® Low Energy (BLE) interface to SPORTident Reader BT. It specifies services, characteristics, wire format, and the application-level request/response messages that are sent over the characteristics.
Terminology used within this document:
- Reader: SPORTident Reader BT device
- Client: The mobile/desktop app connecting to the reader
- User: The person operating the client app, who may interact with the reader by inserting/removing cards, configuring settings, etc
- SI-Card: SPORTident Card inserted into the reader
- Service/Characteristic UUIDs: Defined for the SPORTident Reader BT
- Message: An application payload written to / notified from a characteristic
Bluetooth Low Energy
BLE GATT (Generic Attribute Profile) defines how data is structured and exchanged between a BLE client and server.
- A service groups related functionality (for example, device settings or card readout).
- A characteristic inside a service contains a value and access properties (read, write, notify).
- The client discovers services and characteristics after connection, then subscribes to notifications where required.
- For Reader BT, requests are typically written by the client and responses are returned as notifications on the related characteristic.
In short: GATT provides the application-level data model on top of BLE, while this document specifies the exact UUIDs, message structure, and payload formats used by Reader BT.
Device Discovery
The reader must be in advertising mode, which is activated with the “Service/OFF” instruction card (see the Reader BT documentation).
The client then needs to scan for peripherals advertising the primary service UUID:
- Primary service UUID used for scanning:
bd510001-6aec-4628-a146-f3e95bc49e62 - Note: The reader advertises the primary service UUID but not the card readout or backup service UUIDs, so scanning should target the primary service.
- Note: BLE scanning is 20 seconds, which matches the time the reader remains in advertising mode.
- Note: Depending on the platform/OS, additional filtering by device name prefix (e.g. “Reader BT”) may be possible and can help to reduce noise from non-reader devices.
Connecting
Connect to a discovered (or known) device by its BLE device ID (MAC address).
Depending on the BLE library and operating system used, a maximum MTU length (517) may be required.
After connecting, the client may validate that required services exist by enumerating services and checking UUIDs.
Services and Characteristics
Overview
All UUIDs below are 128-bit UUIDs. Reader BT UUIDs starts with the 32 bit identifier bd5100xx, where xx specifies the GATT service or characteristic.
Generally and unless stated otherwise: The client writes requests to a characteristic. The reader replies via a notification on the same characteristic (or a service-specific notify characteristic). All client > reader writes must be performed as Write With Response. (For the BLE uninitiated, Write With Response essentially means a write with an acknowledgement that is not visible at the application layer.)
A client should subscribe to the relevant services/characteristics:
- Device settings and infos
- Subscribe to the Read settings characteristic
- Card data readout
- Subscribe to the Card state characteristic
- Subscribe to the Card data characteristic
- Read data from the device memory
- Subscribe to the Sessions characteristic
Settings service
Service for configuring device settings and requesting device information.
Service UUID: bd510001-6aec-4628-a146-f3e95bc49e62
Characteristics:
Read settings (bd510002)- Characteristic UUID:
bd510002-6aec-4628-a146-f3e95bc49e62 - Properties: Notify, Write With Response
- Direction: bidirectional
- Used for: reading device info, code number and other settings
- Characteristic UUID:
Write settings (bd510003)- Characteristic UUID:
bd510003-6aec-4628-a146-f3e95bc49e62
- Properties: Write With Response, Write Without Response
- Direction: Client > Reader
- Used for: writing station configuration such as code number, sleep mode, etc
- Characteristic UUID:
Card readout service
Service for reading data from an SI-Card.
Service UUID: bd510011-6aec-4628-a146-f3e95bc49e62
Characteristics:
Card state (bd510012)- Characteristic UUID:
bd510012-6aec-4628-a146-f3e95bc49e62 - Properties: Notify
- Direction: Reader > Client (notifications)
- Used for: card insert/remove state changes. If the station is in Auto Card Readout mode, a card insert notification triggers an automatic readout
- Characteristic UUID:
Card data (bd510013)- Characteristic UUID:
bd510013-6aec-4628-a146-f3e95bc49e62 - Properties: Notify, Write With Response
- Direction: bidirectional
- Used for: readout requests, readout data (possibly segmented), and feedback commands.
- Characteristic UUID:
Sessions service
A service for reading data from the device’s memory.
Service UUID: bd510031-6aec-4628-a146-f3e95bc49e62
Characteristics:
Sessions (bd510032)- Characteristic UUID:
bd510032-6aec-4628-a146-f3e95bc49e62 - Properties: Notify, Write With Response
- Direction: bidirectional
- Used for: session lookup table requests/responses and session data upload
- Characteristic UUID:
Wire format
Message structure
All multi-byte integers are little-endian. Every message begins with a 4-byte header. The base message structure is:
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | uint16 | message_id | Message ID (see below) |
| 2 | 2 | uint16 | payload_length | Number of payload bytes following the header |
| 4 | N | byte[] | payload | Payload bytes, length defined by payload_length |
Use the message_id to identify the message type and decode the payload accordingly (see Messages).
Message segmentation
The BLE transport may deliver large payloads (notably card readout and backup transfers) split across multiple notifications. The client must support reassembly via a dedicated message, the wrapper message (message ID 0xA101) whose payload contains a segment of the original unsegmented message.
Wrapper message payload:
| Offset (within payload) | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 1 | uint8 | packet_flag | 0x01 first, 0x00 subsequentPacket, 0x02 last (SegmentMarker) |
If packet_flag == 0x01 (First packet):
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 1 | 4 | uint32 | total_message_length | Expected length (bytes) of the reassembled unsegmented message |
| 5 | N | byte[] | segment | First segment bytes |
If packet_flag == 0x00 (Continuation) or 0x02 (Last):
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 1 | N | byte[] | segment | Segment bytes |
Reassembly rules:
- On
Firstpacket: clear buffer, storetotal_message_length, appendsegment. - On
SubsequentPacket: appendsegment. - On
Last: appendsegment, then buffer length MUST equaltotal_message_length. - After successful reassembly: treat the reassembled bytes as a normal unsegmented message starting with the 4-byte base header.
Messages
Overview
This section defines payload layouts for the message IDs currently used by Reader BT. “Payload” below refers to bytes after the 4-byte base header (see Message structure).
The following table gives an overview of all defined messages:
| Name | Message ID | Service/Characteristic | Direction | Notes |
|---|---|---|---|---|
| CardStateChange | 0x1101 | Card readout / Card state | Reader > Client (notify) | Card insert/remove events |
| CardDataReadoutMinimalData / CardDataReadoutCompleteData | 0x1102 / 0x1103 | Card readout / Card data | Client > Reader (write) + Reader > Client (notify) | Minimal/complete card readout request/response |
| Feedback | 0x1110 | Card readout / Card data | Client > Reader (write) | Trigger station feedback (LED/Buzzer) |
| ReadDeviceInfo | 0x010E | Settings / Read settings | Client > Reader (write to Read settings) + Reader > Client (notify on Read settings) | Request device information |
| ReadAllSettings | 0x010C | Settings / Read settings | Client > Reader (write to Read settings) + Reader > Client (notify on Read settings) | Request all station settings |
| WriteAllSettings | 0x010D | Settings / Write settings | Client > Reader (write) | Write all station settings |
| SetToSleepMode | 0x0101 | Settings / Write settings | Client > Reader (write) | Put station to sleep mode |
| ReadAvailableSessionsRequest | 0x3101 | Sessions / Sessions | Client > Reader (write) | Request session lookup table page |
| ReadAvailableSessionsResponse | 0x3103 | Sessions / Sessions | Reader > Client (notify) | Response with session lookup table page |
| ReadSessionDataRequest | 0x3102 | Sessions / Sessions | Client > Reader (write) | Request session data by session number |
| ReadSessionDataResponse | 0x3104 | Sessions / Sessions | Reader > Client (notify) | Response with session data (may be segmented) |
Card state change
- Message ID:
0x1101 - Characteristic: notify on Card state (bd510012)
4 byte message header, followed by 7 bytes payload :
| Offset | Size | Type | Name | Notes |
|---|---|---|---|---|
| 0 | 4 | uint32 | card_number | SPORTident card number |
| 4 | 1 | uint8 | state | 0 = Out, 1 = In |
| 5 | 2 | uint16 | code_number | Control code number |
Card readout
There are 2 messages for reading data from a card - minimal and complete. Minimal contains only the card number and punches. Complete contains information about the card owner and production information.
- Minimal data message ID:
0x1102 - Complete data message ID:
0x1103 - Characteristic: notify on
Card data (bd510013)(may be segmented)
4 byte message header, followed by payload :
| Offset (from start of payload) | Size | Type | Name | Notes |
|---|---|---|---|---|
| 0 | 4 | uint32 | card_number | |
| 4 | 1 | uint8 | card_family | See “Card family” below |
| 5 | 2 | uint16 | punch_count | Number of punch records |
| 7 | punch_count * 8 | struct[] | punches | Each punch record is 8 bytes |
| 7 + punches | 13 (optional) | bytes | SIAC_production_data | Present only for complete + card_family = SIAC and 8000000 <= card_number < 9000000 |
| … | variable (optional) | bytes | owner_data | Present only for complete and if enough bytes remain; starts with 1 byte character_set and then NUL-terminated/padded string bytes |
Punch record (8 bytes):
| Offset | Size | Type | Name | Notes |
|---|---|---|---|---|
| 0 | 1 | uint8 | control_info | Bit field used for beacon and radio mode (see decoding below) |
| 1 | 1 | uint8 | punch_type | Encoded punch type |
| 2 | 2 | uint16 | control_code | Control Code number |
| 4 | 4 | uint32 | time_in_ms | Milliseconds in week (Sun 00:00:00 = 0) |
control_info (uint8) decoding (Only for supported SPORTident cards (SIAC), others have the default value 0x00):
- Bits 0..4 are reserved for future
- Beacon mode - timing / punching mode flag:
- if bit 5 set then punching mode used; by default timing mode (used also for direct punching)
- Radio mode (2-bit enum in bits 6..7):
radio_mode = (control_type & 0xC0) >> 6- values :
0=No1=Last2=All3=AllNew
Punch type values (uint8)
0= Undefined1= Clear2= Check3= Start4= StartReserve5= Finish6= FinishReserve7= Control
The punch time is week-based and in milliseconds since Sunday morning 00:00:00.
Example:
time_in_ms = 183845000day_index = floor(183845000 / 86400000) = 2-> Tuesday (0= Sunday,1= Monday,2= Tuesday)time_of_day_ms = 183845000 % 86400000 = 1104500011,045,000 ms = 03:04:05.000
So 183845000 represents Tuesday 03:04:05.000.
Card family values (uint8):
1=SI-Card92=SI-Card84=SI-pCard15=SIAC
The owner data is a string, terminated by 0x00. The data is separated by a semicolon ( ; ), the character set depends on character_set byte and possible codings are 1 (default) ISO8859-1 and 17 (ChineseSimplified) GB2312. The number of owner fields depends on the card family.
Owner data fields:
| Field | 8/9 | SIAC/pCard |
|---|---|---|
First name | X | X |
Last name | X | X |
Sex | - | X |
Year of birth | - | X |
Club | - | X |
Email | - | X |
Mobile | - | X |
City | - | X |
Street | - | X |
Zip | - | X |
Country | - | X |
Owner data size (bytes) for complete readout:
SI-Card8: 104SI-Card9: 24SI-pCardorSIAC: 128
SIAC production data (13 bytes)
Present only for complete readout (message Id: 0x1103) when:
card_family = SIAC8000000 <= card_number < 9000000
Size: 13 bytes
Layout:
Offset (within SIAC_production_data) | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 1 | uint8 | hw_version_raw | Hardware version; formatted as major.minor via hw_version_raw / 10 and hw_version_raw % 10 |
| 1 | 1 | uint8 | sw_version_raw | Software version; formatted as major.minor via sw_version_raw / 10 and sw_version_raw % 10 |
| 2 | 2 | uint16 | signal_count | Feedback cycle counter |
| 4 | 2 | uint16 | clear_count | Clear counter |
| 6 | 2 | uint16 | battery_mv | Battery voltage in millivolts |
| 8 | 1 | uint8 | battery_year | Years since 2000 (0 => 2000) |
| 9 | 1 | uint8 | battery_month | 1..12 |
| 10 | 1 | uint8 | battery_day | 1..31 |
| 11 | 1 | uint8 | production_year | Years since 2000 (0 => 2000) |
| 12 | 1 | uint8 | production_month | 1..12 |
Decoding notes:
battery_yearandproduction_yearare stored as years since 2000- Battery date is represented as a full date
YYYY-MM-DD - Production date is represented as
YYYY-MM
Feedback
The application can inform the user about the success of reading data. Currently, the Reader BT supports 2 feedback types: Feedback_Ok (short flash/beep), and Feedback_Error (longer flash/beep pattern). Feedback is triggered by writing a message with the corresponding feedback_type to the card data characteristic.
Feedback does not depend on whether the SI-Card is in the device or not.
- Message ID:
0x1110 - Characteristic: write to
Card data (bd510013)
4 byte message header, followed by 1 byte payload:
| Offset | Size | Type | Name |
|---|---|---|---|
| 0 | 1 | uint8 | feedback_type |
feedback_type values:
1=Feedback_Ok- short flash/beep2=Feedback_Error- longer flash/beep
Read device info
The response contains the values of the Reader BT device - production date, serial number, etc.
To request device information, write message 0x010E to the Read settings (bd510002) characteristic with no payload (only 4-byte header).
Request:
- Message ID:
0x010E - Characteristic: write to
Read settings (bd510002) - Payload: (empty)
Response:
- Message ID:
0x010E - Characteristic: notify on
Read settings (bd510002)
4 byte message header, followed by payload layout:
| Offset | Size | Type | Name | Note |
|---|---|---|---|---|
| 0 | 4 | uint32 | serial_number | |
| 4 | 2 | uint16 | device_type | Device type identifier (e.g. 0x00A7) |
| 6 | 2 | uint8[2] | hw_version | { major, minor } |
| 8 | 4 | struct | production_date | { year:uint16, month:uint8, day:uint8 } |
| 12 | 4 | struct | battery_date | { year:uint16, month:uint8, day:uint8 } |
| 16 | variable | byte[] | sw_version_ascii | ASCII, NUL-terminated / padded |
Note: The Reader BT’s device type is 0x00A7 (167).
Read all settings
To request all Reader BT settings, write message 0x010C to the Read settings (bd510002) characteristic with no payload (only 4-byte header).
Request:
- Message ID:
0x010C - Characteristic: write to
Read settings (bd510002) - Payload: (empty)
Response:
- Message ID:
0x010C - Characteristic: notify on
Read settings (bd510002)
4 byte message header, 10 bytes payload layout:
| Offset | Size | Type | Name | Notes |
|---|---|---|---|---|
| 0 | 2 | uint16 | code_number | Control number |
| 2 | 1 | uint8 | auto_read | Boolean - 1: Auto Card Readout is enabled in device |
| 3 | 7 | reserved | reserved | Reserved for future |
Last 7 bytes are reserved for future use.
Write all settings
- Message ID:
0x010D - Characteristic: write to
Write settings (bd510003)
Method details:
- Payload encoding matches
Read all settingsand uses the same layout as the read-all-settings response above. - The BLE transport uses Write With Response at the GATT level.
Read available sessions request
Reader BT memory is divided into sessions. A new session is created each time you connect. The last session is the current session.
The session table is like a circular buffer, a maximum of 291 sessions are stored in the buffer, older ones are overwritten.
The list of sessions is divided into pages, each page has maximum 5 records. Page 0 is the newest. To find out how many pages there are, read page 0 first.
- Message ID:
0x3101 - Characteristic: write to
Sessions (bd510032)
4 byte message header, followed by 1 byte payload:
| Offset | Size | Type | Name | Notes |
|---|---|---|---|---|
| 0 | 1 | uint8 | page_number | 0-based |
Read available sessions response
- Message ID:
0x3103 - Characteristic: notify on
Sessions (bd510032)
4 byte message header, payload header:
| Offset | Size | Type | Name |
|---|---|---|---|
| 0 | 1 | uint8 | page_number |
| 1 | 1 | uint8 | total_pages |
| 2 | 1 | uint8 | entries_count |
Then entries_count session entries follow.
Session lookup entry (20 bytes):
| Offset | Size | Type | Name | Notes |
|---|---|---|---|---|
| 0 | 2 | uint16 | session_number | |
| 2 | 8 | uint64 | start_time | Unix time in seconds (or 0 as “unknown”) |
| 10 | 8 | uint64 | end_time | Unix time in seconds (or duration in seconds when start_time == 0) |
| 18 | 2 | uint16 | number_of_readouts |
Read session data request
- Message ID:
0x3102 - Characteristic: write to
Sessions (bd510032)
4 byte message header, payload:
| Offset | Size | Type | Name |
|---|---|---|---|
| 0 | 2 | uint16 | session_number |
Session number is obtained from the lookup table entries described above.
Read session data response
- Message ID:
0x3104 - Characteristic: notify on
Sessions (bd510032)(may be segmented)
4 byte message header, payload header:
| Offset | Size | Type | Name |
|---|---|---|---|
| 0 | 2 | uint16 | session_number |
| 2 | 2 | uint16 | number_of_readouts |
| 4 | 4 | uint32 | session_data_length |
Then follows a concatenation of number_of_readouts embedded card readout messages, each encoded as:
- 4-byte base header (instruction + payload_length)
payload_lengthbytes card readout payload
Each embedded readout’s message_id is expected to be either 0x1102 (minimal) or 0x1103 (complete).
Recommended client workflow
- Scan for devices advertising the Reader BT’s Settings service UUID or device name, starting with “Reader BT”
- Connect to the selected device
- Subscribe to needed services
- Settings for configuration/info
- Card readout for live readout
- Sessions for backup memory session download
- (Optional) Request device info, code number, and other settings
- For live readout
- Wait for
CardStateChangenotification then requestCardDataReadout - Optionally trigger feedback after successful
CardDataReadoutevent
- Wait for
- For backup session download
- Request lookup table page(s), then request session data