1 """Support for HomeKit Controller Televisions."""
3 from __future__
import annotations
7 from aiohomekit.model.characteristics
import (
9 CurrentMediaStateValues,
11 TargetMediaStateValues,
13 from aiohomekit.model.services
import Service, ServicesTypes
14 from aiohomekit.utils
import clamp_enum_to_char
17 MediaPlayerDeviceClass,
19 MediaPlayerEntityFeature,
27 from .
import KNOWN_DEVICES
28 from .connection
import HKDevice
29 from .entity
import HomeKitEntity
31 _LOGGER = logging.getLogger(__name__)
35 CurrentMediaStateValues.PLAYING: MediaPlayerState.PLAYING,
36 CurrentMediaStateValues.PAUSED: MediaPlayerState.PAUSED,
37 CurrentMediaStateValues.STOPPED: MediaPlayerState.IDLE,
43 config_entry: ConfigEntry,
44 async_add_entities: AddEntitiesCallback,
46 """Set up Homekit television."""
47 hkid: str = config_entry.data[
"AccessoryPairingID"]
48 conn: HKDevice = hass.data[KNOWN_DEVICES][hkid]
51 def async_add_service(service: Service) -> bool:
52 if service.type != ServicesTypes.TELEVISION:
54 info = {
"aid": service.accessory.aid,
"iid": service.iid}
56 conn.async_migrate_unique_id(
57 entity.old_unique_id, entity.unique_id, Platform.MEDIA_PLAYER
62 conn.add_listener(async_add_service)
66 """Representation of a HomeKit Controller Television."""
68 _attr_device_class = MediaPlayerDeviceClass.TV
71 """Define the homekit characteristics the entity cares about."""
73 CharacteristicsTypes.ACTIVE,
74 CharacteristicsTypes.CURRENT_MEDIA_STATE,
75 CharacteristicsTypes.TARGET_MEDIA_STATE,
76 CharacteristicsTypes.REMOTE_KEY,
77 CharacteristicsTypes.ACTIVE_IDENTIFIER,
79 CharacteristicsTypes.CONFIGURED_NAME,
80 CharacteristicsTypes.IDENTIFIER,
85 """Flag media player features that are supported."""
88 if self.
serviceservice.has(CharacteristicsTypes.ACTIVE_IDENTIFIER):
89 features |= MediaPlayerEntityFeature.SELECT_SOURCE
91 if self.
serviceservice.has(CharacteristicsTypes.TARGET_MEDIA_STATE):
93 features |= MediaPlayerEntityFeature.PAUSE
96 features |= MediaPlayerEntityFeature.PLAY
99 features |= MediaPlayerEntityFeature.STOP
102 self.
serviceservice.has(CharacteristicsTypes.REMOTE_KEY)
105 features |= MediaPlayerEntityFeature.PAUSE | MediaPlayerEntityFeature.PLAY
111 """Mediate state flags that are supported."""
112 if not self.
serviceservice.has(CharacteristicsTypes.TARGET_MEDIA_STATE):
115 return clamp_enum_to_char(
116 TargetMediaStateValues,
117 self.
serviceservice[CharacteristicsTypes.TARGET_MEDIA_STATE],
122 """Remote key buttons that are supported."""
123 if not self.
serviceservice.has(CharacteristicsTypes.REMOTE_KEY):
126 return clamp_enum_to_char(
127 RemoteKeyValues, self.
serviceservice[CharacteristicsTypes.REMOTE_KEY]
132 """List of all input sources for this television."""
135 this_accessory = self.
_accessory_accessory.entity_map.aid(self._aid)
136 this_tv = this_accessory.services.iid(self._iid)
138 input_sources = this_accessory.services.filter(
139 service_type=ServicesTypes.INPUT_SOURCE,
140 parent_service=this_tv,
143 for input_source
in input_sources:
144 char = input_source[CharacteristicsTypes.CONFIGURED_NAME]
145 sources.append(char.value)
150 """Name of the current input source."""
151 active_identifier = self.
serviceservice.value(CharacteristicsTypes.ACTIVE_IDENTIFIER)
152 if not active_identifier:
155 this_accessory = self.
_accessory_accessory.entity_map.aid(self._aid)
156 this_tv = this_accessory.services.iid(self._iid)
158 input_source = this_accessory.services.first(
159 service_type=ServicesTypes.INPUT_SOURCE,
160 characteristics={CharacteristicsTypes.IDENTIFIER: active_identifier},
161 parent_service=this_tv,
164 char = input_source[CharacteristicsTypes.CONFIGURED_NAME]
168 def state(self) -> MediaPlayerState:
169 """State of the tv."""
170 active = self.
serviceservice.value(CharacteristicsTypes.ACTIVE)
172 return MediaPlayerState.OFF
174 homekit_state = self.
serviceservice.value(CharacteristicsTypes.CURRENT_MEDIA_STATE)
175 if homekit_state
is not None:
176 return HK_TO_HA_STATE.get(homekit_state, MediaPlayerState.ON)
178 return MediaPlayerState.ON
181 """Send play command."""
183 _LOGGER.debug(
"Cannot play while already playing")
188 {CharacteristicsTypes.TARGET_MEDIA_STATE: TargetMediaStateValues.PLAY}
192 {CharacteristicsTypes.REMOTE_KEY: RemoteKeyValues.PLAY_PAUSE}
196 """Send pause command."""
198 _LOGGER.debug(
"Cannot pause while already paused")
203 {CharacteristicsTypes.TARGET_MEDIA_STATE: TargetMediaStateValues.PAUSE}
207 {CharacteristicsTypes.REMOTE_KEY: RemoteKeyValues.PLAY_PAUSE}
211 """Send stop command."""
213 _LOGGER.debug(
"Cannot stop when already idle")
218 {CharacteristicsTypes.TARGET_MEDIA_STATE: TargetMediaStateValues.STOP}
222 """Switch to a different media source."""
223 this_accessory = self.
_accessory_accessory.entity_map.aid(self._aid)
224 this_tv = this_accessory.services.iid(self._iid)
226 input_source = this_accessory.services.first(
227 service_type=ServicesTypes.INPUT_SOURCE,
228 characteristics={CharacteristicsTypes.CONFIGURED_NAME: source},
229 parent_service=this_tv,
233 raise ValueError(f
"Could not find source {source}")
235 identifier = input_source[CharacteristicsTypes.IDENTIFIER]
238 {CharacteristicsTypes.ACTIVE_IDENTIFIER: identifier.value}
None async_put_characteristics(self, dict[str, Any] characteristics)