This commit is contained in:
Maxim Devaev
2022-01-18 09:25:17 +03:00
parent 3ee1948f19
commit 3ab43edeb9
8 changed files with 254 additions and 11 deletions

View File

@@ -32,6 +32,7 @@ from typing import List
from typing import Dict
from typing import Set
from typing import Callable
from typing import Awaitable
from typing import Coroutine
from typing import AsyncGenerator
from typing import Optional
@@ -68,6 +69,7 @@ from .logreader import LogReader
from .ugpio import UserGpio
from .streamer import Streamer
from .snapshoter import Snapshoter
from .tesseract import TesseractOcr
from .http import HttpError
from .http import HttpExposed
@@ -147,6 +149,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
info_manager: InfoManager,
log_reader: LogReader,
user_gpio: UserGpio,
ocr: TesseractOcr,
hid: BaseHid,
atx: BaseAtx,
@@ -192,6 +195,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
]
self.__hid_api = HidApi(hid, keymap_path, ignore_keys, mouse_x_range, mouse_y_range) # Ugly hack to get keymaps state
self.__streamer_api = StreamerApi(streamer, ocr) # Same hack to get ocr langs state
self.__apis: List[object] = [
self,
AuthApi(auth_manager),
@@ -201,7 +205,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
self.__hid_api,
AtxApi(atx),
MsdApi(msd),
StreamerApi(streamer),
self.__streamer_api,
ExportApi(info_manager, atx, user_gpio),
RedfishApi(info_manager, atx),
]
@@ -251,21 +255,27 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
@exposed_http("GET", "/ws")
async def __ws_handler(self, request: aiohttp.web.Request) -> aiohttp.web.WebSocketResponse:
logger = get_logger(0)
client = _WsClient(
ws=aiohttp.web.WebSocketResponse(heartbeat=self.__heartbeat),
stream=valid_bool(request.query.get("stream", "true")),
)
await client.ws.prepare(request)
await self.__register_ws_client(client)
try:
await self.__send_event(client.ws, "gpio_model_state", await self.__user_gpio.get_model())
await self.__send_event(client.ws, "hid_keymaps_state", self.__hid_api.get_keymaps())
await asyncio.gather(*[
self.__send_event(client.ws, component.event_type, await component.get_state())
for component in self.__components
if component.get_state
await self.__send_events_aws(client.ws, [
("gpio_model_state", self.__user_gpio.get_model()),
("hid_keymaps_state", self.__hid_api.get_keymaps()),
("streamer_ocr_state", self.__streamer_api.get_ocr()),
])
await self.__send_events_aws(client.ws, [
(comp.event_type, comp.get_state())
for comp in self.__components
if comp.get_state
])
await self.__send_event(client.ws, "loop", {})
async for msg in client.ws:
if msg.type == aiohttp.web.WSMsgType.TEXT:
try:
@@ -282,6 +292,7 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
logger.error("Unknown websocket event: %r", data)
else:
break
return client.ws
finally:
await self.__remove_ws_client(client)
@@ -380,6 +391,15 @@ class KvmdServer(HttpServer): # pylint: disable=too-many-arguments,too-many-ins
logger.exception("Cleanup error on %s", comp.name)
logger.info("On-Cleanup complete")
async def __send_events_aws(self, ws: aiohttp.web.WebSocketResponse, sources: List[Tuple[str, Awaitable]]) -> None:
await asyncio.gather(*[
self.__send_event(ws, event_type, state)
for (event_type, state) in zip(
map(operator.itemgetter(0), sources),
await asyncio.gather(*map(operator.itemgetter(1), sources)),
)
])
async def __send_event(self, ws: aiohttp.web.WebSocketResponse, event_type: str, event: Optional[Dict]) -> None:
await ws.send_str(json.dumps({
"event_type": event_type,