76 lines
2.1 KiB
Python
76 lines
2.1 KiB
Python
from logging import getLogger
|
|
from threading import Thread
|
|
from typing_extensions import override
|
|
|
|
from redis import ConnectionError
|
|
from tornado.ioloop import IOLoop
|
|
from tornado.websocket import WebSocketHandler
|
|
|
|
from platypush.config import Config
|
|
from platypush.message.event import Event
|
|
from platypush.utils import get_redis
|
|
|
|
events_redis_topic = f'_platypush/{Config.get("device_id")}/events' # type: ignore
|
|
logger = getLogger(__name__)
|
|
|
|
|
|
class WSEventProxy(WebSocketHandler, Thread):
|
|
"""
|
|
Websocket event proxy mapped to ``/ws/events``.
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self._sub = get_redis().pubsub()
|
|
self._io_loop = IOLoop.current()
|
|
|
|
@override
|
|
def open(self, *_, **__):
|
|
logger.info('Started websocket connection with %s', self.request.remote_ip)
|
|
self.name = f'ws:events@{self.request.remote_ip}'
|
|
self.start()
|
|
|
|
@override
|
|
def on_message(self, *_, **__):
|
|
pass
|
|
|
|
@override
|
|
def data_received(self, *_, **__):
|
|
pass
|
|
|
|
@override
|
|
def run(self) -> None:
|
|
super().run()
|
|
self._sub.subscribe(events_redis_topic)
|
|
|
|
try:
|
|
for msg in self._sub.listen():
|
|
if (
|
|
msg.get('type') != 'message'
|
|
and msg.get('channel').decode() != events_redis_topic
|
|
):
|
|
continue
|
|
|
|
try:
|
|
evt = Event.build(msg.get('data').decode())
|
|
except Exception as e:
|
|
logger.warning('Error parsing event: %s: %s', msg.get('data'), e)
|
|
continue
|
|
|
|
self._io_loop.asyncio_loop.call_soon_threadsafe( # type: ignore
|
|
self.write_message, str(evt)
|
|
)
|
|
except ConnectionError:
|
|
pass
|
|
|
|
@override
|
|
def on_close(self):
|
|
self._sub.unsubscribe(events_redis_topic)
|
|
self._sub.close()
|
|
logger.info(
|
|
'Websocket connection to %s closed, reason=%s, message=%s',
|
|
self.request.remote_ip,
|
|
self.close_code,
|
|
self.close_reason,
|
|
)
|