src.bluetooth_sig.gatt.characteristics.templates

Coding templates for characteristic composition patterns.

This module provides reusable coding template classes that can be composed into characteristics via dependency injection. Templates are pure coding strategies that do NOT inherit from BaseCharacteristic.

All templates follow the CodingTemplate protocol and can be used by both SIG and custom characteristics through composition.

Pipeline architecture:

bytes → [Extractor] → raw_int → [Translator] → typed_value

Templates that handle single-field data expose extractor and translator properties for pipeline access. Complex templates (multi-field, variable-length) keep monolithic decode/encode since there’s no single raw value to intercept.

Classes

Name

Description

CodingTemplate

Abstract base class for coding templates.

ConcentrationTemplate

Template for concentration measurements with configurable resolution.

EnumTemplate

Template for IntEnum encoding/decoding with configurable byte size.

Float32Template

Template for IEEE-754 32-bit float parsing.

IEEE11073FloatTemplate

Template for IEEE 11073 SFLOAT format (16-bit medical device float).

PercentageTemplate

Template for percentage values (0-100%) using uint8.

PressureTemplate

Template for pressure measurements (uint32, 0.1 Pa resolution).

ScaledSint16Template

Template for scaled 16-bit signed integer.

ScaledSint24Template

Template for scaled 24-bit signed integer with configurable resolution and offset.

ScaledSint8Template

Template for scaled 8-bit signed integer.

ScaledUint16Template

Template for scaled 16-bit unsigned integer.

ScaledUint24Template

Template for scaled 24-bit unsigned integer with configurable resolution and offset.

ScaledUint32Template

Template for scaled 32-bit unsigned integer with configurable resolution and offset.

ScaledUint8Template

Template for scaled 8-bit unsigned integer.

Sint16Template

Template for 16-bit signed integer parsing (-32768 to 32767).

Sint8Template

Template for 8-bit signed integer parsing (-128 to 127).

TemperatureTemplate

Template for standard Bluetooth SIG temperature format (sint16, 0.01°C resolution).

TimeData

Time characteristic data structure.

TimeDataTemplate

Template for Bluetooth SIG time data parsing (10 bytes).

Uint16Template

Template for 16-bit unsigned integer parsing (0-65535).

Uint24Template

Template for 24-bit unsigned integer parsing (0-16777215).

Uint32Template

Template for 32-bit unsigned integer parsing.

Uint8Template

Template for 8-bit unsigned integer parsing (0-255).

Utf16StringTemplate

Template for UTF-16LE string parsing with variable length.

Utf8StringTemplate

Template for UTF-8 string parsing with variable length.

Vector2DData

2D vector measurement data.

Vector2DTemplate

Template for 2D vector measurements (x, y float32 components).

VectorData

3D vector measurement data.

VectorTemplate

Template for 3D vector measurements (x, y, z float32 components).

Module Contents

class src.bluetooth_sig.gatt.characteristics.templates.CodingTemplate

Bases: abc.ABC, Generic[T_co]

Abstract base class for coding templates.

Templates are pure coding utilities that don’t inherit from BaseCharacteristic. They provide coding strategies that can be injected into characteristics. All templates MUST inherit from this base class and implement the required methods.

Generic over T_co, the type of value produced by _decode_value. Concrete templates specify their return type, e.g., CodingTemplate[int].

Pipeline Integration:

Simple templates (single-field) expose extractor and translator properties for the decode/encode pipeline. Complex templates return None for these properties.

abstractmethod decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) T_co

Decode raw bytes to typed value.

Parameters:
  • data – Raw bytes to parse

  • offset – Byte offset to start parsing from

  • ctx – Optional context for parsing

Returns:

Parsed value of type T_co

abstractmethod encode_value(value: T_co) bytearray

Encode typed value to raw bytes.

Parameters:

value – Typed value to encode

Returns:

Raw bytes representing the value

property data_size: int
Abstractmethod:

Size of data in bytes that this template handles.

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor | None

Get the raw byte extractor for pipeline access.

Returns None for complex templates where extraction isn’t separable.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[Any] | None

Get the value translator for pipeline access.

