class WSClient(QObject): def __init__(self, parent): super().__init__(parent) self.client = QWebSocket("", QWebSocketProtocol.Version13, None) self.client.error.connect(self.onError) self.client.connected.connect(self.onConnected) self.client.disconnected.connect(self.onDisconnected) self.ssl_config = QSslConfiguration() self.ssl_cert_file = QFile(":certs/server.pem") self.ssl_cert_file.open(QIODevice.ReadOnly) self.ssl_cert = QSslCertificate(self.ssl_cert_file) self.ssl_config.setCaCertificates([self.ssl_cert]) self.client.setSslConfiguration(self.ssl_config) self.message_queue = [] self.is_connected = False self.telemetry_connected = False self.websocket_url = "wss://localhost:8081" self.websocket_token = "aVerySecureToken" self.timer_connection_watchdog = QTimer(parent) self.timer_connection_watchdog.start(5000) self.timer_connection_watchdog.timeout.connect(self.connection_watchdog) self.timer_reconnect = QTimer(parent) self.timer_reconnect.start(500) self.timer_reconnect.timeout.connect(self.send_message) def onConnected(self): # print("WebSocket: connected") self.is_connected = True def onDisconnected(self): # print("WebSocket: disconnected -> " + self.client.errorString()) self.is_connected = False self.client.abort() def onError(self): # print("WebSocket: error -> " + self.client.errorString()) self.is_connected = False self.client.abort() def queue_message(self, message): self.message_queue.append(message) def send_message(self): if self.is_connected and len(self.message_queue) > 0: message = self.message_queue.pop(0) message['token'] = self.websocket_token if self.client.sendTextMessage(dumps(message, default=json_util.default)) <= 0: self.message_queue.append(message) def connection_watchdog(self): if self.is_connected == False and self.telemetry_connected == True: # print("WebSocket: connecting to -> " + self.websocket_url) c = self.client.open(QUrl(self.websocket_url)) if self.is_connected == True and self.telemetry_connected == False: # print("WebSocket: disconnecting from -> " + self.websocket_url) self.client.close() self.is_connected = False
class NetWorker(QObject): ifcAddrChanged = pyqtSignal(str, name='ifcAddrChanged', arguments=['ip']) currentIfcAddrChanged = pyqtSignal() wifiStatus = pyqtSignal(str, str, int, int, name='wifiStatus', arguments=['essid', 'freq', 'quality', 'level']) wifiStatusChanged = pyqtSignal() @pyqtProperty(str, notify=currentIfcAddrChanged) def currentIfcAddr(self): return self.ifcAddr.toString() @pyqtProperty(str, notify=wifiStatusChanged) def currentWifiESSID(self): return self.essid @pyqtProperty(str, notify=wifiStatusChanged) def currentWifiFreq(self): return self.freq @pyqtProperty(int, notify=wifiStatusChanged) def currentWifiQuality(self): return self.quality @pyqtProperty(int, notify=wifiStatusChanged) def currentWifiLevel(self): return self.level def __init__(self, loglevel='WARNING', ifcName='wlan0'): QObject.__init__(self) self.logger = Logger(name='ratt.networker') self.logger.setLogLevelStr(loglevel) self.debug = self.logger.isDebug() self.mgr = QNetworkAccessManager() self.sslConfig = QSslConfiguration() self.sslSupported = QSslSocket.supportsSsl() self.setAuth() self.setSSLCertConfig() self.mgr.authenticationRequired.connect( self.handleAuthenticationRequired) self.ifcName = ifcName self.ifcAddr = QHostAddress() self.statusTimer = QTimer() self.statusTimer.setSingleShot(False) self.statusTimer.timeout.connect(self.slotStatusTimer) self.statusTimer.start(5000) self.essid = '' self.freq = '' self.quality = 0 self.level = 0 def slotStatusTimer(self): ip = self.getIfcAddress(ifc=self.ifcName) if ip != self.ifcAddr: self.ifcAddr = ip self.ifcAddrChanged.emit(ip.toString()) self.currentIfcAddrChanged.emit() results = {} if self.getWifiStatus(results): self.essid = results['essid'] self.freq = results['freq'] self.quality = results['quality'] self.level = results['level'] self.wifiStatus.emit(self.essid, self.freq, self.quality, self.level) self.wifiStatusChanged.emit() # ['wlan0', 'IEEE', '802.11', 'ESSID:"FooBar"', 'Mode:Managed', 'Frequency:2.412', # 'GHz', 'Access', 'Point:', '00:11:22:33:44:55', 'Bit', 'Rate=65', 'Mb/s', 'Tx-Power=31', # 'dBm', 'Retry', 'short', 'limit:7', 'RTS', 'thr:off', 'Fragment', 'thr:off', 'Power', # 'Management:on', 'Link', 'Quality=43/70', 'Signal', 'level=-67', 'dBm', 'Rx', 'invalid', # 'nwid:0', 'Rx', 'invalid', 'crypt:0', 'Rx', 'invalid', 'frag:0', 'Tx', 'excessive', 'retries:113', # 'Invalid', 'misc:0', 'Missed', 'beacon:0'] def getWifiStatus(self, res): try: iw = getoutput('/sbin/iwconfig %s' % self.ifcName) fields = iw.split() for field in fields: if field.find('ESSID') != -1: res['essid'] = field.split('"')[1] elif field.find('Frequency') != -1: res['freq'] = field.split(':')[1] elif field.find('Quality') != -1: frac = field.split('=')[1] (n, d) = frac.split('/') q = int(n) * 100 / int(d) res['quality'] = q elif field.find('level') != -1: res['level'] = int(field.split('=')[1]) except: return False return True def getIfcAddress(self, ifc): myIfc = QNetworkInterface.interfaceFromName(ifc) addrList = myIfc.addressEntries() for addr in addrList: if addr.ip().protocol() == QAbstractSocket.IPv4Protocol: return addr.ip() return QHostAddress() def setAuth(self, user='', password=''): self.user = user self.password = password def setSSLCertConfig(self, enabled=False, caCertFile='', clientCertFile='', clientKeyFile=''): self.sslEnabled = enabled if self.sslSupported and self.sslEnabled: self.caCertFile = caCertFile self.clientCertFile = clientCertFile self.clientKeyFile = clientKeyFile self.configureCerts() def get(self, url): self.logger.debug('get url=%s' % url.toString()) request = QNetworkRequest(QUrl(url)) request.setRawHeader("User-Agent", "RATT") if self.sslSupported and self.sslEnabled: request.setSslConfiguration(self.sslConfig) reply = self.mgr.get(request) if self.sslSupported and self.sslEnabled: reply.sslErrors.connect(self.handleSSLErrors) return reply def buildRequest(self, url): request = QNetworkRequest(QUrl(url)) request.setHeader(QNetworkRequest.ContentTypeHeader, "application/x-www-form-urlencoded") return request def buildQuery(self, vars): query = str() for key in vars: value = vars[key] sep = '&' if query != '' else '' query = query + '%s%s=%s' % (sep, key, value) return query def post(self, request, query): self.logger.debug('post url=%s query=%s' % (request.url().toString(), query)) if self.sslSupported and self.sslEnabled: request.setSslConfiguration(self.sslConfig) bytearray = QByteArray() bytearray.append(query) reply = self.mgr.post(request, bytearray) if self.sslSupported and self.sslEnabled: self.mgr.sslErrors.connect(self.handleSSLErrors) return reply def handleSSLErrors(self, reply, errors): for err in errors: self.logger.error('SSL errors:' + err.errorString()) def handleAuthenticationRequired(self, reply, authenticator): if self.user == '' and self.password == '': self.logger.warning( 'authentication required and no user/password set') authenticator.setUser(self.user) authenticator.setPassword(self.password) def configureCerts(self): ## import the private client key privateKeyFile = QFile(self.clientKeyFile) privateKeyFile.open(QIODevice.ReadOnly) privateKey = QSslKey(privateKeyFile, QSsl.Rsa) if privateKey.isNull(): self.logger.warning('SSL private key is null') else: self.sslConfig.setPrivateKey(privateKey) ## import the client certificate certFile = QFile(self.clientCertFile) certFile.open(QIODevice.ReadOnly) cert = QSslCertificate(certFile) self.sslConfig.setLocalCertificate(cert) ## import the self-signed CA certificate caCertFile = QFile(self.caCertFile) caCertFile.open(QIODevice.ReadOnly) caCert = QSslCertificate(caCertFile) ## add self-signed CA cert to the other CA certs caCertList = self.sslConfig.caCertificates() caCertList.append(caCert) self.sslConfig.setCaCertificates(caCertList)