Skip to content

Commit

Permalink
Rework beolink_join source_id handling
Browse files Browse the repository at this point in the history
Update API
Tweaks
  • Loading branch information
mj23000 committed Dec 11, 2024
1 parent 5e73c1a commit 2d6ed6f
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 46 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,10 @@ The Bang & Olufsen integration additionally supports different custom actions

Join a Beolink experience.

| Action data attribute | Optional | Description |
| --------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `beolink_jid` | yes | Manually specify Beolink JID to join. |
| `source_id` | yes | Specify which source to join, behavior varies between platforms. Source names prefaced by a platform name can only be used when connecting to that platform. A defined Beolink JID is required |
| Action data attribute | Optional | Description |
| --------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `beolink_jid` | yes | Manually specify Beolink JID to join. |
| `source_id` | yes | Specify which source to join, behavior varies between hardware platforms. Source names prefaced by a platform name can only be used when connecting to that platform. For example \"ASE Beoradio\" can only be used when joining an ASE device, while ”ASE / Mozart Deezer” can be used with ASE or Mozart devices. A defined Beolink JID is required. |

### Action `bang_olufsen.beolink_expand`

Expand Down
8 changes: 7 additions & 1 deletion custom_components/bang_olufsen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING

from aiohttp import ClientConnectorError, ClientOSError, ServerTimeoutError
from aiohttp import (
ClientConnectorError,
ClientOSError,
ServerTimeoutError,
WSMessageTypeError,
)
from mozart_api.exceptions import ApiException
from mozart_api.mozart_client import MozartClient