Returns None for complex templates where translation isn’t separable.

class src.bluetooth_sig.gatt.characteristics.templates.ConcentrationTemplate(resolution: float = 1.0)

Bases: CodingTemplate[float]

Template for concentration measurements with configurable resolution.

Used for environmental sensors like CO2, VOC, particulate matter, etc.

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) float

Parse concentration with resolution.

encode_value(value: float) bytearray

Encode concentration value to bytes.

classmethod from_letter_method(M: int, d: int, b: int = 0) ConcentrationTemplate

Create instance using Bluetooth SIG M, d, b parameters.

Parameters:
  • M – Multiplier factor

  • d – Decimal exponent (10^d)

  • b – Offset to add to raw value before scaling

Returns:

ConcentrationTemplate instance

property data_size: int

2 bytes.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get extractor from underlying scaled template.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[float]

Return the linear translator from the underlying scaled template.

class src.bluetooth_sig.gatt.characteristics.templates.EnumTemplate(enum_class: type[T], extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor)

Bases: CodingTemplate[T]

Template for IntEnum encoding/decoding with configurable byte size.

Maps raw integer bytes to Python IntEnum instances through extraction and validation. Supports any integer-based enum with any extractor (UINT8, UINT16, SINT8, etc.).

This template validates enum membership explicitly, supporting non-contiguous enum ranges (e.g., values 0, 2, 5, 10).

Pipeline Integration:

bytes → [extractor] → raw_int → [IDENTITY translator] → int → enum constructor

Examples

>>> class Status(IntEnum):
...     IDLE = 0
...     ACTIVE = 1
...     ERROR = 2
>>>
>>> # Create template with factory method
>>> template = EnumTemplate.uint8(Status)
>>>
>>> # Or with explicit extractor
>>> template = EnumTemplate(Status, UINT8)
>>>
>>> # Decode from bytes
>>> status = template.decode_value(bytearray([0x01]))  # Status.ACTIVE
>>>
>>> # Encode enum to bytes
>>> data = template.encode_value(Status.ERROR)  # bytearray([0x02])
>>>
>>> # Encode int to bytes (also supported)
>>> data = template.encode_value(2)  # bytearray([0x02])
decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) T

Decode bytes to enum instance.

Parameters:
  • data – Raw bytes from BLE characteristic

  • offset – Starting offset in data buffer

  • ctx – Optional context for parsing

Returns:

Enum instance of type T

Raises:
encode_value(value: T | int) bytearray

Encode enum instance or int to bytes.

Parameters:

value – Enum instance or integer value to encode

Returns:

Encoded bytes

Raises:

ValueError – If value not a valid enum member

classmethod sint16(enum_class: type[T]) EnumTemplate[T]

Create EnumTemplate for 2-byte signed enum.

Parameters:

enum_class – IntEnum subclass with values -32768 to 32767

Returns:

Configured EnumTemplate instance

classmethod sint32(enum_class: type[T]) EnumTemplate[T]

Create EnumTemplate for 4-byte signed enum.

Parameters:

enum_class – IntEnum subclass with values -2147483648 to 2147483647

Returns:

Configured EnumTemplate instance

classmethod sint8(enum_class: type[T]) EnumTemplate[T]

Create EnumTemplate for 1-byte signed enum.

Parameters:

enum_class – IntEnum subclass with values -128 to 127

Returns:

Configured EnumTemplate instance

Example

>>> class Temperature(IntEnum):
...     FREEZING = -10
...     NORMAL = 0
...     HOT = 10
>>> template = EnumTemplate.sint8(Temperature)
classmethod uint16(enum_class: type[T]) EnumTemplate[T]

Create EnumTemplate for 2-byte unsigned enum.

Parameters:

enum_class – IntEnum subclass with values 0-65535

Returns:

Configured EnumTemplate instance

Example

>>> class ExtendedStatus(IntEnum):
...     STATE_1 = 0x0100
...     STATE_2 = 0x0200
>>> template = EnumTemplate.uint16(ExtendedStatus)
classmethod uint32(enum_class: type[T]) EnumTemplate[T]

