/
/
/
1"""Helpers for Bose soundtouch."""
2
3from defusedxml import ElementTree as DefusedET
4
5
6def source_id(source: str, source_account: str | None) -> str:
7 """Build a stable source id from a SoundTouch source and account."""
8 return f"{source}:{source_account}" if source_account else source
9
10
11def extract_preset_id(message: str) -> int | None:
12 """
13 Extract a Bose SoundTouch favorite/preset id from a websocket XML message.
14
15 Detects a physical preset button press from the speaker's notification channel.
16 """
17 try:
18 root = DefusedET.fromstring(message)
19 except DefusedET.ParseError:
20 return None
21
22 preset_id = next(
23 (
24 element.attrib.get("id")
25 for element in root.iter()
26 if _local_name(element.tag) == "preset"
27 ),
28 None,
29 )
30
31 try:
32 return int(preset_id) if preset_id else None
33 except TypeError, ValueError:
34 return None
35
36
37def _local_name(tag: str) -> str:
38 """Return an XML tag name without its namespace prefix."""
39 return tag.rsplit("}", 1)[-1]
40