Coverage for src / bluetooth_sig / gatt / characteristics / templates / ieee_float.py: 92%

38 statements  

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

1"""IEEE floating-point templates for medical and standard float formats. 

2 

3Covers IEEE11073FloatTemplate (SFLOAT 16-bit) and Float32Template (IEEE-754 32-bit). 

4""" 

5 

6from __future__ import annotations 

7 

8from ...context import CharacteristicContext 

9from ...exceptions import InsufficientDataError 

10from ..utils import DataParser 

11from ..utils.extractors import ( 

12 FLOAT32, 

13 UINT16, 

14 RawExtractor, 

15) 

16from ..utils.translators import ( 

17 SFLOAT, 

18 SfloatTranslator, 

19) 

20from .base import CodingTemplate 

21 

22 

23class IEEE11073FloatTemplate(CodingTemplate[float]): 

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

25 

26 @property 

27 def data_size(self) -> int: 

28 """Size: 2 bytes.""" 

29 return 2 

30 

31 @property 

32 def extractor(self) -> RawExtractor: 

33 """Get uint16 extractor for raw bits.""" 

34 return UINT16 

35 

36 @property 

37 def translator(self) -> SfloatTranslator: 

38 """Get SFLOAT translator.""" 

39 return SFLOAT 

40 

41 def decode_value( 

42 self, data: bytearray, offset: int = 0, ctx: CharacteristicContext | None = None, *, validate: bool = True 

43 ) -> float: 

44 """Parse IEEE 11073 SFLOAT format.""" 

45 if validate and len(data) < offset + 2: 

46 raise InsufficientDataError("IEEE11073 SFLOAT", data[offset:], 2) 

47 raw = self.extractor.extract(data, offset) 

48 return self.translator.translate(raw) 

49 

50 def encode_value(self, value: float, *, validate: bool = True) -> bytearray: 

51 """Encode value to IEEE 11073 SFLOAT format.""" 

52 raw = self.translator.untranslate(value) 

53 return self.extractor.pack(raw) 

54 

55 

56class Float32Template(CodingTemplate[float]): 

57 """Template for IEEE-754 32-bit float parsing.""" 

58 

59 @property 

60 def data_size(self) -> int: 

61 """Size: 4 bytes.""" 

62 return 4 

63 

64 @property 

65 def extractor(self) -> RawExtractor: 

66 """Get float32 extractor.""" 

67 return FLOAT32 

68 

69 def decode_value( 

70 self, data: bytearray, offset: int = 0, ctx: CharacteristicContext | None = None, *, validate: bool = True 

71 ) -> float: 

72 """Parse IEEE-754 32-bit float.""" 

73 if validate and len(data) < offset + 4: 

74 raise InsufficientDataError("float32", data[offset:], 4) 

75 return DataParser.parse_float32(data, offset) 

76 

77 def encode_value(self, value: float, *, validate: bool = True) -> bytearray: 

78 """Encode float32 value to bytes.""" 

79 return DataParser.encode_float32(float(value))