Exemplo n.º 1
0
class Client():
    def __init__(self):
        self.publicKey = ''
        self.privateKey = ''
        self.hashMethod = 'sha1'
        self.pongTimer = 0
        self.pingTimer = 0
        self.supportedMethods = 0
        self.tellduscore = TelldusCore()
        self.serverList = ServerList()

        self.configPath = os.environ['HOME'] + '/.config/Telldus'
        self.configFilename = 'TelldusLive.conf'
        self.config = ConfigObj(self.configPath + '/' + self.configFilename)
        self.connect(self.serverList.popServer())

    def __del__(self):
        try:
            os.makedirs(self.configPath)
        except:
            pass
        self.config.write()

    def connect(self, server):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket = ssl.wrap_socket(
            s,
            ssl_version=ssl.PROTOCOL_TLSv1,
            ca_certs="/etc/ssl/certs/ca-certificates.crt",
            cert_reqs=ssl.CERT_REQUIRED)
        self.socket.settimeout(5)
        self.socket.connect((server['address'], int(server['port'])))

        uuid = ''
        try:
            uuid = self.config['uuid']
        except:
            pass

        msg = LiveMessage('Register')
        msg.append({
            'key': self.publicKey,
            'uuid': uuid,
            'hash': self.hashMethod
        })
        msg.append({
            'protocol': 2,
            'version': '1',
            'os': 'linux',
            'os-version': 'unknown'
        })

        self.socket.write(self.signedMessage(msg))
        self.pongTimer = time.time()
        self.pingTimer = time.time()
        while (1):
            try:
                resp = self.socket.read(1024)
            except ssl.SSLError:
                # Timeout, try again after some maintenance
                if (time.time() - self.pongTimer >= 360):  # No pong received
                    print("No pong received, disconnecting")
                    break
                if (time.time() - self.pingTimer >= 120):
                    # Time to ping
                    msg = LiveMessage("Ping")
                    self.socket.write(self.signedMessage(msg))
                    self.pingTimer = time.time()

                continue

            if (resp == ''):
                print("no response")
                break

            envelope = LiveMessage.fromByteArray(resp)
            if (not envelope.verifySignature(self.hashMethod,
                                             self.privateKey)):
                print "Signature failed"
                continue

            self.pongTimer = time.time()
            self.handleMessage(
                LiveMessage.fromByteArray(envelope.argument(0).stringVal))

    def handleCommand(self, args):
        if (args['action'].stringVal == 'turnon'):
            self.tellduscore.turnon(args['id'].intVal)
        elif (args['action'].stringVal == 'turnoff'):
            self.tellduscore.turnoff(args['id'].intVal)
        else:
            return

        if ('ACK' in args):
            #Respond to ack
            msg = LiveMessage("ACK")
            msg.append(args['ACK'].intVal)
            self.socket.write(self.signedMessage(msg))

    def handleMessage(self, message):
        if (message.name() == "notregistered"):
            params = message.argument(0).dictVal
            self.config['uuid'] = params['uuid'].stringVal
            self.config['activationUrl'] = params['url'].stringVal
            print "This client isn't activated, please activate it using this url:\n%s" % params[
                'url'].stringVal
            return

        if (message.name() == "registered"):
            params = message.argument(0).dictVal
            self.supportedMethods = params['supportedMethods'].intVal
            self.tellduscore.setSupportedMethods(self.supportedMethods)
            self.sendDevicesReport()
            return

        if (message.name() == "command"):
            self.handleCommand(message.argument(0).dictVal)
            return

        if (message.name() == "pong"):
            return

        print "Did not understand: %s" % message.toByteArray()

    def sendDevicesReport(self):
        msg = LiveMessage("DevicesReport")
        msg.append(self.tellduscore.getList())
        self.socket.write(self.signedMessage(msg))

    def signedMessage(self, message):
        return message.toSignedMessage(self.hashMethod, self.privateKey)
