Exemplo n.º 1
0
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
Exemplo n.º 2
0
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)