async def ws_get_statistics_during_period( opp: OpenPeerPower, connection: websocket_api.ActiveConnection, msg: dict ) -> None: """Handle statistics websocket command.""" start_time_str = msg["start_time"] end_time_str = msg.get("end_time") start_time = dt_util.parse_datetime(start_time_str) if start_time: start_time = dt_util.as_utc(start_time) else: connection.send_error(msg["id"], "invalid_start_time", "Invalid start_time") return if end_time_str: end_time = dt_util.parse_datetime(end_time_str) if end_time: end_time = dt_util.as_utc(end_time) else: connection.send_error(msg["id"], "invalid_end_time", "Invalid end_time") return else: end_time = None statistics = await opp.async_add_executor_job( statistics_during_period, opp, start_time, end_time, msg.get("statistic_id"), ) connection.send_result(msg["id"], {"statistics": statistics})
async def ws_update_item(self, opp: OpenPeerPower, connection: websocket_api.ActiveConnection, msg: dict) -> None: """Update a item.""" data = dict(msg) msg_id = data.pop("id") item_id = data.pop(self.item_id_key) data.pop("type") try: item = await self.storage_collection.async_update_item( item_id, data) connection.send_result(msg_id, item) except ItemNotFound: connection.send_error( msg["id"], websocket_api.const.ERR_NOT_FOUND, f"Unable to find {self.item_id_key} {item_id}", ) except vol.Invalid as err: connection.send_error( msg["id"], websocket_api.const.ERR_INVALID_FORMAT, humanize_error(data, err), ) except ValueError as err: connection.send_error(msg_id, websocket_api.const.ERR_INVALID_FORMAT, str(err))
def ws_list_person(opp: OpenPeerPowerType, connection: websocket_api.ActiveConnection, msg): """List persons.""" yaml, storage = opp.data[DOMAIN] connection.send_result(msg[ATTR_ID], { "storage": storage.async_items(), "config": yaml.async_items() })
async def websocket_update_prefs( opp: OpenPeerPower, connection: ActiveConnection, msg: dict ) -> None: """Handle request for account info.""" prefs = opp.data[DATA_CAMERA_PREFS] changes = dict(msg) changes.pop("id") changes.pop("type") entity_id = changes.pop("entity_id") await prefs.async_update(entity_id, **changes) connection.send_result(msg["id"], prefs.get(entity_id).as_dict())
async def ws_delete_item(self, opp: OpenPeerPower, connection: websocket_api.ActiveConnection, msg: dict) -> None: """Delete a item.""" try: await self.storage_collection.async_delete_item( msg[self.item_id_key]) except ItemNotFound: connection.send_error( msg["id"], websocket_api.const.ERR_NOT_FOUND, f"Unable to find {self.item_id_key} {msg[self.item_id_key]}", ) connection.send_result(msg["id"])
async def ws_create_item(self, opp: OpenPeerPower, connection: websocket_api.ActiveConnection, msg: dict) -> None: """Create a item.""" try: data = dict(msg) data.pop("id") data.pop("type") item = await self.storage_collection.async_create_item(data) connection.send_result(msg["id"], item) except vol.Invalid as err: connection.send_error( msg["id"], websocket_api.const.ERR_INVALID_FORMAT, humanize_error(data, err), ) except ValueError as err: connection.send_error(msg["id"], websocket_api.const.ERR_INVALID_FORMAT, str(err))
async def ws_camera_stream( opp: OpenPeerPower, connection: ActiveConnection, msg: dict ) -> None: """Handle get camera stream websocket command. Async friendly. """ try: entity_id = msg["entity_id"] camera = _get_camera_from_entity_id(opp, entity_id) url = await _async_stream_endpoint_url(opp, camera, fmt=msg["format"]) connection.send_result(msg["id"], {"url": url}) except OpenPeerPowerError as ex: _LOGGER.error("Error requesting stream: %s", ex) connection.send_error(msg["id"], "start_stream_failed", str(ex)) except asyncio.TimeoutError: _LOGGER.error("Timeout getting stream source") connection.send_error( msg["id"], "start_stream_failed", "Timeout getting stream source" )
def ws_list_item(self, opp: OpenPeerPower, connection: websocket_api.ActiveConnection, msg: dict) -> None: """List items.""" connection.send_result(msg["id"], self.storage_collection.async_items())
async def handle_info(opp: OpenPeerPower, connection: websocket_api.ActiveConnection, msg: dict): """Handle an info request via a subscription.""" registrations: dict[str, SystemHealthRegistration] = opp.data[DOMAIN] data = {} pending_info = {} for domain, domain_data in zip( registrations, await asyncio.gather(*(get_integration_info(opp, registration) for registration in registrations.values())), ): for key, value in domain_data["info"].items(): if asyncio.iscoroutine(value): value = asyncio.create_task(value) if isinstance(value, asyncio.Task): pending_info[(domain, key)] = value domain_data["info"][key] = {"type": "pending"} else: domain_data["info"][key] = _format_value(value) data[domain] = domain_data # Confirm subscription connection.send_result(msg["id"]) stop_event = asyncio.Event() connection.subscriptions[msg["id"]] = stop_event.set # Send initial data connection.send_message( websocket_api.messages.event_message(msg["id"], { "type": "initial", "data": data })) # If nothing pending, wrap it up. if not pending_info: connection.send_message( websocket_api.messages.event_message(msg["id"], {"type": "finish"})) return tasks = [asyncio.create_task(stop_event.wait()), *pending_info.values()] pending_lookup = {val: key for key, val in pending_info.items()} # One task is the stop_event.wait() and is always there while len(tasks) > 1 and not stop_event.is_set(): # Wait for first completed task done, tasks = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED) if stop_event.is_set(): for task in tasks: task.cancel() return # Update subscription of all finished tasks for result in done: domain, key = pending_lookup[result] event_msg = { "type": "update", "domain": domain, "key": key, } if result.exception(): exception = result.exception() _LOGGER.error( "Error fetching system info for %s - %s", domain, key, exc_info=(type(exception), exception, exception.__traceback__), ) event_msg["success"] = False event_msg["error"] = {"type": "failed", "error": "unknown"} else: event_msg["success"] = True event_msg["data"] = _format_value(result.result()) connection.send_message( websocket_api.messages.event_message(msg["id"], event_msg)) connection.send_message( websocket_api.messages.event_message(msg["id"], {"type": "finish"}))
async def websocket_get_prefs( opp: OpenPeerPower, connection: ActiveConnection, msg: dict ) -> None: """Handle request for account info.""" prefs = opp.data[DATA_CAMERA_PREFS].get(msg["entity_id"]) connection.send_result(msg["id"], prefs.as_dict())