Create EnumTemplate for 4-byte unsigned enum.

Parameters:

enum_class – IntEnum subclass with values 0-4294967295

Returns:

Configured EnumTemplate instance

classmethod uint8(enum_class: type[T]) EnumTemplate[T]

Create EnumTemplate for 1-byte unsigned enum.

Parameters:

enum_class – IntEnum subclass with values 0-255

Returns:

Configured EnumTemplate instance

Example

>>> class Status(IntEnum):
...     IDLE = 0
...     ACTIVE = 1
>>> template = EnumTemplate.uint8(Status)
property data_size: int

Return byte size required for encoding.

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Return extractor for pipeline access.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[int]

Get IDENTITY translator for enums (no scaling needed).

class src.bluetooth_sig.gatt.characteristics.templates.Float32Template

Bases: CodingTemplate[float]

Template for IEEE-754 32-bit float parsing.

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) float

Parse IEEE-754 32-bit float.

encode_value(value: float) bytearray

Encode float32 value to bytes.

property data_size: int

4 bytes.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get float32 extractor.

class src.bluetooth_sig.gatt.characteristics.templates.IEEE11073FloatTemplate

Bases: CodingTemplate[float]

Template for IEEE 11073 SFLOAT format (16-bit medical device float).

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) float

Parse IEEE 11073 SFLOAT format.

encode_value(value: float) bytearray

Encode value to IEEE 11073 SFLOAT format.

property data_size: int

2 bytes.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get uint16 extractor for raw bits.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.SfloatTranslator

Get SFLOAT translator.

class src.bluetooth_sig.gatt.characteristics.templates.PercentageTemplate

Bases: CodingTemplate[int]

Template for percentage values (0-100%) using uint8.

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) int

Parse percentage value.

encode_value(value: int) bytearray

Encode percentage value to bytes.

property data_size: int

1 byte.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get uint8 extractor.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.IdentityTranslator

Return identity translator since validation is separate from translation.

class src.bluetooth_sig.gatt.characteristics.templates.PressureTemplate

Bases: CodingTemplate[float]

Template for pressure measurements (uint32, 0.1 Pa resolution).

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) float

Parse pressure in 0.1 Pa resolution (returns Pa).

encode_value(value: float) bytearray

Encode pressure to bytes.

property data_size: int

4 bytes.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get extractor from underlying scaled template.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[float]

Return the linear translator from the underlying scaled template.

class src.bluetooth_sig.gatt.characteristics.templates.ScaledSint16Template(scale_factor: float = 0.01, offset: int = 0)

Bases: ScaledTemplate

Template for scaled 16-bit signed integer.

Used for signed values that need decimal precision encoded as integers. Can be initialized with scale_factor/offset or Bluetooth SIG M, d, b parameters. Formula: value = scale_factor * (raw + offset) or value = M * 10^d * (raw + b) Example: Temperature -10.5°C stored as -1050 with scale_factor=0.01, offset=0 or M=1, d=-2, b=0

property data_size: int

2 bytes.

Type:

Size

class src.bluetooth_sig.gatt.characteristics.templates.ScaledSint24Template(scale_factor: float = 0.01, offset: int = 0)

Bases: ScaledTemplate

Template for scaled 24-bit signed integer with configurable resolution and offset.

Used for signed values encoded in 3 bytes. Example: Elevation 500.00m stored as bytes with scale_factor=0.01, offset=0

property data_size: int

3 bytes.

Type:

Size

class src.bluetooth_sig.gatt.characteristics.templates.ScaledSint8Template(scale_factor: float = 1.0, offset: int = 0)

Bases: ScaledTemplate

Template for scaled 8-bit signed integer.

Used for signed values that need decimal precision encoded as integers. Can be initialized with scale_factor/offset or Bluetooth SIG M, d, b parameters. Formula: value = scale_factor * (raw + offset) or value = M * 10^d * (raw + b) Example: Temperature with scale_factor=0.01, offset=0 or M=1, d=-2, b=0

property data_size: int

1 byte.

Type:

Size

class src.bluetooth_sig.gatt.characteristics.templates.ScaledUint16Template(scale_factor: float = 1.0, offset: int = 0)

