Coverage for src/bluetooth_sig/types/gatt_enums.py: 99%
171 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-30 00:10 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-30 00:10 +0000
1"""Core GATT enumerations for strong typing.
3Defines enums for GATT properties, value types, characteristic names,
4and other core BLE concepts to replace string usage with type-safe
5alternatives.
6"""
8from __future__ import annotations
10from enum import Enum
13class GattProperty(Enum):
14 """GATT characteristic properties defined by Bluetooth SIG."""
16 BROADCAST = "broadcast"
17 READ = "read"
18 WRITE_WITHOUT_RESPONSE = "write-without-response"
19 WRITE = "write"
20 NOTIFY = "notify"
21 INDICATE = "indicate"
22 AUTHENTICATED_SIGNED_WRITES = "authenticated-signed-writes"
23 EXTENDED_PROPERTIES = "extended-properties"
24 RELIABLE_WRITE = "reliable-write"
25 WRITABLE_AUXILIARIES = "writable-auxiliaries"
26 # Encryption and authentication properties
27 ENCRYPT_READ = "encrypt-read"
28 ENCRYPT_WRITE = "encrypt-write"
29 ENCRYPT_NOTIFY = "encrypt-notify"
30 AUTH_READ = "auth-read"
31 AUTH_WRITE = "auth-write"
32 AUTH_NOTIFY = "auth-notify"
35class ValueType(Enum):
36 """Data types for characteristic values."""
38 STRING = "string"
39 INT = "int"
40 FLOAT = "float"
41 BYTES = "bytes"
42 BOOL = "bool"
43 DATETIME = "datetime"
44 UUID = "uuid"
45 DICT = "dict"
46 VARIOUS = "various"
47 UNKNOWN = "unknown"
50class DataType(Enum):
51 """Bluetooth SIG data types from GATT specifications."""
53 BOOLEAN = "boolean"
54 UINT8 = "uint8"
55 UINT16 = "uint16"
56 UINT24 = "uint24"
57 UINT32 = "uint32"
58 UINT64 = "uint64"
59 SINT8 = "sint8"
60 SINT16 = "sint16"
61 SINT24 = "sint24"
62 SINT32 = "sint32"
63 SINT64 = "sint64"
64 FLOAT32 = "float32"
65 FLOAT64 = "float64"
66 UTF8S = "utf8s"
67 STRUCT = "struct"
68 MEDFLOAT16 = "medfloat16"
69 MEDFLOAT32 = "medfloat32"
70 VARIOUS = "various"
71 UNKNOWN = "unknown"
73 @classmethod
74 def from_string(cls, type_str: str | None) -> DataType:
75 """Convert string representation to DataType enum.
77 Args:
78 type_str: String representation of data type (case-insensitive)
80 Returns:
81 Corresponding DataType enum, or DataType.UNKNOWN if not found
82 """
83 if not type_str:
84 return cls.UNKNOWN
86 # Handle common aliases
87 type_str = type_str.lower()
88 aliases = {
89 "utf16s": cls.UTF8S, # TODO utf16s maps to UTF8S for now
90 "sfloat": cls.MEDFLOAT16, # IEEE-11073 16-bit SFLOAT
91 "float": cls.FLOAT32, # IEEE-11073 32-bit FLOAT
92 "variable": cls.STRUCT, # variable maps to STRUCT
93 }
95 if type_str in aliases:
96 return aliases[type_str]
98 # Try direct match
99 for member in cls:
100 if member.value == type_str:
101 return member
103 return cls.UNKNOWN
105 def to_value_type(self) -> ValueType:
106 """Convert DataType to internal ValueType enum.
108 Returns:
109 Corresponding ValueType for this data type
110 """
111 mapping = {
112 # Integer types
113 self.SINT8: ValueType.INT,
114 self.UINT8: ValueType.INT,
115 self.SINT16: ValueType.INT,
116 self.UINT16: ValueType.INT,
117 self.UINT24: ValueType.INT,
118 self.SINT32: ValueType.INT,
119 self.UINT32: ValueType.INT,
120 self.UINT64: ValueType.INT,
121 self.SINT64: ValueType.INT,
122 # Float types
123 self.FLOAT32: ValueType.FLOAT,
124 self.FLOAT64: ValueType.FLOAT,
125 self.MEDFLOAT16: ValueType.FLOAT,
126 self.MEDFLOAT32: ValueType.FLOAT,
127 # String types
128 self.UTF8S: ValueType.STRING,
129 # Boolean type
130 self.BOOLEAN: ValueType.BOOL,
131 # Struct/opaque data
132 self.STRUCT: ValueType.BYTES,
133 # Meta types
134 self.VARIOUS: ValueType.VARIOUS,
135 self.UNKNOWN: ValueType.UNKNOWN,
136 }
137 return mapping.get(self, ValueType.UNKNOWN)
139 def to_python_type(self) -> str:
140 """Convert DataType to Python type string.
142 Returns:
143 Corresponding Python type string
144 """
145 mapping = {
146 # Integer types
147 self.UINT8: "int",
148 self.UINT16: "int",
149 self.UINT24: "int",
150 self.UINT32: "int",
151 self.UINT64: "int",
152 self.SINT8: "int",
153 self.SINT16: "int",
154 self.SINT24: "int",
155 self.SINT32: "int",
156 self.SINT64: "int",
157 # Float types
158 self.FLOAT32: "float",
159 self.FLOAT64: "float",
160 self.MEDFLOAT16: "float",
161 self.MEDFLOAT32: "float",
162 # String types
163 self.UTF8S: "string",
164 # Boolean type
165 self.BOOLEAN: "boolean",
166 # Struct/opaque data
167 self.STRUCT: "bytes",
168 # Meta types
169 self.VARIOUS: "various",
170 self.UNKNOWN: "unknown",
171 }
172 return mapping.get(self, "bytes")
175class CharacteristicName(Enum):
176 """Enumeration of all supported GATT characteristic names."""
178 BATTERY_LEVEL = "Battery Level"
179 BATTERY_LEVEL_STATUS = "Battery Level Status"
180 TEMPERATURE = "Temperature"
181 TEMPERATURE_MEASUREMENT = "Temperature Measurement"
182 HUMIDITY = "Humidity"
183 PRESSURE = "Pressure"
184 UV_INDEX = "UV Index"
185 ILLUMINANCE = "Illuminance"
186 POWER_SPECIFICATION = "Power Specification"
187 HEART_RATE_MEASUREMENT = "Heart Rate Measurement"
188 BLOOD_PRESSURE_MEASUREMENT = "Blood Pressure Measurement"
189 INTERMEDIATE_CUFF_PRESSURE = "Intermediate Cuff Pressure"
190 BLOOD_PRESSURE_FEATURE = "Blood Pressure Feature"
191 CSC_MEASUREMENT = "CSC Measurement"
192 RSC_MEASUREMENT = "RSC Measurement"
193 CYCLING_POWER_MEASUREMENT = "Cycling Power Measurement"
194 CYCLING_POWER_FEATURE = "Cycling Power Feature"
195 CYCLING_POWER_VECTOR = "Cycling Power Vector"
196 CYCLING_POWER_CONTROL_POINT = "Cycling Power Control Point"
197 GLUCOSE_MEASUREMENT = "Glucose Measurement"
198 GLUCOSE_MEASUREMENT_CONTEXT = "Glucose Measurement Context"
199 GLUCOSE_FEATURE = "Glucose Feature"
200 MANUFACTURER_NAME_STRING = "Manufacturer Name String"
201 MODEL_NUMBER_STRING = "Model Number String"
202 SERIAL_NUMBER_STRING = "Serial Number String"
203 FIRMWARE_REVISION_STRING = "Firmware Revision String"
204 HARDWARE_REVISION_STRING = "Hardware Revision String"
205 SOFTWARE_REVISION_STRING = "Software Revision String"
206 DEVICE_NAME = "Device Name"
207 APPEARANCE = "Appearance"
208 WEIGHT_MEASUREMENT = "Weight Measurement"
209 WEIGHT_SCALE_FEATURE = "Weight Scale Feature"
210 BODY_COMPOSITION_MEASUREMENT = "Body Composition Measurement"
211 BODY_COMPOSITION_FEATURE = "Body Composition Feature"
212 # Environmental characteristics
213 DEW_POINT = "Dew Point"
214 HEAT_INDEX = "Heat Index"
215 WIND_CHILL = "Wind Chill"
216 TRUE_WIND_SPEED = "True Wind Speed"
217 TRUE_WIND_DIRECTION = "True Wind Direction"
218 APPARENT_WIND_SPEED = "Apparent Wind Speed"
219 APPARENT_WIND_DIRECTION = "Apparent Wind Direction"
220 MAGNETIC_DECLINATION = "Magnetic Declination"
221 ELEVATION = "Elevation"
222 MAGNETIC_FLUX_DENSITY_2D = "Magnetic Flux Density - 2D"
223 MAGNETIC_FLUX_DENSITY_3D = "Magnetic Flux Density - 3D"
224 BAROMETRIC_PRESSURE_TREND = "Barometric Pressure Trend"
225 POLLEN_CONCENTRATION = "Pollen Concentration"
226 RAINFALL = "Rainfall"
227 TIME_ZONE = "Time Zone"
228 LOCAL_TIME_INFORMATION = "Local Time Information"
229 # Gas sensor characteristics
230 AMMONIA_CONCENTRATION = "Ammonia Concentration"
231 CO2_CONCENTRATION = "Carbon Dioxide Concentration"
232 METHANE_CONCENTRATION = "Methane Concentration"
233 NITROGEN_DIOXIDE_CONCENTRATION = "Nitrogen Dioxide Concentration"
234 NON_METHANE_VOC_CONCENTRATION = "Non-Methane Volatile Organic Compounds Concentration"
235 OZONE_CONCENTRATION = "Ozone Concentration"
236 PM1_CONCENTRATION = "Particulate Matter - PM1 Concentration"
237 PM10_CONCENTRATION = "Particulate Matter - PM10 Concentration"
238 PM25_CONCENTRATION = "Particulate Matter - PM2.5 Concentration"
239 SULFUR_DIOXIDE_CONCENTRATION = "Sulfur Dioxide Concentration"
240 VOC_CONCENTRATION = "Volatile Organic Compounds Concentration"
241 # Power characteristics
242 ELECTRIC_CURRENT = "Electric Current"
243 ELECTRIC_CURRENT_RANGE = "Electric Current Range"
244 ELECTRIC_CURRENT_SPECIFICATION = "Electric Current Specification"
245 ELECTRIC_CURRENT_STATISTICS = "Electric Current Statistics"
246 VOLTAGE = "Voltage"
247 VOLTAGE_FREQUENCY = "Voltage Frequency"
248 VOLTAGE_SPECIFICATION = "Voltage Specification"
249 VOLTAGE_STATISTICS = "Voltage Statistics"
250 HIGH_VOLTAGE = "High Voltage"
251 AVERAGE_CURRENT = "Average Current"
252 AVERAGE_VOLTAGE = "Average Voltage"
253 SUPPORTED_POWER_RANGE = "Supported Power Range"
254 # Audio characteristics
255 NOISE = "Noise"
256 # Pulse oximetry
257 PULSE_OXIMETRY_CONTINUOUS_MEASUREMENT = "Pulse Oximetry Continuous Measurement"
258 LOCATION_AND_SPEED = "Location and Speed"
259 NAVIGATION = "Navigation"
260 POSITION_QUALITY = "Position Quality"
261 LN_FEATURE = "LN Feature"
262 LN_CONTROL_POINT = "LN Control Point"
263 SERVICE_CHANGED = "Service Changed"
264 ALERT_STATUS = "Alert Status"
265 RINGER_SETTING = "Ringer Setting"
266 RINGER_CONTROL_POINT = "Ringer Control Point"
269class ServiceName(Enum):
270 """Enumeration of all supported GATT service names."""
272 GENERIC_ACCESS = "Generic Access"
273 GENERIC_ATTRIBUTE = "Generic Attribute"
274 DEVICE_INFORMATION = "Device Information"
275 BATTERY_SERVICE = "Battery Service"
276 HEART_RATE = "Heart Rate"
277 BLOOD_PRESSURE = "Blood Pressure"
278 HEALTH_THERMOMETER = "Health Thermometer"
279 GLUCOSE = "Glucose"
280 CYCLING_SPEED_AND_CADENCE = "Cycling Speed and Cadence"
281 CYCLING_POWER = "Cycling Power"
282 RUNNING_SPEED_AND_CADENCE = "Running Speed and Cadence"
283 AUTOMATION_IO = "Automation IO"
284 ENVIRONMENTAL_SENSING = "Environmental Sensing"
285 BODY_COMPOSITION = "Body Composition"
286 WEIGHT_SCALE = "Weight Scale"
287 LOCATION_AND_NAVIGATION = "Location and Navigation"
288 PHONE_ALERT_STATUS = "Phone Alert Status"