Exemplo n.º 2
0
class TelldusLive(Plugin):
    observers = ObserverCollection(ITelldusLiveObserver)

    def __init__(self):
        print("Telldus Live! loading")
        self.email = ''
        self.supportedMethods = 0
        self.connected = False
        self.registered = False
        self.serverList = ServerList()
        Application().registerShutdown(self.stop)
        self.s = Settings('tellduslive.config')
        self.uuid = self.s['uuid']
        self.conn = ServerConnection()
        self.pingTimer = 0
        self.thread = threading.Thread(target=self.run)
        if self.conn.publicKey != '':
            # Only connect if the keys has been set.
            self.thread.start()

    @mainthread
    def handleMessage(self, message):
        if (message.name() == "notregistered"):
            self.email = ''
            self.connected = True
            self.registered = False
            params = message.argument(0).dictVal
            self.s['uuid'] = params['uuid'].stringVal
            print(
                "This client isn't activated, please activate it using this url:\n%s"
                % params['url'].stringVal)
            self.observers.liveConnected()
            return

        if (message.name() == "registered"):
            self.connected = True
            self.registered = True
            data = message.argument(0).toNative()
            if 'email' in data:
                self.email = data['email']
            self.observers.liveRegistered(data)
            return

        if (message.name() == "command"):
            # Extract ACK and handle it
            args = message.argument(0).dictVal
            if 'ACK' in args:
                msg = LiveMessage("ACK")
                msg.append(args['ACK'].intVal)
                self.send(msg)

        if (message.name() == "pong"):
            return

        if (message.name() == "disconnect"):
            self.conn.close()
            self.__disconnected()
            return

        handled = False
        for o in self.observers:
            for f in getattr(o, '_telldusLiveHandlers',
                             {}).get(message.name(), []):
                f(o, message)
                handled = True
        if not handled:
            print "Did not understand: %s" % message.toByteArray()

    def isConnected(self):
        return self.connected

    def isRegistered(self):
        return self.registered

    def run(self):
        self.running = True

        wait = 0
        pongTimer, self.pingTimer = (0, 0)
        while self.running:
            if wait > 0:
                wait = wait - 1
                time.sleep(1)
                continue
            state = self.conn.process()
            if state == ServerConnection.CLOSED:
                server = self.serverList.popServer()
                if not server:
                    wait = random.randint(60, 300)
                    print("No servers found, retry in %i seconds" % wait)
                    continue
                if not self.conn.connect(server['address'], int(
                        server['port'])):
                    wait = random.randint(60, 300)
                    print("Could not connect, retry in %i seconds" % wait)

            elif state == ServerConnection.CONNECTED:
                pongTimer, self.pingTimer = (time.time(), time.time())
                self.__sendRegisterMessage()

            elif state == ServerConnection.MSG_RECEIVED:
                msg = self.conn.popMessage()
                if msg is None:
                    continue
                pongTimer = time.time()
                self.handleMessage(msg)

            elif state == ServerConnection.DISCONNECTED:
                wait = random.randint(10, 50)
                print("Disconnected, reconnect in %i seconds" % wait)
                self.__disconnected()

            else:
                if (time.time() - pongTimer >= 360):  # No pong received
                    self.conn.close()
                    wait = random.randint(10, 50)
                    print(
                        "No pong received, disconnecting. Reconnect in %i seconds"
                        % wait)
                    self.__disconnected()
                elif (time.time() - self.pingTimer >= 120):
                    # Time to ping
                    self.conn.send(LiveMessage("Ping"))
                    self.pingTimer = time.time()

    def stop(self):
        self.running = False

    def send(self, message):
        self.conn.send(message)
        self.pingTimer = time.time()

    def pushToWeb(self, module, action, data):
        msg = LiveMessage("sendToWeb")
        msg.append(module)
        msg.append(action)
        msg.append(data)
        self.send(msg)

    def __disconnected(self):
        self.email = ''
        self.connected = False
        self.registered = False

        def sendNotification():
            self.observers.liveDisconnected()

        # Syncronize signal with main thread
        Application().queue(sendNotification)

    @staticmethod
    def handler(message):
        def call(fn):
            import sys
            frame = sys._getframe(1)
            frame.f_locals.setdefault('_telldusLiveHandlers',
                                      {}).setdefault(message, []).append(fn)
            return fn

        return call

    def __sendRegisterMessage(self):
        print("Send register")
        msg = LiveMessage('Register')
        msg.append({
            'key': self.conn.publicKey,
            'mac': TelldusLive.getMacAddr(Board.networkInterface()),
            'secret': Board.secret(),
            'hash': 'sha1'
        })
        msg.append({
            'protocol': 2,
            'version': Board.firmwareVersion(),
            'os': 'linux',
            'os-version': 'telldus'
        })
        self.conn.send(msg)

    @staticmethod
    def getMacAddr(ifname):
        addrs = netifaces.ifaddresses(ifname)
        try:
            mac = addrs[netifaces.AF_LINK][0]['addr']
        except IndexError, KeyError:
            return ''
        return mac.upper().replace(':', '')
