""" The panopticon provides a way to observe (& control) all running Hugveys trough a web interface """ import logging import tornado import tornado.websocket import tornado.web import tornado.ioloop import os from pytz.reference import Central import asyncio import json from urllib.parse import urlparse logger = logging.getLogger("panopticon") web_dir = os.path.join(os.path.split(__file__)[0], '..', 'www') print(web_dir) def getWebSocketHandler(central_command): class WebSocketHandler(tornado.websocket.WebSocketHandler): CORS_ORIGINS = ['localhost'] connections = set() def check_origin(self, origin): parsed_origin = urlparse(origin) # parsed_origin.netloc.lower() gives localhost:3333 valid = parsed_origin.hostname in self.CORS_ORIGINS return valid # the client connected def open(self): self.connections.add(self) logger.info("New client connected") # the client sent the message def on_message(self, message): logger.debug(f"recieve: {message}") try: msg = json.loads(message) if msg['action'] == 'init': self.msgInit() if msg['action'] == 'get_status': self.msgStatus() if msg['action'] == 'resume': self.msgResume(msg['hugvey']) if msg['action'] == 'pause': self.msgPause(msg['hugvey']) if msg['action'] == 'restart': self.msgRestart(msg['hugvey']) except Exception as e: self.send({'alert': 'Invalid request: {}'.format(e)}) def send(self, message): j = json.dumps(message) print(self.connections) [con.write_message(j) for con in self.connections] # client disconnected def on_close(self): self.connections.remove(self) logger.info("Client disconnected") def getStatusMsg(self): msg = central_command.getStatusSummary() msg['action'] = 'status' return msg def msgStatus(self): self.send(self.getStatusMsg()) def msgInit(self): msg = self.getStatusMsg() self.send(msg) def msgResume(self, hv_id): central_command.hugveys[hv_id].eventQueue.put({'event': 'resume'}) def msgPause(self, hv_id): central_command.hugveys[hv_id].eventQueue.put({'event': 'pause'}) def msgRestart(self, hv_id): central_command.hugveys[hv_id].eventQueue.put({'event': 'restart'}) return WebSocketHandler class Panopticon(object): def __init__(self, central_command, config): self.command = central_command self.config = config self.application = tornado.web.Application([ (r"/ws", getWebSocketHandler(self.command)), (r"/local/(.*)", tornado.web.StaticFileHandler, {"path": config['web']['files_dir']}), (r"/(.*)", tornado.web.StaticFileHandler, {"path": web_dir, "default_filename": 'index.html'}), ], debug=True) self.application.listen(config['web']['port']) # self.loop.configure(evt_loop) def start(self): evt_loop = asyncio.new_event_loop() asyncio.set_event_loop(evt_loop) self.loop = tornado.ioloop.IOLoop.current() logger.info(f"Start Panopticon on http://localhost:{self.config['web']['port']}") self.loop.start() def stop(self): self.loop.stop()