Auto recreate HomeKit TVs when the sources are out of sync (#53208)
parent
2a65c5f93c
commit
f20602e11d
|
@ -58,12 +58,14 @@ from .const import (
|
||||||
CONF_LOW_BATTERY_THRESHOLD,
|
CONF_LOW_BATTERY_THRESHOLD,
|
||||||
DEFAULT_LOW_BATTERY_THRESHOLD,
|
DEFAULT_LOW_BATTERY_THRESHOLD,
|
||||||
DEVICE_CLASS_PM25,
|
DEVICE_CLASS_PM25,
|
||||||
|
DOMAIN,
|
||||||
EVENT_HOMEKIT_CHANGED,
|
EVENT_HOMEKIT_CHANGED,
|
||||||
HK_CHARGING,
|
HK_CHARGING,
|
||||||
HK_NOT_CHARGABLE,
|
HK_NOT_CHARGABLE,
|
||||||
HK_NOT_CHARGING,
|
HK_NOT_CHARGING,
|
||||||
MANUFACTURER,
|
MANUFACTURER,
|
||||||
SERV_BATTERY_SERVICE,
|
SERV_BATTERY_SERVICE,
|
||||||
|
SERVICE_HOMEKIT_RESET_ACCESSORY,
|
||||||
TYPE_FAUCET,
|
TYPE_FAUCET,
|
||||||
TYPE_OUTLET,
|
TYPE_OUTLET,
|
||||||
TYPE_SHOWER,
|
TYPE_SHOWER,
|
||||||
|
@ -454,6 +456,17 @@ class HomeAccessory(Accessory):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ha_callback
|
||||||
|
def async_reset(self):
|
||||||
|
"""Reset and recreate an accessory."""
|
||||||
|
self.hass.async_create_task(
|
||||||
|
self.hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_HOMEKIT_RESET_ACCESSORY,
|
||||||
|
{ATTR_ENTITY_ID: self.entity_id},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@ha_callback
|
@ha_callback
|
||||||
def async_stop(self):
|
def async_stop(self):
|
||||||
"""Cancel any subscriptions when the bridge is stopped."""
|
"""Cancel any subscriptions when the bridge is stopped."""
|
||||||
|
|
|
@ -87,6 +87,7 @@ class RemoteInputSelectAccessory(HomeAccessory):
|
||||||
features = state.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
features = state.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||||
|
|
||||||
self.source_key = source_key
|
self.source_key = source_key
|
||||||
|
self.source_list_key = source_list_key
|
||||||
self.sources = []
|
self.sources = []
|
||||||
self.support_select_source = False
|
self.support_select_source = False
|
||||||
if features & required_feature:
|
if features & required_feature:
|
||||||
|
@ -152,13 +153,26 @@ class RemoteInputSelectAccessory(HomeAccessory):
|
||||||
index = self.sources.index(source_name)
|
index = self.sources.index(source_name)
|
||||||
if self.char_input_source.value != index:
|
if self.char_input_source.value != index:
|
||||||
self.char_input_source.set_value(index)
|
self.char_input_source.set_value(index)
|
||||||
elif hk_state:
|
return
|
||||||
_LOGGER.warning(
|
|
||||||
"%s: Sources out of sync. Restart Home Assistant",
|
possible_sources = new_state.attributes.get(self.source_list_key, [])
|
||||||
|
if source_name in possible_sources:
|
||||||
|
_LOGGER.debug(
|
||||||
|
"%s: Sources out of sync. Rebuilding Accessory",
|
||||||
self.entity_id,
|
self.entity_id,
|
||||||
)
|
)
|
||||||
if self.char_input_source.value != 0:
|
# Sources are out of sync, recreate the accessory
|
||||||
self.char_input_source.set_value(0)
|
self.async_reset()
|
||||||
|
return
|
||||||
|
|
||||||
|
_LOGGER.debug(
|
||||||
|
"%s: Source %s does not exist the source list: %s",
|
||||||
|
self.entity_id,
|
||||||
|
source_name,
|
||||||
|
possible_sources,
|
||||||
|
)
|
||||||
|
if self.char_input_source.value != 0:
|
||||||
|
self.char_input_source.set_value(0)
|
||||||
|
|
||||||
|
|
||||||
@TYPES.register("ActivityRemote")
|
@TYPES.register("ActivityRemote")
|
||||||
|
|
|
@ -242,7 +242,7 @@ async def test_media_player_television(hass, hk_driver, events, caplog):
|
||||||
hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: "HDMI 5"})
|
hass.states.async_set(entity_id, STATE_ON, {ATTR_INPUT_SOURCE: "HDMI 5"})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert acc.char_input_source.value == 0
|
assert acc.char_input_source.value == 0
|
||||||
assert caplog.records[-2].levelname == "WARNING"
|
assert caplog.records[-2].levelname == "DEBUG"
|
||||||
|
|
||||||
# Set from HomeKit
|
# Set from HomeKit
|
||||||
call_turn_on = async_mock_service(hass, DOMAIN, "turn_on")
|
call_turn_on = async_mock_service(hass, DOMAIN, "turn_on")
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
from homeassistant.components.homekit.const import (
|
from homeassistant.components.homekit.const import (
|
||||||
ATTR_KEY_NAME,
|
ATTR_KEY_NAME,
|
||||||
ATTR_VALUE,
|
ATTR_VALUE,
|
||||||
|
DOMAIN as HOMEKIT_DOMAIN,
|
||||||
EVENT_HOMEKIT_TV_REMOTE_KEY_PRESSED,
|
EVENT_HOMEKIT_TV_REMOTE_KEY_PRESSED,
|
||||||
KEY_ARROW_RIGHT,
|
KEY_ARROW_RIGHT,
|
||||||
|
SERVICE_HOMEKIT_RESET_ACCESSORY,
|
||||||
)
|
)
|
||||||
from homeassistant.components.homekit.type_remotes import ActivityRemote
|
from homeassistant.components.homekit.type_remotes import ActivityRemote
|
||||||
from homeassistant.components.remote import (
|
from homeassistant.components.remote import (
|
||||||
|
@ -146,3 +148,19 @@ async def test_activity_remote(hass, hk_driver, events, caplog):
|
||||||
|
|
||||||
assert len(events) == 1
|
assert len(events) == 1
|
||||||
assert events[0].data[ATTR_KEY_NAME] == KEY_ARROW_RIGHT
|
assert events[0].data[ATTR_KEY_NAME] == KEY_ARROW_RIGHT
|
||||||
|
|
||||||
|
call_reset_accessory = async_mock_service(
|
||||||
|
hass, HOMEKIT_DOMAIN, SERVICE_HOMEKIT_RESET_ACCESSORY
|
||||||
|
)
|
||||||
|
# A wild source appears - The accessory should rebuild itself
|
||||||
|
hass.states.async_set(
|
||||||
|
entity_id,
|
||||||
|
STATE_ON,
|
||||||
|
{
|
||||||
|
ATTR_SUPPORTED_FEATURES: SUPPORT_ACTIVITY,
|
||||||
|
ATTR_CURRENT_ACTIVITY: "Amazon TV",
|
||||||
|
ATTR_ACTIVITY_LIST: ["TV", "Apple TV", "Amazon TV"],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert call_reset_accessory[0].data[ATTR_ENTITY_ID] == entity_id
|
||||||
|
|
Loading…
Reference in New Issue