Exemplo n.º 3
0
class Client():
	def __init__(self):
		self.publicKey = ''
		self.privateKey = ''
		self.hashMethod = 'sha1'
		self.pongTimer = 0
		self.pingTimer = 0
		self.supportedMethods = 0
		self.tellduscore = TelldusCore()
		self.serverList = ServerList()

		self.configPath = os.environ['HOME'] + '/.config/Telldus'
		self.configFilename = 'TelldusLive.conf'
		self.config = ConfigObj(self.configPath + '/' + self.configFilename)
		self.connect(self.serverList.popServer())

	def __del__(self):
		try:
			os.makedirs(self.configPath)
		except:
			pass
		self.config.write()

	def connect(self, server):
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.socket = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ca_certs="/etc/ssl/certs/ca-certificates.crt",cert_reqs=ssl.CERT_REQUIRED)
		self.socket.settimeout(5)
		self.socket.connect((server['address'], int(server['port'])))

		uuid = ''
		try:
			uuid = self.config['uuid']
		except:
			pass

		msg = LiveMessage('Register')
		msg.append({
			'key': self.publicKey,
			'uuid': uuid,
			'hash': self.hashMethod
		})
		msg.append({
			'protocol': 2,
			'version': '1',
			'os': 'linux',
			'os-version': 'unknown'
		})

		self.socket.write(self.signedMessage(msg))
		self.pongTimer = time.time()
		self.pingTimer = time.time()
		while(1):
			try:
				resp = self.socket.read(1024)
			except ssl.SSLError:
				# Timeout, try again after some maintenance
				if (time.time() - self.pongTimer >= 360):  # No pong received
					print("No pong received, disconnecting")
					break
				if (time.time() - self.pingTimer >= 120):
					# Time to ping
					msg = LiveMessage("Ping")
					self.socket.write(self.signedMessage(msg))
					self.pingTimer = time.time()

				continue

			if (resp == ''):
				print("no response")
				break

			envelope = LiveMessage.fromByteArray(resp)
			if (not envelope.verifySignature(self.hashMethod, self.privateKey)):
				print "Signature failed"
				continue

			self.pongTimer = time.time()
			self.handleMessage(LiveMessage.fromByteArray(envelope.argument(0).stringVal))

	def handleCommand(self, args):
		if (args['action'].stringVal == 'turnon'):
			self.tellduscore.turnon(args['id'].intVal)
		elif (args['action'].stringVal == 'turnoff'):
			self.tellduscore.turnoff(args['id'].intVal)
		else:
			return

		if ('ACK' in args):
			#Respond to ack
			msg = LiveMessage("ACK")
			msg.append(args['ACK'].intVal)
			self.socket.write(self.signedMessage(msg))

	def handleMessage(self, message):
		if (message.name() == "notregistered"):
			params = message.argument(0).dictVal
			self.config['uuid'] = params['uuid'].stringVal
			self.config['activationUrl'] = params['url'].stringVal
			print "This client isn't activated, please activate it using this url:\n%s" % params['url'].stringVal
			return

		if (message.name() == "registered"):
			params = message.argument(0).dictVal
			self.supportedMethods = params['supportedMethods'].intVal
			self.tellduscore.setSupportedMethods(self.supportedMethods)
			self.sendDevicesReport()
			return

		if (message.name() == "command"):
			self.handleCommand(message.argument(0).dictVal)
			return

		if (message.name() == "pong"):
			return

		print "Did not understand: %s" % message.toByteArray()


	def sendDevicesReport(self):
		msg = LiveMessage("DevicesReport")
		msg.append(self.tellduscore.getList())
		self.socket.write(self.signedMessage(msg))

	def signedMessage(self, message):
		return message.toSignedMessage(self.hashMethod, self.privateKey)