import logging import json from tornado.websocket import WebSocketHandler import zmq from zmq.eventloop.zmqstream import ZMQStream from zmq.eventloop import ioloop from config import PUBLISHER_PORT, RECEIVER_PORT from buttons import Buttons ioloop.install() class ZMQWebSocketHandler(WebSocketHandler): def __init__(self, application, request, zmq_context=None, **kwargs): super().__init__(application, request, **kwargs) self.zmq_context = zmq_context or zmq.Context.instance() self.zmq_pull_socket = self.zmq_context.socket(zmq.PULL) self.zmq_pull_stream = ZMQStream(self.zmq_pull_socket) self.zmq_pub_socket = self.zmq_context.socket(zmq.PUB) self.fsm = Buttons(self) def open(self, *args, **kwargs): pub_socket_address = 'tcp://*:{}'.format(PUBLISHER_PORT) self.zmq_pub_socket.bind(pub_socket_address) logging.debug('Pub socket bound to {}'.format(pub_socket_address)) pull_socket_address = 'tcp://*:{}'.format(RECEIVER_PORT) self.zmq_pull_socket.bind(pull_socket_address) logging.debug('Pull socket bound to {}'.format(pull_socket_address)) def zmq_callback(msg_parts): anchor, data = msg_parts logging.debug('Received on pull socket: {}'.format(data.decode())) self.write_message(data.decode()) self.zmq_pull_stream.on_recv(zmq_callback) def on_message(self, message): logging.debug('Received on WebSocket: {}'.format(message)) self.fsm.trigger(self._parse_anchor(message), message=message) def send_message(self, message, anchor: str = None): if not anchor: anchor = self._parse_anchor(message) encoded_message = [part.encode('utf-8') for part in (anchor, message)] self.zmq_pub_socket.send_multipart(encoded_message) def on_close(self): self.zmq_pull_socket.close() self.zmq_pub_socket.close() # much secure, very cors, wow def check_origin(self, origin): return True @staticmethod def _parse_anchor(message): message_json = json.loads(message) return message_json['anchor']