7 from django.core.management.base import BaseCommand
9 from nonstop.app_settings import app_settings
11 logger = logging.getLogger('switch-proxy')
14 class PanikSwitchProtocol(asyncio.DatagramProtocol):
17 self.currently_active = 0
18 self.update_with_http()
19 self.websocket_connections = set()
21 def datagram_received(self, data, addr):
22 logger.debug('Datagram received: %s', data)
23 new_active = json.loads(data)['active']
24 if new_active != self.currently_active:
25 logger.info('UDP update, %s -> %s', self.currently_active, new_active)
26 self.currently_active = json.loads(data)['active']
28 async def websocket_handler(self, websocket, path):
29 self.websocket_connections.add(websocket)
32 if self.currently_active != latest_active:
33 latest_active = self.currently_active
35 for ws in self.websocket_connections:
37 await ws.send(json.dumps({'active': self.currently_active}))
38 except websockets.exceptions.ConnectionClosed:
41 self.websocket_connections.remove(ws)
42 await asyncio.sleep(0.1)
44 def update_with_http(self):
46 resp = requests.get(app_settings.ON_AIR_SWITCH_URL, timeout=2)
48 new_active = resp.json().get('active')
49 if new_active != self.currently_active:
50 logger.info('HTTP-only update, %s -> %s', self.currently_active, new_active)
51 self.currently_active = resp.json().get('active')
52 except (OSError, requests.exceptions.RequestException):
56 class Command(BaseCommand):
57 help = 'proxy between arduino switch and websockets'
59 def add_arguments(self, parser):
60 parser.add_argument('--udp-port', metavar='UDP_PORT', default='1312')
61 parser.add_argument('--http-port', metavar='HTTP_PORT', default='8765')
63 def handle(self, verbosity, **options):
64 self.udp_port = int(options.get('udp_port'))
65 self.http_port = int(options.get('http_port'))
66 asyncio.run(self.main())
69 loop = asyncio.get_running_loop()
70 proto = PanikSwitchProtocol()
71 await websockets.serve(proto.websocket_handler, '0.0.0.0', self.http_port)
72 transport, protocol = await loop.create_datagram_endpoint(
73 lambda: proto, local_addr=('0.0.0.0', self.udp_port)
77 await asyncio.sleep(300)
78 proto.update_with_http()