1 """Harmony data object which contains the Harmony Client."""
3 from __future__
import annotations
5 from collections.abc
import Iterable
8 from aioharmony.const
import ClientCallbackType, SendCommandDevice
9 import aioharmony.exceptions
as aioexc
10 from aioharmony.harmonyapi
import HarmonyAPI
as HarmonyClient
17 from .const
import ACTIVITY_POWER_OFF
18 from .subscriber
import HarmonySubscriberMixin
20 _LOGGER = logging.getLogger(__name__)
23 type HarmonyConfigEntry = ConfigEntry[HarmonyData]
27 """HarmonyData registers for Harmony hub updates."""
29 _client: HarmonyClient
32 self, hass: HomeAssistant, address: str, name: str, unique_id: str |
None
34 """Initialize a data object."""
43 """List of all non-poweroff activity objects."""
44 activity_infos = self.
_client_client.config.get(
"activity", [])
47 for info
in activity_infos
48 if info[
"label"]
is not None and info[
"label"] != ACTIVITY_POWER_OFF
53 """Names of all the remotes activities."""
55 return [activity[
"label"]
for activity
in activity_infos]
59 """Names of all of the devices connected to the hub."""
60 device_infos = self.
_client_client.config.get(
"device", [])
61 return [device[
"label"]
for device
in device_infos]
65 """Return the Harmony device's unique_id."""
70 """Return the hub config as json."""
71 if self.
_client_client.config
is None:
73 return self.
_client_client.json_config
77 """Return if connected to the hub."""
82 """Return the current activity tuple."""
83 return self.
_client_client.current_activity
86 """Return hub device info."""
88 if "ethernetStatus" in self.
_client_client.hub_config.info:
89 model =
"Harmony Hub Pro 2400"
91 identifiers={(domain, self.
unique_idunique_id)},
92 manufacturer=
"Logitech",
95 sw_version=self.
_client_client.hub_config.info.get(
96 "hubSwVersion", self.
_client_client.fw_version
98 configuration_url=
"https://www.logitech.com/en-us/my-account",
102 """Connect to the Harmony Hub."""
103 _LOGGER.debug(
"%s: Connecting", self.
namename)
113 ip_address=self.
_address_address, callbacks=ClientCallbackType(**callbacks)
119 except (TimeoutError, aioexc.TimeOut)
as err:
120 await self.
_client_client.close()
122 f
"{self.name}: Connection timed-out to {self._address}:8088"
124 except (ValueError, AttributeError)
as err:
125 await self.
_client_client.close()
127 f
"{self.name}: Error {err} while connected HUB at:"
128 f
" {self._address}:8088"
131 await self.
_client_client.close()
133 f
"{self.name}: Unable to connect to HUB at: {self._address}:8088"
137 """Close connection on shutdown."""
138 _LOGGER.debug(
"%s: Closing Harmony Hub", self.
namename)
140 await self.
_client_client.close()
141 except aioexc.TimeOut:
142 _LOGGER.warning(
"%s: Disconnect timed-out", self.
namename)
145 """Start an activity from the Harmony device."""
148 _LOGGER.error(
"%s: No activity specified with turn_on service", self.
namename)
154 if activity.isdigit()
or activity ==
"-1":
155 _LOGGER.debug(
"%s: Activity is numeric", self.
namename)
156 activity_name = self.
_client_client.get_activity_name(
int(activity))
158 activity_id = activity
160 if activity_id
is None:
161 _LOGGER.debug(
"%s: Find activity ID based on name", self.
namename)
162 activity_name =
str(activity)
163 activity_id = self.
_client_client.get_activity_id(activity_name)
165 if activity_id
is None:
166 _LOGGER.error(
"%s: Activity %s is invalid", self.
namename, activity)
170 if current_activity_name == activity_name:
176 "%s: Current activity is already %s", self.
namename, activity_name
182 await self.
_client_client.start_activity(activity_id)
183 except aioexc.TimeOut:
184 _LOGGER.error(
"%s: Starting activity %s timed-out", self.
namename, activity)
188 """Start the PowerOff activity."""
189 _LOGGER.debug(
"%s: Turn Off", self.
namename)
191 await self.
_client_client.power_off()
192 except aioexc.TimeOut:
193 _LOGGER.error(
"%s: Powering off timed-out", self.
namename)
197 commands: Iterable[str],
203 """Send a list of commands to one device."""
206 _LOGGER.debug(
"%s: Device %s is numeric", self.
namename, device)
210 if device_id
is None:
212 "%s: Find device ID %s based on device name", self.
namename, device
216 if device_id
is None:
217 _LOGGER.error(
"%s: Device %s is invalid", self.
namename, device)
222 "Sending commands to device %s holding for %s seconds "
223 "with a delay of %s seconds"
232 for _
in range(num_repeats):
233 for single_command
in commands:
234 send_command = SendCommandDevice(
235 device=device_id, command=single_command, delay=hold_secs
237 snd_cmnd_list.append(send_command)
239 snd_cmnd_list.append(
float(delay_secs))
241 _LOGGER.debug(
"%s: Sending commands", self.
namename)
243 result_list = await self.
_client_client.send_commands(snd_cmnd_list)
244 except aioexc.TimeOut:
245 _LOGGER.error(
"%s: Sending commands timed-out", self.
namename)
248 for result
in result_list:
250 "Sending command %s to device %s failed with code %s: %s",
251 result.command.command,
252 result.command.device,
258 """Change the channel using Harmony remote."""
259 _LOGGER.debug(
"%s: Changing channel to %s", self.
namename, channel)
262 except aioexc.TimeOut:
263 _LOGGER.error(
"%s: Changing channel to %s timed-out", self.
namename, channel)
266 """Sync the Harmony device with the web service.
268 Returns True if the sync was successful.
270 _LOGGER.debug(
"%s: Syncing hub with Harmony cloud", self.
namename)
273 except aioexc.TimeOut:
274 _LOGGER.error(
"%s: Syncing hub with Harmony cloud timed-out", self.
namename)
None async_send_command(self, Iterable[str] commands, str device, int num_repeats, float delay_secs, float hold_secs)
None async_start_activity(self, str activity)
None __init__(self, HomeAssistant hass, str address, str name, str|None unique_id)
None change_channel(self, int channel)
tuple current_activity(self)
None async_power_off(self)
list[str] activity_names(self)
DeviceInfo device_info(self, str domain)
None _disconnected(self, str|None _=None)
None async_unlock_start_activity(self)
None _connected(self, str|None _=None)
None _activity_started(self, tuple activity_info)
None _config_updated(self, dict|None _=None)
None async_lock_start_activity(self)
None _activity_starting(self, tuple activity_info)
str get_device_id(ServerInfoMessage server_info, MatterEndpoint endpoint)
str get_device_name(Device device, Device|None parent=None)