Bases: ScaledTemplate

Template for scaled 16-bit unsigned integer.

Used for values that need decimal precision encoded as integers. Can be initialized with scale_factor/offset or Bluetooth SIG M, d, b parameters. Formula: value = scale_factor * (raw + offset) or value = M * 10^d * (raw + b) Example: Temperature 25.5°C stored as 2550 with scale_factor=0.01, offset=0 or M=1, d=-2, b=0

property data_size: int

2 bytes.

Type:

Size

class src.bluetooth_sig.gatt.characteristics.templates.ScaledUint24Template(scale_factor: float = 1.0, offset: int = 0)

Bases: ScaledTemplate

Template for scaled 24-bit unsigned integer with configurable resolution and offset.

Used for values encoded in 3 bytes as unsigned integers. Example: Illuminance 1000 lux stored as bytes with scale_factor=1.0, offset=0

property data_size: int

3 bytes.

Type:

Size

class src.bluetooth_sig.gatt.characteristics.templates.ScaledUint32Template(scale_factor: float = 0.1, offset: int = 0)

Bases: ScaledTemplate

Template for scaled 32-bit unsigned integer with configurable resolution and offset.

property data_size: int

4 bytes.

Type:

Size

class src.bluetooth_sig.gatt.characteristics.templates.ScaledUint8Template(scale_factor: float = 1.0, offset: int = 0)

Bases: ScaledTemplate

Template for scaled 8-bit unsigned integer.

Used for unsigned values that need decimal precision encoded as integers. Can be initialized with scale_factor/offset or Bluetooth SIG M, d, b parameters. Formula: value = scale_factor * (raw + offset) or value = M * 10^d * (raw + b) Example: Uncertainty with scale_factor=0.1, offset=0 or M=1, d=-1, b=0

property data_size: int

1 byte.

Type:

Size

class src.bluetooth_sig.gatt.characteristics.templates.Sint16Template

Bases: CodingTemplate[int]

Template for 16-bit signed integer parsing (-32768 to 32767).

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) int

Parse 16-bit signed integer.

encode_value(value: int) bytearray

Encode sint16 value to bytes.

property data_size: int

2 bytes.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get sint16 extractor.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[int]

Return identity translator for no scaling.

class src.bluetooth_sig.gatt.characteristics.templates.Sint8Template

Bases: CodingTemplate[int]

Template for 8-bit signed integer parsing (-128 to 127).

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) int

Parse 8-bit signed integer.

encode_value(value: int) bytearray

Encode sint8 value to bytes.

property data_size: int

1 byte.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get sint8 extractor.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[int]

Return identity translator for no scaling.

class src.bluetooth_sig.gatt.characteristics.templates.TemperatureTemplate

Bases: CodingTemplate[float]

Template for standard Bluetooth SIG temperature format (sint16, 0.01°C resolution).

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) float

Parse temperature in 0.01°C resolution.

encode_value(value: float) bytearray

Encode temperature to bytes.

property data_size: int

2 bytes.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get extractor from underlying scaled template.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[float]

Return the linear translator from the underlying scaled template.

class src.bluetooth_sig.gatt.characteristics.templates.TimeData

Bases: msgspec.Struct

Time characteristic data structure.

adjust_reason: src.bluetooth_sig.types.gatt_enums.AdjustReason
date_time: datetime.datetime | None
day_of_week: src.bluetooth_sig.types.gatt_enums.DayOfWeek
fractions256: int
class src.bluetooth_sig.gatt.characteristics.templates.TimeDataTemplate

Bases: CodingTemplate[TimeData]

Template for Bluetooth SIG time data parsing (10 bytes).

Used for Current Time and Time with DST characteristics. Structure: Date Time (7 bytes) + Day of Week (1) + Fractions256 (1) + Adjust Reason (1)

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) TimeData

Parse time data from bytes.

encode_value(value: TimeData) bytearray

Encode time data to bytes.

ADJUST_REASON_MAX = 255
DAY_OF_WEEK_MAX = 7
FRACTIONS256_MAX = 255
LENGTH = 10
property data_size: int

