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

25 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-03 16:41 +0000

1"""ACS Status characteristic (0x2B2F).""" 

2 

3from __future__ import annotations 

4 

5import msgspec 

6 

7from ..context import CharacteristicContext 

8from .base import BaseCharacteristic 

9from .utils import DataParser 

10 

11 

12class ACSStatusData(msgspec.Struct, frozen=True, kw_only=True): 

13 """Parsed data from ACS Status characteristic.""" 

14 

15 security_controls_switch: bool 

16 security_established: bool 

17 current_restriction_map_id: int 

18 

19 

20class ACSStatusCharacteristic(BaseCharacteristic[ACSStatusData]): 

21 """ACS Status characteristic (0x2B2F). 

22 

23 org.bluetooth.characteristic.acs_status 

24 

25 Contains ACS status flags and the current restriction map ID. 

26 """ 

27 

28 expected_length: int | None = 3 

29 

30 def _decode_value( 

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

32 ) -> ACSStatusData: 

33 status_flags = DataParser.parse_int8(data, 0, signed=False) 

34 restriction_map_id = DataParser.parse_int16(data, 1, signed=False) 

35 

36 return ACSStatusData( 

37 security_controls_switch=bool(status_flags & 0x01), 

38 security_established=bool(status_flags & 0x02), 

39 current_restriction_map_id=restriction_map_id, 

40 ) 

41 

42 def _encode_value(self, data: ACSStatusData) -> bytearray: 

43 status_flags = 0 

44 if data.security_controls_switch: 

45 status_flags |= 0x01 

46 if data.security_established: 

47 status_flags |= 0x02 

48 

49 result = bytearray() 

50 result.extend(DataParser.encode_int8(status_flags, signed=False)) 

51 result.extend(DataParser.encode_int16(data.current_restriction_map_id, signed=False)) 

52 return result