Coverage for src / bluetooth_sig / gatt / characteristics / sc_control_point.py: 100%
32 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-03 16:41 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-03 16:41 +0000
1"""SC Control Point characteristic (0x2A55).
3Speed and Cadence sensor control point for calibration,
4cumulative value, and sensor location management.
6References:
7 Bluetooth SIG Cycling Speed and Cadence / Running Speed and Cadence
8 org.bluetooth.characteristic.sc_control_point (GSS YAML)
9"""
11from __future__ import annotations
13from enum import IntEnum
15import msgspec
17from ..context import CharacteristicContext
18from .base import BaseCharacteristic
19from .utils import DataParser
22class SCControlPointOpCode(IntEnum):
23 """SC Control Point Op Codes."""
25 SET_CUMULATIVE_VALUE = 0x01
26 START_SENSOR_CALIBRATION = 0x02
27 UPDATE_SENSOR_LOCATION = 0x03
28 REQUEST_SUPPORTED_SENSOR_LOCATIONS = 0x04
29 RESPONSE_CODE = 0x10
32class SCControlPointResponseValue(IntEnum):
33 """SC Control Point Response Values."""
35 SUCCESS = 0x01
36 OP_CODE_NOT_SUPPORTED = 0x02
37 INVALID_PARAMETER = 0x03
38 OPERATION_FAILED = 0x04
41class SCControlPointData(msgspec.Struct, frozen=True, kw_only=True):
42 """Parsed data from SC Control Point.
44 Attributes:
45 opcode: The operation code.
46 parameter: Raw parameter bytes (variable per opcode). Empty if none.
48 """
50 opcode: SCControlPointOpCode
51 parameter: bytes = b""
54class SCControlPointCharacteristic(BaseCharacteristic[SCControlPointData]):
55 """SC Control Point characteristic (0x2A55).
57 org.bluetooth.characteristic.sc_control_point
59 Control point for Speed and Cadence sensor procedures.
60 ROLE: CONTROL
61 """
63 min_length = 1
64 allow_variable_length = True
66 def _decode_value(
67 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
68 ) -> SCControlPointData:
69 """Parse SC Control Point data.
71 Format: OpCode (uint8) + Parameter (variable).
72 """
73 opcode = SCControlPointOpCode(DataParser.parse_int8(data, 0, signed=False))
74 parameter = bytes(data[1:])
76 return SCControlPointData(
77 opcode=opcode,
78 parameter=parameter,
79 )
81 def _encode_value(self, data: SCControlPointData) -> bytearray:
82 """Encode SC Control Point data."""
83 result = bytearray()
84 result.extend(DataParser.encode_int8(int(data.opcode), signed=False))
85 result.extend(data.parameter)
86 return result