Coverage for src / bluetooth_sig / gatt / characteristics / illuminance.py: 100%

12 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-18 11:17 +0000

1"""Illuminance characteristic implementation.""" 

2 

3from __future__ import annotations 

4 

5from ..context import CharacteristicContext 

6from .base import BaseCharacteristic 

7from .utils.data_parser import DataParser 

8 

9# pylint: disable=duplicate-code 

10# Justification: This file follows the standard BLE characteristic base class pattern, 

11# which is intentionally duplicated across multiple characteristic implementations. 

12# These patterns are required by Bluetooth SIG specifications and represent legitimate 

13# code duplication for protocol compliance. 

14 

15 

16class IlluminanceCharacteristic(BaseCharacteristic[float]): 

17 """Illuminance characteristic (0x2AFB). 

18 

19 Measures light intensity in lux (lumens per square meter). 

20 Uses uint24 (3 bytes) with 0.01 lux resolution. 

21 """ 

22 

23 resolution: float = 0.01 

24 

25 def _decode_value( 

26 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True 

27 ) -> float: 

28 """Decode illuminance characteristic. 

29 

30 Decodes a 24-bit unsigned integer representing illuminance in 0.01 lux increments 

31 per Bluetooth SIG Illuminance characteristic specification. 

32 

33 Args: 

34 data: Raw bytes from BLE characteristic (exactly 3 bytes, little-endian) 

35 ctx: Optional context for parsing (device info, flags, etc.) 

36 validate: Whether to validate ranges (default True) 

37 

38 Returns: 

39 Illuminance in lux 

40 

41 Raises: 

42 InsufficientDataError: If data is not exactly 3 bytes 

43 """ 

44 raw_value = DataParser.parse_int24(data, 0, signed=False) 

45 return raw_value * self.resolution 

46 

47 def _encode_value(self, data: float) -> bytearray: 

48 """Encode illuminance value.""" 

49 raw_value = int(data / self.resolution) 

50 return DataParser.encode_int24(raw_value, signed=False)