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)
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(':', '')
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)