def listen(): # 1. create connection to redis redis = RedisClient() try: for msg in ssdp.listen(): # 2. Write JSON to redis pubsub channel json_str = json.dumps(msg) pub_ret = redis.publish('upnp-tools:ssdp', json_str.encode()) finally: redis.close()
def do_GET(self): # want to split path into path?params parts = urllib.parse.urlsplit(self.path) path = parts.path if path == '/': self.sendfile('index.html', 'text/html; charset=utf-8') elif path == '/main.js': self.sendfile('main.js', 'application/javascript; charset=utf-8') elif path == '/main.css': self.sendfile('main.css', 'text/css; charset=utf-8') elif path == '/api/discover': # switch to 1.1 to get the browser to believe the chunked transfer # encoding old_proto = self.protocol_version self.protocol_version = 'HTTP/1.1' try: self.send_response(HTTPStatus.OK) self.send_header('Content-Type', 'application/x-json-stream') self.send_header('Cache-Control', 'no-cache') self.send_header('Transfer-Encoding', 'chunked') self.end_headers() if self.headers['ST']: st = self.headers['ST'] else: st = 'ssdp:all' for svc in ssdp.discover_stream(st): # convert to json chunk = (json.dumps(svc) + '\n').encode('utf-8') self.write_chunk(chunk) # chunked encoding requires us to send an empty chunk at the # end self.write_chunk(b'') finally: self.protocol_version = old_proto elif path == '/api/description' or path == '/api/scpd': params = urllib.parse.parse_qs(parts.query) if 'location' not in params: self.respond_simple( HTTPStatus.BAD_REQUEST, 'location query parameter is required but was missing', ) return location = params['location'][0] print('location =', location) parts = urllib.parse.urlsplit(location) conn = http.client.HTTPConnection(parts.netloc) print('parts.path =', parts.path) rpath = self.path_and_query(location) print('rpath =', rpath) # Sky+ boxes reject our requests unless using this specific # User-Agent string conn.request( 'GET', rpath, headers={ 'User-Agent': 'SKY_skyplus', 'Accept-Language': 'en' }, ) try: f = conn.getresponse() self.send_response(HTTPStatus(f.status)) self.send_header('Content-Type', f.getheader('Content-Type')) if f.getheader('Content-Length'): self.send_header('Content-Length', f.getheader('Content-Length')) self.end_headers() shutil.copyfileobj(f, self.wfile) finally: conn.close() elif path == '/api/notifications': redis = RedisClient() try: self.protocol_version = 'HTTP/1.1' self.send_response(HTTPStatus.OK) self.send_header('Content-Type', 'text/event-stream') self.send_header('Cache-Control', 'no-cache') self.end_headers() for json_bytes in redis.subscribe('upnp-tools:ssdp'): self.wfile.write(b'data: ' + json_bytes + b'\r\n\r\n') finally: redis.close() else: self.respond_simple(HTTPStatus.NOT_FOUND, 'Cannot find ' + self.path)