mirror of
https://github.com/home-assistant/core.git
synced 2025-07-15 09:17:10 +00:00
Support songpal wireless-only soundbar identifiers (#65330)
As shown in #64868, a number of newer models don't come wiht a macAddr attributes, so for those fall back to the wireless address. This could be hidden by the python-songpal library but for now this will make it possible to have multiple modern songpal devices on the same network.
This commit is contained in:
parent
63d3a47599
commit
c6aa526469
@ -212,13 +212,18 @@ class SongpalEntity(MediaPlayerEntity):
|
|||||||
@property
|
@property
|
||||||
def unique_id(self):
|
def unique_id(self):
|
||||||
"""Return a unique ID."""
|
"""Return a unique ID."""
|
||||||
return self._sysinfo.macAddr
|
return self._sysinfo.macAddr or self._sysinfo.wirelessMacAddr
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> DeviceInfo:
|
def device_info(self) -> DeviceInfo:
|
||||||
"""Return the device info."""
|
"""Return the device info."""
|
||||||
|
connections = set()
|
||||||
|
if self._sysinfo.macAddr:
|
||||||
|
connections.add((dr.CONNECTION_NETWORK_MAC, self._sysinfo.macAddr))
|
||||||
|
if self._sysinfo.wirelessMacAddr:
|
||||||
|
connections.add((dr.CONNECTION_NETWORK_MAC, self._sysinfo.wirelessMacAddr))
|
||||||
return DeviceInfo(
|
return DeviceInfo(
|
||||||
connections={(dr.CONNECTION_NETWORK_MAC, self._sysinfo.macAddr)},
|
connections=connections,
|
||||||
identifiers={(DOMAIN, self.unique_id)},
|
identifiers={(DOMAIN, self.unique_id)},
|
||||||
manufacturer="Sony Corporation",
|
manufacturer="Sony Corporation",
|
||||||
model=self._model,
|
model=self._model,
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
from songpal import SongpalException
|
from songpal import SongpalException
|
||||||
|
from songpal.containers import Sysinfo
|
||||||
|
|
||||||
from homeassistant.components.songpal.const import CONF_ENDPOINT
|
from homeassistant.components.songpal.const import CONF_ENDPOINT
|
||||||
from homeassistant.const import CONF_NAME
|
from homeassistant.const import CONF_NAME
|
||||||
@ -12,6 +13,7 @@ HOST = "0.0.0.0"
|
|||||||
ENDPOINT = f"http://{HOST}:10000/sony"
|
ENDPOINT = f"http://{HOST}:10000/sony"
|
||||||
MODEL = "model"
|
MODEL = "model"
|
||||||
MAC = "mac"
|
MAC = "mac"
|
||||||
|
WIRELESS_MAC = "wmac"
|
||||||
SW_VERSION = "sw_ver"
|
SW_VERSION = "sw_ver"
|
||||||
|
|
||||||
CONF_DATA = {
|
CONF_DATA = {
|
||||||
@ -20,7 +22,7 @@ CONF_DATA = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _create_mocked_device(throw_exception=False):
|
def _create_mocked_device(throw_exception=False, wired_mac=MAC, wireless_mac=None):
|
||||||
mocked_device = MagicMock()
|
mocked_device = MagicMock()
|
||||||
|
|
||||||
type(mocked_device).get_supported_methods = AsyncMock(
|
type(mocked_device).get_supported_methods = AsyncMock(
|
||||||
@ -35,9 +37,15 @@ def _create_mocked_device(throw_exception=False):
|
|||||||
return_value=interface_info
|
return_value=interface_info
|
||||||
)
|
)
|
||||||
|
|
||||||
sys_info = MagicMock()
|
sys_info = Sysinfo(
|
||||||
sys_info.macAddr = MAC
|
bdAddr=None,
|
||||||
sys_info.version = SW_VERSION
|
macAddr=wired_mac,
|
||||||
|
wirelessMacAddr=wireless_mac,
|
||||||
|
bssid=None,
|
||||||
|
ssid=None,
|
||||||
|
bleID=None,
|
||||||
|
version=SW_VERSION,
|
||||||
|
)
|
||||||
type(mocked_device).get_system_info = AsyncMock(return_value=sys_info)
|
type(mocked_device).get_system_info = AsyncMock(return_value=sys_info)
|
||||||
|
|
||||||
volume1 = MagicMock()
|
volume1 = MagicMock()
|
||||||
|
@ -29,6 +29,7 @@ from . import (
|
|||||||
MAC,
|
MAC,
|
||||||
MODEL,
|
MODEL,
|
||||||
SW_VERSION,
|
SW_VERSION,
|
||||||
|
WIRELESS_MAC,
|
||||||
_create_mocked_device,
|
_create_mocked_device,
|
||||||
_patch_media_player_device,
|
_patch_media_player_device,
|
||||||
)
|
)
|
||||||
@ -126,6 +127,78 @@ async def test_state(hass):
|
|||||||
assert entity.unique_id == MAC
|
assert entity.unique_id == MAC
|
||||||
|
|
||||||
|
|
||||||
|
async def test_state_wireless(hass):
|
||||||
|
"""Test state of the entity with only Wireless MAC."""
|
||||||
|
mocked_device = _create_mocked_device(wired_mac=None, wireless_mac=WIRELESS_MAC)
|
||||||
|
entry = MockConfigEntry(domain=songpal.DOMAIN, data=CONF_DATA)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
with _patch_media_player_device(mocked_device):
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(ENTITY_ID)
|
||||||
|
assert state.name == FRIENDLY_NAME
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
attributes = state.as_dict()["attributes"]
|
||||||
|
assert attributes["volume_level"] == 0.5
|
||||||
|
assert attributes["is_volume_muted"] is False
|
||||||
|
assert attributes["source_list"] == ["title1", "title2"]
|
||||||
|
assert attributes["source"] == "title2"
|
||||||
|
assert attributes["supported_features"] == SUPPORT_SONGPAL
|
||||||
|
|
||||||
|
device_registry = dr.async_get(hass)
|
||||||
|
device = device_registry.async_get_device(
|
||||||
|
identifiers={(songpal.DOMAIN, WIRELESS_MAC)}
|
||||||
|
)
|
||||||
|
assert device.connections == {(dr.CONNECTION_NETWORK_MAC, WIRELESS_MAC)}
|
||||||
|
assert device.manufacturer == "Sony Corporation"
|
||||||
|
assert device.name == FRIENDLY_NAME
|
||||||
|
assert device.sw_version == SW_VERSION
|
||||||
|
assert device.model == MODEL
|
||||||
|
|
||||||
|
entity_registry = er.async_get(hass)
|
||||||
|
entity = entity_registry.async_get(ENTITY_ID)
|
||||||
|
assert entity.unique_id == WIRELESS_MAC
|
||||||
|
|
||||||
|
|
||||||
|
async def test_state_both(hass):
|
||||||
|
"""Test state of the entity with both Wired and Wireless MAC."""
|
||||||
|
mocked_device = _create_mocked_device(wired_mac=MAC, wireless_mac=WIRELESS_MAC)
|
||||||
|
entry = MockConfigEntry(domain=songpal.DOMAIN, data=CONF_DATA)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
with _patch_media_player_device(mocked_device):
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get(ENTITY_ID)
|
||||||
|
assert state.name == FRIENDLY_NAME
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
attributes = state.as_dict()["attributes"]
|
||||||
|
assert attributes["volume_level"] == 0.5
|
||||||
|
assert attributes["is_volume_muted"] is False
|
||||||
|
assert attributes["source_list"] == ["title1", "title2"]
|
||||||
|
assert attributes["source"] == "title2"
|
||||||
|
assert attributes["supported_features"] == SUPPORT_SONGPAL
|
||||||
|
|
||||||
|
device_registry = dr.async_get(hass)
|
||||||
|
device = device_registry.async_get_device(identifiers={(songpal.DOMAIN, MAC)})
|
||||||
|
assert device.connections == {
|
||||||
|
(dr.CONNECTION_NETWORK_MAC, MAC),
|
||||||
|
(dr.CONNECTION_NETWORK_MAC, WIRELESS_MAC),
|
||||||
|
}
|
||||||
|
assert device.manufacturer == "Sony Corporation"
|
||||||
|
assert device.name == FRIENDLY_NAME
|
||||||
|
assert device.sw_version == SW_VERSION
|
||||||
|
assert device.model == MODEL
|
||||||
|
|
||||||
|
entity_registry = er.async_get(hass)
|
||||||
|
entity = entity_registry.async_get(ENTITY_ID)
|
||||||
|
# We prefer the wired mac if present.
|
||||||
|
assert entity.unique_id == MAC
|
||||||
|
|
||||||
|
|
||||||
async def test_services(hass):
|
async def test_services(hass):
|
||||||
"""Test services."""
|
"""Test services."""
|
||||||
mocked_device = _create_mocked_device()
|
mocked_device = _create_mocked_device()
|
||||||
@ -173,11 +246,7 @@ async def test_services(hass):
|
|||||||
mocked_device.set_sound_settings.assert_called_once_with("name", "value")
|
mocked_device.set_sound_settings.assert_called_once_with("name", "value")
|
||||||
mocked_device.set_sound_settings.reset_mock()
|
mocked_device.set_sound_settings.reset_mock()
|
||||||
|
|
||||||
mocked_device2 = _create_mocked_device()
|
mocked_device2 = _create_mocked_device(wired_mac="mac2")
|
||||||
sys_info = MagicMock()
|
|
||||||
sys_info.macAddr = "mac2"
|
|
||||||
sys_info.version = SW_VERSION
|
|
||||||
type(mocked_device2).get_system_info = AsyncMock(return_value=sys_info)
|
|
||||||
entry2 = MockConfigEntry(
|
entry2 = MockConfigEntry(
|
||||||
domain=songpal.DOMAIN, data={CONF_NAME: "d2", CONF_ENDPOINT: ENDPOINT}
|
domain=songpal.DOMAIN, data={CONF_NAME: "d2", CONF_ENDPOINT: ENDPOINT}
|
||||||
)
|
)
|
||||||
@ -194,6 +263,27 @@ async def test_services(hass):
|
|||||||
)
|
)
|
||||||
mocked_device.set_sound_settings.assert_called_once_with("name", "value")
|
mocked_device.set_sound_settings.assert_called_once_with("name", "value")
|
||||||
mocked_device2.set_sound_settings.assert_called_once_with("name", "value")
|
mocked_device2.set_sound_settings.assert_called_once_with("name", "value")
|
||||||
|
mocked_device.set_sound_settings.reset_mock()
|
||||||
|
mocked_device2.set_sound_settings.reset_mock()
|
||||||
|
|
||||||
|
mocked_device3 = _create_mocked_device(wired_mac=None, wireless_mac=WIRELESS_MAC)
|
||||||
|
entry3 = MockConfigEntry(
|
||||||
|
domain=songpal.DOMAIN, data={CONF_NAME: "d2", CONF_ENDPOINT: ENDPOINT}
|
||||||
|
)
|
||||||
|
entry3.add_to_hass(hass)
|
||||||
|
with _patch_media_player_device(mocked_device3):
|
||||||
|
await hass.config_entries.async_setup(entry3.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
songpal.DOMAIN,
|
||||||
|
SET_SOUND_SETTING,
|
||||||
|
{"entity_id": "all", "name": "name", "value": "value"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
mocked_device.set_sound_settings.assert_called_once_with("name", "value")
|
||||||
|
mocked_device2.set_sound_settings.assert_called_once_with("name", "value")
|
||||||
|
mocked_device3.set_sound_settings.assert_called_once_with("name", "value")
|
||||||
|
|
||||||
|
|
||||||
async def test_websocket_events(hass):
|
async def test_websocket_events(hass):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user