1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00

Fix detection of zone master in soundtouch media_player (#33157)

This commit is contained in:
da-anda 2020-03-30 17:27:02 +02:00 committed by GitHub
parent 0186ce7896
commit 01bf4daf37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 14 deletions

View File

@ -437,15 +437,25 @@ class SoundTouchDevice(MediaPlayerDevice):
# slaves for some reason. To compensate for this shortcoming we have to fetch
# the zone info from the master when the current device is a slave until this is
# fixed in the SoundTouch API or libsoundtouch, or of course until somebody has a
# better idea on how to fix this
if zone_status.is_master:
# better idea on how to fix this.
# In addition to this shortcoming, libsoundtouch seems to report the "is_master"
# property wrong on some slaves, so the only reliable way to detect if the current
# devices is the master, is by comparing the master_id of the zone with the device_id
if zone_status.master_id == self._device.config.device_id:
return self._build_zone_info(self.entity_id, zone_status.slaves)
master_instance = self._get_instance_by_ip(zone_status.master_ip)
master_zone_status = master_instance.device.zone_status()
return self._build_zone_info(
master_instance.entity_id, master_zone_status.slaves
)
# The master device has to be searched by it's ID and not IP since libsoundtouch / BOSE API
# do not return the IP of the master for some slave objects/responses
master_instance = self._get_instance_by_id(zone_status.master_id)
if master_instance is not None:
master_zone_status = master_instance.device.zone_status()
return self._build_zone_info(
master_instance.entity_id, master_zone_status.slaves
)
# We should never end up here since this means we haven't found a master device to get the
# correct zone info from. In this case, assume current device is master
return self._build_zone_info(self.entity_id, zone_status.slaves)
def _get_instance_by_ip(self, ip_address):
"""Search and return a SoundTouchDevice instance by it's IP address."""
@ -454,6 +464,13 @@ class SoundTouchDevice(MediaPlayerDevice):
return instance
return None
def _get_instance_by_id(self, instance_id):
"""Search and return a SoundTouchDevice instance by it's ID (aka MAC address)."""
for instance in self.hass.data[DATA_SOUNDTOUCH]:
if instance and instance.device.config.device_id == instance_id:
return instance
return None
def _build_zone_info(self, master, zone_slaves):
"""Build the exposed zone attributes."""
slaves = []

View File

@ -33,6 +33,8 @@ from homeassistant.setup import async_setup_component
DEVICE_1_IP = "192.168.0.1"
DEVICE_2_IP = "192.168.0.2"
DEVICE_1_ID = 1
DEVICE_2_ID = 2
def get_config(host=DEVICE_1_IP, port=8090, name="soundtouch"):
@ -60,20 +62,22 @@ def one_device_fixture():
def two_zones_fixture():
"""Mock one master and one slave."""
device_1 = MockDevice(
DEVICE_1_ID,
MockZoneStatus(
is_master=True,
master_id=1,
master_id=DEVICE_1_ID,
master_ip=DEVICE_1_IP,
slaves=[MockZoneSlave(DEVICE_2_IP)],
)
),
)
device_2 = MockDevice(
DEVICE_2_ID,
MockZoneStatus(
is_master=False,
master_id=1,
master_id=DEVICE_1_ID,
master_ip=DEVICE_1_IP,
slaves=[MockZoneSlave(DEVICE_2_IP)],
)
),
)
devices = {DEVICE_1_IP: device_1, DEVICE_2_IP: device_2}
device_patch = patch(
@ -112,9 +116,9 @@ async def setup_soundtouch(hass, config):
class MockDevice(STD):
"""Mock device."""
def __init__(self, zone_status=None):
def __init__(self, id=None, zone_status=None):
"""Init the class."""
self._config = MockConfig()
self._config = MockConfig(id)
self._zone_status = zone_status or MockZoneStatus()
def zone_status(self, refresh=True):
@ -125,9 +129,10 @@ class MockDevice(STD):
class MockConfig(Config):
"""Mock config."""
def __init__(self):
def __init__(self, id=None):
"""Init class."""
self._name = "name"
self._id = id or DEVICE_1_ID
class MockZoneStatus(ZoneStatus):