def connect_to_site(self): logger.info("Connecting to Site: {}".format(cfg.IP_CONNECTION_SITEID)) if self.site_info is None: self.site_info = self.get_site_info( siteid=cfg.IP_CONNECTION_SITEID, email=cfg.IP_CONNECTION_EMAIL) if self.site_info is None: logger.error("Unable to get site info") return False try: logger.debug("Site Info: {}".format( json.dumps(self.site_info, indent=4))) xoraddr = binascii.unhexlify( self.site_info['site'][0]['module'][0]['xoraddr']) stun_host = 'turn.paradoxmyhome.com' logger.debug("STUN TCP Change Request") self.client = stun.StunClient(stun_host) self.client.send_tcp_change_request() stun_r = self.client.receive_response() if stun.is_error(stun_r): logger.error(stun.get_error(stun_r)) return False logger.debug("STUN TCP Binding Request") self.client.send_binding_request() stun_r = self.client.receive_response() if stun.is_error(stun_r): logger.error(stun.get_error(stun_r)) return False logger.debug("STUN Connect Request") self.client.send_connect_request(xoraddr=xoraddr) stun_r = self.client.receive_response() if stun.is_error(stun_r): logger.error(stun.get_error(stun_r)) return False self.connection_timestamp = time.time() connection_id = stun_r[0]['attr_body'] raddr = self.client.sock.getpeername() logger.debug("STUN Connection Bind Request") self.client1 = stun.StunClient(host=raddr[0], port=raddr[1]) self.client1.send_connection_bind_request( binascii.unhexlify(connection_id)) stun_r = self.client1.receive_response() if stun.is_error(stun_r): logger.error(stun.get_error(stun_r)) return False self.socket = self.client1.sock logger.info("Connected to Site: {}".format( cfg.IP_CONNECTION_SITEID)) except Exception: logger.exception("Unable to negotiate connection to site") return True
async def _stun_tcp_binding_request(self): logger.debug("STUN TCP Binding Request") self.stun_control.send_binding_request() stun_r = self.stun_control.receive_response() if stun.is_error(stun_r): raise ConnectToSiteFailed( f"STUN TCP Binding Request error: {stun.get_error(stun_r)}")
async def _stun_connect(self, xoraddr): logger.debug("STUN Connect Request") self.stun_control.send_connect_request(xoraddr=xoraddr) stun_r = self.stun_control.receive_response() if stun.is_error(stun_r): raise ConnectToSiteFailed( f"STUN Connect Request error: {stun.get_error(stun_r)}") return stun_r
async def _stun_tcp_change_request(self): stun_host = "turn.paradoxmyhome.com" logger.debug("STUN TCP Change Request") self.stun_control = stun.StunClient(stun_host) self.stun_control.send_tcp_change_request() stun_r = self.stun_control.receive_response() if stun.is_error(stun_r): raise ConnectToSiteFailed( f"STUN TCP Change Request error: {stun.get_error(stun_r)}")
def refresh_session_if_required(self) -> None: if self.site_info is None or self.connection_timestamp == 0: return # Refresh session if required if time.time() - self.connection_timestamp >= 500: logger.info("STUN Session Refresh") self.stun_control.send_refresh_request() stun_r = self.stun_control.receive_response() if stun.is_error(stun_r): self.connected = False raise StunSessionRefreshFailed( f"STUN Session Refresh failed: {stun.get_error(stun_r)}") self.connection_timestamp = time.time()
async def connect(self) -> None: self.connection_timestamp = 0 logger.info("Connecting to Site: {}".format(self.site_id)) if self.site_info is None: self.site_info = await self._get_site_info(siteid=self.site_id, email=self.email) if self.site_info is None: raise ConnectToSiteFailed("Unable to get site info") logger.debug("Site Info: {}".format( json.dumps(self.site_info, indent=4))) self.module = self._select_module() if self.module is None: self.site_info = None # Reset state raise ConnectToSiteFailed( "Unable to find module with desired panel serial") xoraddr = binascii.unhexlify(self.module["xoraddr"]) await self._stun_tcp_change_request() await self._stun_tcp_binding_request() stun_r = await self._stun_connect(xoraddr) self.connection_timestamp = time.time() connection_id = stun_r[0]["attr_body"] raddr = self.stun_control.sock.getpeername() logger.debug("STUN Connection Bind Request") self.stun_tunnel = stun.StunClient(host=raddr[0], port=raddr[1]) self.stun_tunnel.send_connection_bind_request( binascii.unhexlify(connection_id)) stun_r = self.stun_tunnel.receive_response() if stun.is_error(stun_r): raise ConnectToSiteFailed( f"STUN Connection Bind Request error: {stun.get_error(stun_r)}" ) logger.info("Connected to Site: {}".format(self.site_id))
def refresh_stun(self): if self.site_info is None: return True try: # Refresh session if required if time.time() - self.connection_timestamp >= 500: logger.debug("Refreshing session") self.client.send_refresh_request() stun_r = self.client.receive_response() if stun.is_error(stun_r): logger.error(stun.get_error(stun_r)) self.connected = False return False self.connection_timestamp = time.time() return True except Exception: logger.exception("Session refresh") return False
async def connect(self) -> None: self.connection_timestamp = 0 logger.info("Connecting to Site: {}".format(self.site_id)) if self.site_info is None: self.site_info = await self._get_site_info( siteid=self.site_id, email=self.email ) if self.site_info is None: raise ConnectToSiteFailed("Unable to get site info") # xoraddr = binascii.unhexlify(self.site_info['site'][0]['module'][0]['xoraddr']) self.module = None logger.debug("Site Info: {}".format(json.dumps(self.site_info, indent=4))) if self.panel_serial is not None: for site in self.site_info["site"]: for module in site: logger.debug( "Found module with panel serial: {}".format( module["panelSerial"] ) ) if module["panelSerial"] == self.panel_serial: self.module = module break if self.module is not None: break else: self.module = self.site_info["site"][0]["module"][0] # Use first if self.module is None: self.site_info = None # Reset state raise ConnectToSiteFailed("Unable to find module with desired panel serial") xoraddr = binascii.unhexlify(self.module["xoraddr"]) stun_host = "turn.paradoxmyhome.com" logger.debug("STUN TCP Change Request") self.stun_control = stun.StunClient(stun_host) self.stun_control.send_tcp_change_request() stun_r = self.stun_control.receive_response() if stun.is_error(stun_r): raise ConnectToSiteFailed( f"STUN TCP Change Request error: {stun.get_error(stun_r)}" ) logger.debug("STUN TCP Binding Request") self.stun_control.send_binding_request() stun_r = self.stun_control.receive_response() if stun.is_error(stun_r): raise ConnectToSiteFailed( f"STUN TCP Binding Request error: {stun.get_error(stun_r)}" ) logger.debug("STUN Connect Request") self.stun_control.send_connect_request(xoraddr=xoraddr) stun_r = self.stun_control.receive_response() if stun.is_error(stun_r): raise ConnectToSiteFailed( f"STUN Connect Request error: {stun.get_error(stun_r)}" ) self.connection_timestamp = time.time() connection_id = stun_r[0]["attr_body"] raddr = self.stun_control.sock.getpeername() logger.debug("STUN Connection Bind Request") self.stun_tunnel = stun.StunClient(host=raddr[0], port=raddr[1]) self.stun_tunnel.send_connection_bind_request(binascii.unhexlify(connection_id)) stun_r = self.stun_tunnel.receive_response() if stun.is_error(stun_r): raise ConnectToSiteFailed( f"STUN Connection Bind Request error: {stun.get_error(stun_r)}" ) logger.info("Connected to Site: {}".format(self.site_id))
async def connect_to_site(self): loop = asyncio.get_event_loop() self.connection_timestamp = 0 logger.info("Connecting to Site: {}".format(cfg.IP_CONNECTION_SITEID)) if self.site_info is None: self.site_info = self.get_site_info(siteid=cfg.IP_CONNECTION_SITEID, email=cfg.IP_CONNECTION_EMAIL) if self.site_info is None: logger.error("Unable to get site info") return False try: xoraddr = binascii.unhexlify(self.site_info['site'][0]['module'][0]['xoraddr']) if self.site_info is None: logger.error("Unable to get site info") return False self.module = None logger.debug("Site Info: {}".format(json.dumps(self.site_info, indent=4))) if cfg.IP_CONNECTION_PANEL_SERIAL is not None: for site in self.site_info['site']: for module in site: logger.debug("Found module with panel serial: {}".format(module['panelSerial'])) if module['panelSerial'] == cfg.IP_CONNECTION_PANEL_SERIAL: self.module = module break if self.module is not None: break else: self.module = self.site_info['site'][0]['module'][0] # Use first if self.module is None: self.site_info = None # Reset state logger.error("Unable to find module with desired panel serial") return False xoraddr = binascii.unhexlify(self.module['xoraddr']) stun_host = 'turn.paradoxmyhome.com' logger.debug("STUN TCP Change Request") self.client = stun.StunClient(stun_host) self.client.send_tcp_change_request() stun_r = self.client.receive_response() if stun.is_error(stun_r): logger.error(stun.get_error(stun_r)) return False logger.debug("STUN TCP Binding Request") self.client.send_binding_request() stun_r = self.client.receive_response() if stun.is_error(stun_r): logger.error(stun.get_error(stun_r)) return False logger.debug("STUN Connect Request") self.client.send_connect_request(xoraddr=xoraddr) stun_r = self.client.receive_response() if stun.is_error(stun_r): logger.error(stun.get_error(stun_r)) return False self.connection_timestamp = time.time() connection_id = stun_r[0]['attr_body'] raddr = self.client.sock.getpeername() logger.debug("STUN Connection Bind Request") self.client1 = stun.StunClient(host=raddr[0], port=raddr[1]) self.client1.send_connection_bind_request(binascii.unhexlify(connection_id)) stun_r = self.client1.receive_response() if stun.is_error(stun_r): logger.error(stun.get_error(stun_r)) return False _, self.connection = await loop.create_connection(self.make_protocol, sock=self.client1.sock) logger.info("Connected to Site: {}".format(cfg.IP_CONNECTION_SITEID)) except Exception: logger.exception("Unable to negotiate connection to site") return True