Expand Down Expand Up @@ -92,6 +97,7 @@ async def async_setup_entry(
ServerTimeoutError,
ApiException,
TimeoutError,
WSMessageTypeError,
) as error:
await client.close_api_client()
raise ConfigEntryNotReady(
Expand Down
31 changes: 26 additions & 5 deletions custom_components/bang_olufsen/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ class WebsocketNotification(StrEnum):
# Power states.
BANG_OLUFSEN_ON: Final[str] = "on"

VALID_MEDIA_TYPES: Final[tuple] = (
VALID_MEDIA_TYPES: Final[tuple[str, ...]] = (
BangOlufsenMediaType.DEEZER,
BangOlufsenMediaType.FAVOURITE,
BangOlufsenMediaType.OVERLAY_TTS,
Expand All @@ -155,8 +155,15 @@ class WebsocketNotification(StrEnum):
)

# Playback states for playing and not playing
PLAYING: Final[tuple] = ("started", "buffering", BANG_OLUFSEN_ON)
NOT_PLAYING: Final[tuple] = ("idle", "paused", "stopped", "ended", "unknown", "error")
PLAYING: Final[tuple[str, ...]] = ("started", "buffering", BANG_OLUFSEN_ON)
NOT_PLAYING: Final[tuple[str, ...]] = (
"idle",
"paused",
"stopped",
"ended",
"unknown",
"error",
)

# Fallback sources to use in case of API failure.
FALLBACK_SOURCES: Final[SourceArray] = SourceArray(
Expand Down Expand Up @@ -421,5 +428,19 @@ class WebsocketNotification(StrEnum):
NONE_PARAMETERS,
)

# Prefix for Beolink Converter NL/ML in async_beolink_join custom service
BL_CONVERTER_PREFIX = "bc_nlml_"
# Beolink Converter NL/ML sources need to be transformed to upper case
BEOLINK_JOIN_SOURCES_TO_UPPER = (
"aux_a",
"cd",
"ph",
"radio",
"tp1",
"tp2",
)
BEOLINK_JOIN_SOURCES = (
*BEOLINK_JOIN_SOURCES_TO_UPPER,
"beoradio",
"deezer",
"spotify",
"tidal",
)
2 changes: 1 addition & 1 deletion custom_components/bang_olufsen/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async def async_get_config_entry_diagnostics(
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""

data: dict = {
data: dict[str, dict[str, Any] | bool] = {
"config_entry": config_entry.as_dict(),
"websocket_connected": config_entry.runtime_data.client.websocket_connected,
}
Expand Down
16 changes: 8 additions & 8 deletions custom_components/bang_olufsen/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,12 @@
BANG_OLUFSEN_REPEAT_FROM_HA,
BANG_OLUFSEN_REPEAT_TO_HA,
BANG_OLUFSEN_STATES,
BEOLINK_JOIN_SOURCES,
BEOLINK_JOIN_SOURCES_TO_UPPER,
BEOLINK_LEADER_COMMAND,
BEOLINK_LISTENER_COMMAND,
BEOLINK_RELATIVE_VOLUME,
BEOLINK_VOLUME,
BL_CONVERTER_PREFIX,
CONF_BEOLINK_JID,
CONNECTION_STATUS,
DOMAIN,
Expand Down Expand Up @@ -155,7 +156,7 @@ async def async_setup_entry(
name="beolink_join",
schema={
vol.Optional("beolink_jid"): jid_regex,
vol.Optional("source_id"): str,
vol.Optional("source_id"): vol.In(BEOLINK_JOIN_SOURCES),
},
func="async_beolink_join",
supports_response=SupportsResponse.OPTIONAL,
Expand Down Expand Up @@ -267,10 +268,10 @@ def __init__(self, config_entry: BangOlufsenConfigEntry) -> None:
# Beolink
self._beolink_sources: dict[str, bool] = {}
self._remote_leader: BeolinkLeader | None = None
self._beolink_attribute: dict[str, dict] = {}
self._beolink_attribute: dict[str, dict[str, Any]] = {}
self._beolink_listeners: list[BeolinkListener] = []

self._favourite_attribute: dict[str, dict] = {}
self._favourite_attribute: dict[str, dict[str, Any]] = {}

async def async_added_to_hass(self) -> None:
"""Turn on the dispatchers."""
Expand Down Expand Up @@ -1165,10 +1166,9 @@ async def async_beolink_join(
response = await self._client.join_beolink_peer(jid=beolink_jid)
# Join a peer and select specific source
elif beolink_jid and source_id:
# Home Assistant does not support the "raw" Beolink Converter NL/ML source ids in strings.json
# So they have the be transformed to be compatible and now have to be capatilized in order to work
if BL_CONVERTER_PREFIX in source_id:
source_id = source_id.removeprefix(BL_CONVERTER_PREFIX).upper()
# Beolink Converter NL/ML sources need to be in upper case
if source_id in BEOLINK_JOIN_SOURCES_TO_UPPER:
source_id = source_id.upper()

response = await self._client.join_beolink_peer(
jid=beolink_jid, source=source_id
Expand Down
14 changes: 7 additions & 7 deletions custom_components/bang_olufsen/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,16 @@ beolink_join:
select:
translation_key: "source_ids"
options:
- beoradio
- deezer
- spotify
- tidal
- beoradio
- bc_nlml_radio
- bc_nlml_tp1
- bc_nlml_tp2
- bc_nlml_cd
- bc_nlml_aux_a
- bc_nlml_ph
- radio
- tp1
- tp2
- cd
- aux_a
- ph

beolink_leader_command:
target:
Expand Down
20 changes: 10 additions & 10 deletions custom_components/bang_olufsen/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@
"selector": {
"source_ids": {
"options": {
"deezer": "Deezer",
"spotify": "Spotify",
"tidal": "Mozart Tidal",
"beoradio": "ASE Beoradio",
"bc_nlml_radio": "Beolink Converter NL/ML RADIO",
"bc_nlml_tp1": "Beolink Converter NL/ML TP1",
"bc_nlml_tp2": "Beolink Converter NL/ML TP2",
"bc_nlml_cd": "Beolink Converter NL/ML CD",
"bc_nlml_aux_a": "Beolink Converter NL/ML AUX_A",
"bc_nlml_ph": "Beolink Converter NL/ML PH"
"deezer": "ASE / Mozart Deezer",
"spotify": "ASE / Mozart Spotify",
"tidal": "Mozart Tidal",
"aux_a": "Beolink Converter NL/ML AUX_A",
"cd": "Beolink Converter NL/ML CD",
"ph": "Beolink Converter NL/ML PH",
"radio": "Beolink Converter NL/ML RADIO",
"tp1": "Beolink Converter NL/ML TP1",
"tp2": "Beolink Converter NL/ML TP2"
}
}
},
Expand Down Expand Up @@ -87,7 +87,7 @@
},
"source_id": {
"name": "Source",
"description": "Specify which source to join, behavior varies between platforms. Source names prefaced by a platform name can only be used when connecting to that platform. A defined Beolink JID is required"
"description": "Specify which source to join, behavior varies between hardware platforms. Source names prefaced by a platform name can only be used when connecting to that platform. For example \"ASE Beoradio\" can only be used when joining an ASE device, while ”ASE / Mozart Deezer” can be used with ASE or Mozart devices. A defined Beolink JID is required."
}
},
"sections": {
Expand Down
20 changes: 10 additions & 10 deletions custom_components/bang_olufsen/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1242,16 +1242,16 @@
"selector": {
"source_ids": {
"options": {
"bc_nlml_aux_a": "Beolink Converter NL/ML AUX_A",
"bc_nlml_cd": "Beolink Converter NL/ML CD",
"bc_nlml_ph": "Beolink Converter NL/ML PH",
"bc_nlml_radio": "Beolink Converter NL/ML RADIO",
"bc_nlml_tp1": "Beolink Converter NL/ML TP1",
"bc_nlml_tp2": "Beolink Converter NL/ML TP2",
"aux_a": "Beolink Converter NL/ML AUX_A",
"beoradio": "ASE Beoradio",
"deezer": "Deezer",
"spotify": "Spotify",
"tidal": "Mozart Tidal"
"cd": "Beolink Converter NL/ML CD",
"deezer": "ASE / Mozart Deezer",
"ph": "Beolink Converter NL/ML PH",
"radio": "Beolink Converter NL/ML RADIO",
"spotify": "ASE / Mozart Spotify",
"tidal": "Mozart Tidal",
"tp1": "Beolink Converter NL/ML TP1",
"tp2": "Beolink Converter NL/ML TP2"
}
}
},
Expand Down Expand Up @@ -1288,7 +1288,7 @@
"name": "Beolink JID"
},
"source_id": {
"description": "Specify which source to join, behavior varies between platforms. Source names prefaced by a platform name can only be used when connecting to that platform. A defined Beolink JID is required",
"description": "Specify which source to join, behavior varies between hardware platforms. Source names prefaced by a platform name can only be used when connecting to that platform. For example \"ASE Beoradio\" can only be used when joining an ASE device, while \u201dASE / Mozart Deezer\u201d can be used with ASE or Mozart devices. A defined Beolink JID is required.",
"name": "Source"
}
},
Expand Down

0 comments on commit 2d6ed6f

Please sign in to comment.