10 bytes.

Type:

Size

class src.bluetooth_sig.gatt.characteristics.templates.Uint16Template

Bases: CodingTemplate[int]

Template for 16-bit unsigned integer parsing (0-65535).

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) int

Parse 16-bit unsigned integer.

encode_value(value: int) bytearray

Encode uint16 value to bytes.

property data_size: int

2 bytes.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get uint16 extractor.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[int]

Return identity translator for no scaling.

class src.bluetooth_sig.gatt.characteristics.templates.Uint24Template

Bases: CodingTemplate[int]

Template for 24-bit unsigned integer parsing (0-16777215).

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) int

Parse 24-bit unsigned integer.

encode_value(value: int) bytearray

Encode uint24 value to bytes.

property data_size: int

3 bytes.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get uint24 extractor.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[int]

Return identity translator for no scaling.

class src.bluetooth_sig.gatt.characteristics.templates.Uint32Template

Bases: CodingTemplate[int]

Template for 32-bit unsigned integer parsing.

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) int

Parse 32-bit unsigned integer.

encode_value(value: int) bytearray

Encode uint32 value to bytes.

property data_size: int

4 bytes.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get uint32 extractor.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[int]

Return identity translator for no scaling.

class src.bluetooth_sig.gatt.characteristics.templates.Uint8Template

Bases: CodingTemplate[int]

Template for 8-bit unsigned integer parsing (0-255).

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) int

Parse 8-bit unsigned integer.

encode_value(value: int) bytearray

Encode uint8 value to bytes.

property data_size: int

1 byte.

Type:

Size

property extractor: src.bluetooth_sig.gatt.characteristics.utils.extractors.RawExtractor

Get uint8 extractor.

property translator: src.bluetooth_sig.gatt.characteristics.utils.translators.ValueTranslator[int]

Return identity translator for no scaling.

class src.bluetooth_sig.gatt.characteristics.templates.Utf16StringTemplate(max_length: int = 256)

Bases: CodingTemplate[str]

Template for UTF-16LE string parsing with variable length.

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) str

Parse UTF-16LE string from remaining data.

encode_value(value: str) bytearray

Encode string to UTF-16LE bytes.

UNICODE_BOM = '\ufeff'
UNICODE_SURROGATE_END = 57343
UNICODE_SURROGATE_START = 55296
property data_size: int

Variable (0 to max_length, even bytes only).

Type:

Size

max_length = 256
class src.bluetooth_sig.gatt.characteristics.templates.Utf8StringTemplate(max_length: int = 256)

Bases: CodingTemplate[str]

Template for UTF-8 string parsing with variable length.

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) str

Parse UTF-8 string from remaining data.

encode_value(value: str) bytearray

Encode string to UTF-8 bytes.

property data_size: int

Variable (0 to max_length).

Type:

Size

max_length = 256
class src.bluetooth_sig.gatt.characteristics.templates.Vector2DData

Bases: msgspec.Struct

2D vector measurement data.

x_axis: float
y_axis: float
class src.bluetooth_sig.gatt.characteristics.templates.Vector2DTemplate

Bases: CodingTemplate[Vector2DData]

Template for 2D vector measurements (x, y float32 components).

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) Vector2DData

Parse 2D vector data.

encode_value(value: Vector2DData) bytearray

Encode 2D vector data to bytes.

property data_size: int

8 bytes (2 x float32).

Type:

Size

class src.bluetooth_sig.gatt.characteristics.templates.VectorData

Bases: msgspec.Struct

3D vector measurement data.

x_axis: float
y_axis: float
z_axis: float
class src.bluetooth_sig.gatt.characteristics.templates.VectorTemplate

Bases: CodingTemplate[VectorData]

Template for 3D vector measurements (x, y, z float32 components).

decode_value(data: bytearray, offset: int = 0, ctx: src.bluetooth_sig.gatt.context.CharacteristicContext | None = None) VectorData

Parse 3D vector data.

encode_value(value: VectorData) bytearray

Encode 3D vector data to bytes.

property data_size: int

12 bytes (3 x float32).

Type:

Size