def device_program(self, devname, address, filename): if self.connected == False: return False if devname not in self.subscribed: print "error: device {0} not subscribed".format(devname) return False if address.startswith('0x') == False: print "error: wrong address input {0}, address should start with 0x".format(address) return False try: expandname = os.path.expanduser(filename) except: print "{0} does not exist".format(filename) return False if os.path.exists(expandname) == False: print "{0} does not exist".format(filename) return False if self.send_file_to_client(devname, expandname) == False: return False filehash = TBframe.hash_of_file(expandname) content = self.subscribed[devname] + ',' + address + ',' + filehash data = TBframe.construct(TBframe.DEVICE_PROGRAM, content); self.send_data(data) self.wait_cmd_excute_done(270) if self.cmd_excute_state == "done": ret = True else: ret = False self.cmd_excute_state = 'idle' return ret
def send_file_to_someone(self, dst, filename): if os.path.exists(filename) == False: print "{0} does not exist\n".format(filename) return False print "sending {0} to {1} ...".format(filename, dst['addr']), file = open(filename, 'r') content = filename.split('/')[-1] data = TBframe.construct(TBframe.FILE_BEGIN, content) try: dst['socket'].send(data) except: print "failed" return False content = file.read(1024) while (content): data = TBframe.construct(TBframe.FILE_DATA, content) try: dst['socket'].send(data) except: print "failed" return False content = file.read(1024) file.close() content = filename.split('/')[-1] data = TBframe.construct(TBframe.FILE_END, content) try: dst['socket'].send(data) except: print "failed" return False print "succeed" return True
def log_on_off(self, args): if len(args) < 2: self.cmdrun_status_display( "Usage error, usage: log on/off devices") return False if args[0] == "on": type = TBframe.LOG_SUB elif args[0] == "off": type = TBframe.LOG_UNSUB else: self.cmdrun_status_display( "Usage error, usage: log on/off devices") return False for dev in args[1:]: indexes = self.parse_device_index(dev) if not indexes: self.cmdrun_status_display( 'invalid device index {0}'.format(dev)) continue for index in indexes: dev_str = self.get_devstr_by_index(index) if type == TBframe.LOG_SUB and dev_str not in self.log_subscribed: data = TBframe.construct(type, dev_str) self.send_data(data) self.log_subscribed.append(dev_str) elif type == TBframe.LOG_UNSUB and dev_str in self.log_subscribed: data = TBframe.construct(type, dev_str) self.send_data(data) self.log_subscribed.remove(dev_str)
def server_interaction(self): msg = '' while self.keep_running: try: new_msg = self.service_socket.recv(MAX_MSG_LENTH) if new_msg == '': print 'connection lost' break msg += new_msg while msg != '': type, length, value, msg = TBframe.parse(msg) if type == TBframe.TYPE_NONE: break #print type, length if type == TBframe.ALL_DEV: new_list = {} clients = value.split(':') for c in clients: if c == '': continue devs = c.split(',') uuid = devs[0] devs = devs[1:] for d in devs: if d == '': continue [dev, using] = d.split('|') new_list[uuid + ',' + dev] = using old_list = list(self.device_list) for dev in list(new_list): if dev not in old_list: data = TBframe.construct( TBframe.STATUS_SUB, dev) self.service_socket.send(data) self.device_list[dev] = new_list[dev] for dev in list(self.device_list): if dev in list(new_list): continue self.device_list.pop(dev) if type == TBframe.DEVICE_STATUS: print value except: if DEBUG: raise break self.keep_running = False print 'server interaction thread exited'
def device_run_cmd(self, devname, args, expect_lines = 0, timeout=0.8, filters=[""]): if self.connected == False: return False if devname not in self.subscribed: return False if len(args) == 0: return False content = self.subscribed[devname] content += ':' + '|'.join(args) data = TBframe.construct(TBframe.DEVICE_CMD, content) with self.filter_lock: self.filter['devname'] = devname self.filter['cmdstr'] = ' '.join(args) self.filter['lines_exp'] = expect_lines self.filter['lines_num'] = 0 self.filter['filters'] = filters self.filter['response'] = [] retry = 3 while retry > 0: self.send_data(data) self.filter_event.clear() self.filter_event.wait(timeout) if self.filter['lines_num'] > 0: break; retry -= 1 response = self.filter['response'] with self.filter_lock: self.filter = {} return response
def heartbeat_func(self): heartbeat_timeout = time.time() + 10 while self.keep_running: time.sleep(0.05) if time.time() < heartbeat_timeout: continue self.send_data(TBframe.construct(TBframe.HEARTBEAT, '')) heartbeat_timeout += 10
def send_device_list_to_all(self): devs = self.construct_dev_list() data = TBframe.construct(TBframe.ALL_DEV, devs) for t in self.terminal_list: try: t['socket'].send(data) except: continue
def device_unsubscribe(self, devices): for devname in list(devices): if devname not in self.subscribed: continue data = TBframe.construct(TBframe.LOG_UNSUB, self.subscribed[devname]) self.send_data(data) self.subscribed_reverse.pop(self.subscribed[devname]) self.subscribed.pop(devname)
def send_device_list(self): device_list = [] for port in list(self.devices): if self.devices[port]['valid']: device_list.append(port) content = ':'.join(device_list) data = TBframe.construct(TBframe.CLIENT_DEV, content) try: self.service_socket.send(data) except: self.connected = False
def heartbeat_func(self): heartbeat_timeout = time.time() + 10 while self.keep_running: time.sleep(0.05) if time.time() < heartbeat_timeout: continue try: self.service_socket.send(TBframe.construct(TBframe.HEARTBEAT, '')) except: continue heartbeat_timeout += 10
def device_log_poll(self, port, exit_condition): log_time = time.time() log = '' if LOCALLOG: logfile = 'client/' + port.split('/')[-1] + '.log' flog = open(logfile, 'a+') while os.path.exists(port) and exit_condition.is_set() == False: if self.connected == False or self.devices[port]['slock'].locked(): time.sleep(0.01) continue newline = False while self.devices[port]['slock'].acquire(False) == True: try: c = self.devices[port]['serial'].read(1) except: c = '' finally: self.devices[port]['slock'].release() if c == '': break if log == '': log_time = time.time() log += c if c == '\n': newline = True break if newline == True and log != '': if self.poll_str in log: queue_safeput(self.devices[port]['plog_queue'], log) else: self.device_log_filter(port, log) if LOCALLOG: flog.write('{0:.3f}:'.format(log_time) + log) log = port + ':{0:.3f}:'.format(log_time) + log data = TBframe.construct(TBframe.DEVICE_LOG, log) log = '' try: self.service_socket.send(data) except: #self.connected = False continue if LOCALLOG: flog.close() print 'device {0} removed'.format(port) self.devices[port]['valid'] = False exit_condition.set() self.devices[port]['serial'].close() self.send_device_list() print 'device log poll thread for {0} exited'.format(port)
def heartbeat_func(self): heartbeat_timeout = time.time() + 10 while self.keep_running: time.sleep(0.05) if time.time() >= heartbeat_timeout: try: self.service_socket.send( TBframe.construct(TBframe.HEARTBEAT, '')) heartbeat_timeout += 10 except: continue print 'heart beat thread exited'
def device_program(self, devname, address, filepath): """ program device with a firmware file arguments: devname : the device to be programmed address : start address write the firware(in hex format), example: '0x13200' filepath: firmware file path, only bin file is supported right now return: Ture - succeed; False - failed """ if self.connected == False: return False if devname not in self.subscribed: print "error: device {0} not subscribed".format(devname) return False if address.startswith('0x') == False: print "error: wrong address input {0}, address should start with 0x".format( address) return False try: expandname = path.expanduser(filepath) except: print "{0} does not exist".format(filepath) return False if path.exists(expandname) == False: print "{0} does not exist".format(filepath) return False retry = 3 while retry: if self.send_file_to_client(devname, expandname) == False: retry -= 1 time.sleep(5) else: break if retry == 0: return False filehash = pkt.hash_of_file(expandname) content = self.subscribed[devname] + ',' + address + ',' + filehash self.send_packet(pkt.DEVICE_PROGRAM, content) elapsed_time = time.time() response = self.wait_cmd_response(pkt.DEVICE_PROGRAM, 270) if response == "success": ret = True else: ret = False elapsed_time = time.time() - elapsed_time print "Programming device {0} finished in {1:0.1f}S, result:{2}".format( devname, elapsed_time, ret == True and 'succeed' or 'failed') return ret
def packet_send_thread(self): heartbeat_timeout = time.time() + 10 while self.keep_running: try: [type, content] = self.output_queue.get(block=True, timeout=0.1) except Queue.Empty: type = None pass if self.service_socket == None: continue if type == None: if time.time() < heartbeat_timeout: continue heartbeat_timeout += 10 data = pkt.construct(pkt.HEARTBEAT, '') else: data = pkt.construct(type, content) try: self.service_socket.send(data) except: self.connected = False continue
def device_control(self, devname, operation): operations = {"start":TBframe.DEVICE_START, "stop":TBframe.DEVICE_STOP, "reset":TBframe.DEVICE_RESET} if self.connected == False: return False if devname not in self.subscribed: return False if operation not in list(operations): return False content = self.subscribed[devname] data = TBframe.construct(operations[operation], content) self.send_data(data) return True
def device_erase(self, devname): if self.connected == False: return False if devname not in self.subscribed: print "error: device {0} not subscribed".format(devname) return False content = self.subscribed[devname] data = TBframe.construct(TBframe.DEVICE_ERASE, content); self.send_data(data) self.wait_cmd_excute_done(10) if self.cmd_excute_state == "done": ret = True else: ret = False self.cmd_excute_state = 'idle' return ret
def device_subscribe(self, devices): if self.connected == False: return False for devname in list(devices): devstr = self.get_devstr_by_partialstr(devices[devname]) if devstr == "": self.subscribed = {} self.subscribed_reverse = {} return False else: self.subscribed[devname] = devstr; self.subscribed_reverse[devstr] = devname for devname in devices: data = TBframe.construct(TBframe.LOG_SUB, self.subscribed[devname]) self.send_data(data) return True
def device_allocate(self, type, number, timeout, purpose='general'): if self.connected == False: return [] content = ','.join([type, str(number), purpose]) data = TBframe.construct(TBframe.DEVICE_ALLOC, content) timeout += time.time() while time.time() < timeout: self.send_data(data) self.wait_cmd_excute_done(0.8) if self.cmd_excute_return == None or self.cmd_excute_return == []: time.sleep(8) continue if len(self.cmd_excute_return) != number: print "error: allocated number does not equal requested" break if time.time() > timeout: self.cmd_excute_return = [] return self.cmd_excute_return
def control_devices(self, operate, args): if len(args) < 1: self.cmdrun_status_display("Usage error, usage: reset devices") return False operations = { "start": TBframe.DEVICE_START, "stop": TBframe.DEVICE_STOP, "reset": TBframe.DEVICE_RESET } operate = operations[operate] succeed = [] failed = [] for dev in args: indexes = self.parse_device_index(dev) if indexes == []: self.cmdrun_status_display( 'invalid device index {0}'.format(dev)) return False for index in indexes: dev_str = self.get_devstr_by_index(index) data = TBframe.construct(operate, dev_str) self.send_data(data) self.wait_cmd_excute_done(1.5) if self.cmd_excute_state == "done": succeed.append(index) else: failed.append(index) self.cmd_excute_state = 'idle' if dev_str not in self.using_list: self.using_list.append(dev_str) status_str = '' if succeed != []: status_str += "succeed: {0}".format(succeed) if failed != []: if status_str != '': status_str += ', ' status_str += "failed: {0}".format(failed) self.cmdrun_status_display(status_str)
def erase_devices(self, args): devs = args if devs == []: self.cmdrun_status_display( "Usage error: please specify devices you want to programg") return False succeed = [] failed = [] for dev in devs: indexes = self.parse_device_index(dev) if indexes == []: self.cmdrun_status_display( 'invalid device index {0}'.format(dev)) continue for index in indexes: status_str = 'erasing {0}.{1}...'.format( index, self.get_devstr_by_index(index)) self.cmdrun_status_display(status_str) dev_str = self.get_devstr_by_index(index) data = TBframe.construct(TBframe.DEVICE_ERASE, dev_str) self.send_data(data) self.wait_cmd_excute_done(10) status_str += self.cmd_excute_state self.cmdrun_status_display(status_str) if self.cmd_excute_state == "done": succeed.append(index) else: failed.append(index) self.cmd_excute_state = 'idle' if dev_str not in self.using_list: self.using_list.append(dev_str) status_str = '' if succeed != []: status_str += "succeed: {0}".format(succeed) if failed != []: if status_str != '': status_str += ', ' status_str += "failed: {0}".format(failed) self.cmdrun_status_display(status_str)
def log_download(self, args): if len(args) < 1: self.cmdrun_status_display( "Usage error, usage: logdownload device0 [device1 ... deviceN]" ) return False succeed = [] failed = [] for dev in args: indexes = self.parse_device_index(dev) if indexes == []: self.cmdrun_status_display( 'invalid device index {0}'.format(dev)) return False for index in indexes: device = self.get_devstr_by_index(index).split(',') status_str = 'downloading log file for {0}.{1}:{2}...'.format( index, device[0], device[1].replace('/dev/', '')) self.cmdrun_status_display(status_str) content = ','.join(device) data = TBframe.construct(TBframe.LOG_DOWNLOAD, content) self.send_data(data) self.wait_cmd_excute_done(480) if self.cmd_excute_state == "done": succeed.append(index) else: failed.append(index) self.cmd_excute_state = 'idle' status_str = '' if succeed != []: status_str += "succeed: {0}".format(succeed) if failed != []: if status_str != '': status_str += ', ' status_str += "failed: {0}".format(failed) self.cmdrun_status_display(status_str) return (len(failed) == 0)
def client_serve_thread(self, conn, addr): file = {} msg = '' client = None self.conn_timeout[conn] = { 'type': 'client', 'addr': addr, 'timeout': time.time() + 30 } while self.keep_running: try: new_msg = conn.recv(MAX_MSG_LENTH) if new_msg == '': break msg += new_msg while msg != '': type, length, value, msg = TBframe.parse(msg) if type == TBframe.TYPE_NONE: break self.conn_timeout[conn]['timeout'] = time.time() + 30 if client == None: if type != TBframe.CLIENT_UUID: data = TBframe.construct( TBframe.CLIENT_UUID, 'give me your uuid first') conn.send(data) time.sleep(0.1) continue for c in self.client_list: if c['uuid'] != value: continue client = c break if client == None: client = { 'uuid': value, 'valid': True, 'socket': conn, 'addr': addr, 'devices': {} } self.client_list.append(client) print "new client {0} connected @ {1}".format( value, addr) else: client['socket'] = conn client['addr'] = addr client['valid'] = True print "client {0} re-connected @ {1}".format( value, addr) continue if type == TBframe.CLIENT_DEV: new_devices = value.split(':') for port in new_devices: if port == "": continue if port in client['devices'] and client['devices'][ port]['valid'] == True: continue if port not in client['devices']: print "new device {0} added to client {1}".format( port, client['uuid']) client['devices'][port] = { 'lock': threading.Lock(), 'valid': True, 'using': 0, 'status': '{}', 'log_subscribe': [], 'status_subscribe': [] } else: print "device {0} re-added to client {1}".format( port, client['uuid']) client['devices'][port]['status'] = '{}' client['devices'][port]['valid'] = True for port in list(client['devices']): if port in new_devices: continue if client['devices'][port]['valid'] == False: continue client['devices'][port]['status'] = '{}' client['devices'][port]['valid'] = False print "device {0} removed from client {1}".format( port, client['uuid']) for port in list(file): if client['devices'][port]['valid'] == True: continue file[port]['handle'].close() file.pop(port) self.send_device_list_to_all() elif type == TBframe.DEVICE_LOG: port = value.split(':')[0] if port not in client['devices']: continue #forwad log to subscribed devices if client['devices'][port]['log_subscribe'] != [] and \ ('tag' not in client or client['tag'] not in value): log = client['uuid'] + ',' + value data = TBframe.construct(type, log) for s in client['devices'][port]['log_subscribe']: try: s.send(data) except: continue #save log to files try: logtime = value.split(':')[1] logstr = value[len(port) + 1 + len(logtime):] logtime = float(logtime) logtimestr = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(logtime)) logtimestr += ("{0:.3f}".format(logtime - int(logtime)))[1:] logstr = logtimestr + logstr logdatestr = time.strftime("%Y-%m-%d", time.localtime(logtime)) except: if DEBUG: traceback.print_exc() continue if (port not in file) or (file[port]['date'] != logdatestr): if port in file: file[port]['handle'].close() file.pop(port) log_dir = 'server/' + logdatestr if os.path.isdir(log_dir) == False: try: os.mkdir(log_dir) except: print "error: can not create directory {0}".format( log_dir) filename = log_dir + '/' + client[ 'uuid'] + '-' + port.split('/')[-1] + '.log' try: handle = open(filename, 'a+') file[port] = { 'handle': handle, 'date': logdatestr } except: print "error: can not open/create file ", filename if port in file and file[port]['date'] == logdatestr: file[port]['handle'].write(logstr) elif type == TBframe.DEVICE_STATUS: #print value port = value.split(':')[0] if port not in client['devices']: continue client['devices'][port]['status'] = value[len(port) + 1:] if client['devices'][port]['status_subscribe'] != []: log = client['uuid'] + ',' + port log += value[len(port):] data = TBframe.construct(type, log) for s in client['devices'][port][ 'status_subscribe']: try: s.send(data) except: continue elif type == TBframe.DEVICE_ERASE or type == TBframe.DEVICE_PROGRAM or \ type == TBframe.DEVICE_START or type == TBframe.DEVICE_STOP or \ type == TBframe.DEVICE_RESET or type == TBframe.DEVICE_CMD or \ type == TBframe.FILE_BEGIN or type == TBframe.FILE_DATA or \ type == TBframe.FILE_END: values = value.split(',') addr = (values[0], int(values[1])) terminal = None for t in self.terminal_list: if t['addr'] == addr: terminal = t if terminal != None: if values[2] != 'success' and values[2] != 'ok': data = TBframe.construct( TBframe.CMD_ERROR, ','.join(values[2:])) else: data = TBframe.construct( TBframe.CMD_DONE, ','.join(values[2:])) terminal['socket'].send(data) elif type == TBframe.CLIENT_TAG: client['tag'] = value print 'client {0} tag: {1}'.format( client['uuid'], repr(value)) except: if DEBUG: traceback.print_exc() break conn.close() self.conn_timeout.pop(conn) if client: for port in client['devices']: if client['devices'][port]['valid'] == False: continue client['devices'][port]['status'] = '{}' client['devices'][port]['valid'] = False print "device {0} removed from client {1}".format( port, client['uuid']) client['valid'] = False print "client {0} @ {1} disconnected".format(client['uuid'], addr) self.send_device_list_to_all() else: print "client @ {0} disconnected".format(addr)
def send_device_list_to_terminal(self, terminal): devs = self.construct_dev_list() data = TBframe.construct(TBframe.ALL_DEV, devs) terminal['socket'].send(data)
def client_func(self, server_ip, server_port): self.service_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: self.service_socket.connect((server_ip, server_port)) self.connected = True print 'connect to server {0}:{1} succeeded'.format( server_ip, server_port) except: print 'connect to server {0}:{1} failed'.format( server_ip, server_port) return if os.path.exists('client') == False: os.mkdir('client') if os.path.exists('client/.uuid') == True: try: file = open('client/.uuid', 'rb') self.uuid = json.load(file) file.close() except: print "read uuid from file failed" if not self.uuid: bytes = os.urandom(6) self.uuid = '' for byte in bytes: self.uuid += '{0:02x}'.format(ord(byte)) try: file = open('client/.uuid', 'w') file.write(json.dumps(self.uuid)) file.close() except: print "save uuid to file failed" signal.signal(signal.SIGINT, signal_handler) self.send_packet(TBframe.CLIENT_UUID, self.uuid) self.send_packet(TBframe.CLIENT_TAG, self.poll_str) thread.start_new_thread(self.device_monitor, ()) thread.start_new_thread(self.heartbeat_func, ()) file_received = {} file_receiving = {} msg = '' while True: try: new_msg = self.service_socket.recv(MAX_MSG_LENTH) if new_msg == '': raise ConnectionLost break msg += new_msg while msg != '': type, length, value, msg = TBframe.parse(msg) if type == TBframe.TYPE_NONE: break for hash in list(file_receiving): if time.time() > file_receiving[hash]['timeout']: file_receiving[hash]['handle'].close() try: os.remove(file_receiving[hash]['name']) except: pass file_receiving.pop(hash) if type == TBframe.FILE_BEGIN: split_value = value.split(':') terminal = split_value[0] hash = split_value[1] filename = split_value[2] if hash in file_received: if os.path.exists(file_received[hash]) == True: content = terminal + ',' + 'exist' self.send_packet(type, content) continue else: file_received.pop(hash) if hash in file_receiving: content = terminal + ',' + 'busy' self.send_packet(type, content) continue filename = 'client/' + filename filename += '-' + terminal.split(',')[0] filename += '@' + time.strftime('%Y-%m-%d-%H-%M') filehandle = open(filename, 'wb') timeout = time.time() + 5 file_receiving[hash] = { 'name': filename, 'seq': 0, 'handle': filehandle, 'timeout': timeout } content = terminal + ',' + 'ok' self.send_packet(type, content) if DEBUG: print 'start receiving {0} as {1}'.format( split_value[2], filename) elif type == TBframe.FILE_DATA: split_value = value.split(':') terminal = split_value[0] hash = split_value[1] seq = split_value[2] data = value[(len(terminal) + len(hash) + len(seq) + 3):] seq = int(seq) if hash not in file_receiving: content = terminal + ',' + 'noexist' self.send_packet(type, content) continue if file_receiving[hash][ 'seq'] != seq and file_receiving[hash][ 'seq'] != seq + 1: content = terminal + ',' + 'seqerror' self.send_packet(type, content) continue if file_receiving[hash]['seq'] == seq: file_receiving[hash]['handle'].write(data) file_receiving[hash]['seq'] += 1 file_receiving[hash]['timeout'] = time.time() + 5 content = terminal + ',' + 'ok' self.send_packet(type, content) elif type == TBframe.FILE_END: split_value = value.split(':') terminal = split_value[0] hash = split_value[1] if hash not in file_receiving: content = terminal + ',' + 'noexist' self.send_packet(type, content) continue file_receiving[hash]['handle'].close() localhash = TBframe.hash_of_file( file_receiving[hash]['name']) if localhash != hash: response = 'hasherror' else: response = 'ok' file_received[hash] = file_receiving[hash]['name'] if DEBUG: print 'finished receiving {0}, result:{1}'.format( file_receiving[hash]['name'], response) file_receiving.pop(hash) content = terminal + ',' + response self.send_packet(type, content) elif type == TBframe.DEVICE_ERASE: args = value.split(',') if len(args) != 3: continue term = args[0:2] port = args[2] if os.path.exists(port) and port in self.devices: if self.devices[port]['queue'].full() == False: self.devices[port]['queue'].put([type, term]) continue else: result = 'busy' print 'erase', port, 'failed, device busy' else: result = 'nonexist' print 'erase', port, 'failed, device nonexist' content = ','.join(term) + ',' + result self.send_packet(type, content) elif type == TBframe.DEVICE_PROGRAM: args = value.split(',') if len(args) != 5: continue term = args[0:2] port = args[2] address = args[3] hash = args[4] if hash not in file_received: content = ','.join(term) + ',' + 'error' self.send_packet(type, content) continue filename = file_received[hash] if os.path.exists(port) and port in self.devices: if self.devices[port]['queue'].full() == False: self.devices[port]['queue'].put( [type, term, address, filename]) continue else: result = 'busy' print 'program {0} to {1} @ {2} failed, device busy'.format( filename, port, address) else: result = 'error' print 'program {0} to {1} @ {2} failed, device nonexist'.format( filename, port, address) content = ','.join(term) + ',' + result self.send_packet(type, content) elif type == TBframe.DEVICE_RESET or type == TBframe.DEVICE_START or type == TBframe.DEVICE_STOP: operations = { TBframe.DEVICE_RESET: 'reset', TBframe.DEVICE_START: 'start', TBframe.DEVICE_STOP: 'stop' } args = value.split(',') if len(args) != 3: continue term = args[0:2] port = args[2] if os.path.exists(port) and port in self.devices: if self.devices[port]['queue'].full() == False: self.devices[port]['queue'].put([type, term]) continue else: result = 'busy' print operations[ type], port, 'failed, device busy' else: result = 'nonexist' print operations[ type], port, 'failed, device nonexist' content = ','.join(term) + ',' + result self.send_packet(type, content) elif type == TBframe.DEVICE_CMD: args = value.split(':')[0] arglen = len(args) + 1 args = args.split(',') term = args[0:2] port = args[2] cmd = value[arglen:].split('|') cmd = ' '.join(cmd) if os.path.exists(port) and port in self.devices and \ self.devices[port]['valid'] == True: if self.devices[port]['queue'].full() == False: self.devices[port]['queue'].put( [type, term, cmd]) continue else: result = 'busy' print "run command '{0}' at {1} failed, device busy".format( cmd, port) else: result = 'nonexist' print "run command '{0}' at {1} failed, device nonexist".format( cmd, port) content = ','.join(term) + ',' + result self.send_packet(type, content) elif type == TBframe.CLIENT_UUID: print 'server request UUID' self.send_packet(TBframe.CLIENT_UUID, self.uuid) self.send_packet(TBframe.CLIENT_TAG, self.poll_str) self.send_device_list() except ConnectionLost: self.connected = False print 'connection to server lost, try reconnecting...' self.service_socket.close() self.service_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) while True: try: self.service_socket.connect((server_ip, server_port)) time.sleep(0.1) self.connected = True self.send_packet(TBframe.CLIENT_UUID, self.uuid) self.send_packet(TBframe.CLIENT_TAG, self.poll_str) self.send_device_list() break except: try: time.sleep(1) except: self.service_socket.close() return print 'connection to server resumed' except KeyboardInterrupt: print "client exiting ..." self.keep_running = False time.sleep(0.3) break except: if DEBUG: traceback.print_exc() self.service_socket.close()
def terminal_serve_thread(self, conn, addr): terminal = {'socket': conn, 'addr': addr} self.terminal_list.append(terminal) using_list = [] msg = '' self.conn_timeout[conn] = { 'type': 'terminal', 'addr': addr, 'timeout': time.time() + 30 } self.send_device_list_to_terminal(terminal) while self.keep_running: try: new_msg = terminal['socket'].recv(MAX_MSG_LENTH) if new_msg == '': break msg += new_msg while msg != '': type, length, value, msg = TBframe.parse(msg) if type == TBframe.TYPE_NONE: break self.conn_timeout[conn]['timeout'] = time.time() + 30 if type == TBframe.FILE_BEGIN or type == TBframe.FILE_DATA or type == TBframe.FILE_END: dev_str = value.split(':')[0] uuid = dev_str.split(',')[0] target_data = value[len(dev_str):] client = self.get_client_by_uuid(uuid) if client == None: data = TBframe.construct(TBframe.CMD_ERROR, 'nonexist') terminal['socket'].send(data) continue content = terminal['addr'][0] + ',' + str( terminal['addr'][1]) content += target_data data = TBframe.construct(type, content) client['socket'].send(data) elif type == TBframe.DEVICE_ERASE or type == TBframe.DEVICE_PROGRAM or \ type == TBframe.DEVICE_START or type == TBframe.DEVICE_STOP or \ type == TBframe.DEVICE_RESET or type == TBframe.DEVICE_CMD: dev_str_split = value.split(':')[0].split(',')[0:2] if len(dev_str_split) != 2: data = TBframe.construct(TBframe.CMD_ERROR, 'argerror') terminal['socket'].send(data) continue [uuid, port] = dev_str_split client = self.get_client_by_uuid(uuid) if client == None: data = TBframe.construct(TBframe.CMD_ERROR, 'nonexist') terminal['socket'].send(data) continue content = terminal['addr'][0] content += ',' + str(terminal['addr'][1]) content += value[len(uuid):] data = TBframe.construct(type, content) client['socket'].send(data) self.increase_device_refer(client, port, using_list) elif type == TBframe.DEVICE_ALLOC: result = self.allocate_devices(value) content = ','.join(result) data = TBframe.construct(TBframe.DEVICE_ALLOC, content) terminal['socket'].send(data) elif type == TBframe.LOG_SUB or type == TBframe.LOG_UNSUB or \ type == TBframe.STATUS_SUB or type == TBframe.STATUS_UNSUB: dev_str_split = value.split(',') if len(dev_str_split) != 2: continue [uuid, port] = dev_str_split client = self.get_client_by_uuid(uuid) if client == None: continue if port not in list(client['devices']): continue if type == TBframe.LOG_SUB: if terminal['socket'] in client['devices'][port][ 'log_subscribe']: continue client['devices'][port]['log_subscribe'].append( terminal['socket']) print "terminal {0}:{1}".format( terminal['addr'][0], terminal['addr'][1]), print "subscribed log of device {0}:{1}".format( uuid, port) elif type == TBframe.LOG_UNSUB: if terminal['socket'] not in client['devices'][ port]['log_subscribe']: continue client['devices'][port]['log_subscribe'].remove( terminal['socket']) print "terminal {0}:{1}".format( terminal['addr'][0], terminal['addr'][1]), print "unsubscribed log of device {0}:{1}".format( uuid, port) elif type == TBframe.STATUS_SUB: if terminal['socket'] in client['devices'][port][ 'status_subscribe']: continue client['devices'][port]['status_subscribe'].append( terminal['socket']) print "terminal {0}:{1}".format( terminal['addr'][0], terminal['addr'][1]), print "subscribed status of device {0}:{1}".format( uuid, port) content = client['uuid'] + ',' + port content += ':' + client['devices'][port]['status'] data = TBframe.construct(TBframe.DEVICE_STATUS, content) terminal['socket'].send(data) elif type == TBframe.STATUS_UNSUB: if terminal['socket'] not in client['devices'][ port]['status_subscribe']: continue client['devices'][port]['status_subscribe'].remove( terminal['socket']) print "terminal {0}:{1}".format( terminal['addr'][0], terminal['addr'][1]), print "unsubscribed status of device {0}:{1}".format( uuid, port) elif type == TBframe.LOG_DOWNLOAD: dev_str_split = value.split(',') if len(dev_str_split) != 2: continue [uuid, port] = dev_str_split datestr = time.strftime('%Y-%m-%d') filename = 'server/' + datestr + '/' + uuid + '-' + port.split( '/')[-1] + '.log' client = self.get_client_by_uuid(uuid) if client == None or port not in list( client['devices']) or os.path.exists( filename) == False: data = TBframe.construct(TBframe.CMD_ERROR, 'fail') terminal['socket'].send(data) print "terminal {0}:{1}".format( terminal['addr'][0], terminal['addr'][1]), print "downloading log of device {0}:{1} ... failed".format( uuid, port) continue self.send_file_to_someone(terminal, filename) heartbeat_timeout = time.time() + 30 data = TBframe.construct(TBframe.CMD_DONE, 'success') terminal['socket'].send(data) print "terminal {0}:{1}".format( terminal['addr'][0], terminal['addr'][1]), print "downloading log of device {0}:{1} ... succeed".format( uuid, port) except: if DEBUG: traceback.print_exc() break for client in self.client_list: for port in list(client['devices']): if terminal['socket'] in client['devices'][port][ 'log_subscribe']: client['devices'][port]['log_subscribe'].remove( terminal['socket']) if terminal['socket'] in client['devices'][port][ 'status_subscribe']: client['devices'][port]['status_subscribe'].remove( terminal['socket']) for device in using_list: uuid = device[0] port = device[1] client = None for c in self.client_list: if c['uuid'] != uuid: continue client = c break if client != None and port in list(client['devices']): with client['devices'][port]['lock']: if client['devices'][port]['using'] > 0: client['devices'][port]['using'] -= 1 terminal['socket'].close() self.conn_timeout.pop(conn) print "terminal ", terminal['addr'], "disconnected" self.terminal_list.remove(terminal) self.send_device_list_to_all()
def device_cmd_process(self, port, exit_condition): poll_fail_num = 0 poll_queue = Queue.Queue(12) if self.devices[port]['attributes'] != {}: content = port + ':' + json.dumps(self.devices[port]['attributes'], sort_keys=True) data = TBframe.construct(TBframe.DEVICE_STATUS, content) self.service_socket.send(data) poll_timeout = time.time() + 5 + random.uniform( 0, self.poll_interval / 3) while os.path.exists(port) and exit_condition.is_set() == False: try: if time.time() >= poll_timeout: poll_timeout += self.poll_interval poll_queue.put(['devname', 1, 0.2]) poll_queue.put(['mac', 1, 0.2]) poll_queue.put(['version', 2, 0.2]) poll_queue.put(['uuid', 1, 0.2]) poll_queue.put(['umesh status', 11, 0.2]) poll_queue.put(['umesh extnetid', 1, 0.2]) poll_queue.put(['umesh nbrs', 33, 0.3]) block = True timeout = 0 try: args = None if self.devices[port]['queue'].empty( ) == True and poll_queue.empty() == True: args = self.devices[port]['queue'].get(block=True, timeout=0.1) elif self.devices[port]['queue'].empty() == False: args = self.devices[port]['queue'].get() except Queue.Empty: args = None continue except: if DEBUG: traceback.print_exc() args = None continue if args != None: type = args[0] term = args[1] if type == TBframe.DEVICE_ERASE: self.device_erase(port, term) elif type == TBframe.DEVICE_PROGRAM: address = args[2] filename = args[3] self.device_program(port, address, filename, term) elif type == TBframe.DEVICE_RESET or type == TBframe.DEVICE_START or type == TBframe.DEVICE_STOP: self.device_control(port, type, term) elif type == TBframe.DEVICE_CMD: cmd = args[2] self.device_run_cmd(port, cmd, term) else: print "error: unknown operation tyep {0}".format( repr(type)) args = None time.sleep(0.05) continue if poll_queue.empty() == True: continue [cmd, lines, timeout] = poll_queue.get() response = self.run_poll_command(port, cmd, lines, timeout) if cmd == 'devname': #poll device model if len(response) == lines and response[0].startswith( 'device name:'): poll_fail_num = 0 self.devices[port]['attributes']['model'] = response[ 0].split()[-1] else: poll_fail_num += 1 elif cmd == 'mac': #poll device mac if len(response) == 1 and response[0].startswith( 'MAC address:'): poll_fail_num = 0 macaddr = response[0].split()[-1] macaddr = macaddr.replace('-', '') + '0000' self.devices[port]['attributes']['macaddr'] = macaddr else: poll_fail_num += 1 elif cmd == 'version': #poll device version if len(response) == lines: poll_fail_num = 0 for line in response: if 'kernel version :' in line: self.devices[port]['attributes'][ 'kernel_version'] = line.replace( 'kernel version :AOS-', '') if 'app version :' in line: line = line.replace('app version :', '') line = line.replace('app-', '') line = line.replace('APP-', '') self.devices[port]['attributes'][ 'app_version'] = line else: poll_fail_num += 1 elif cmd == 'umesh status': #poll mesh status if len(response) == lines: poll_fail_num = 0 for line in response: if 'state\t' in line: self.devices[port]['attributes'][ 'state'] = line.replace('state\t', '') elif '\tnetid\t' in line: self.devices[port]['attributes'][ 'netid'] = line.replace('\tnetid\t', '') elif '\tsid\t' in line: self.devices[port]['attributes'][ 'sid'] = line.replace('\tsid\t', '') elif '\tnetsize\t' in line: self.devices[port]['attributes'][ 'netsize'] = line.replace( '\tnetsize\t', '') elif '\trouter\t' in line: self.devices[port]['attributes'][ 'router'] = line.replace('\trouter\t', '') elif '\tchannel\t' in line: self.devices[port]['attributes'][ 'channel'] = line.replace( '\tchannel\t', '') else: poll_fail_num += 1 elif cmd == 'umesh nbrs': #poll mesh nbrs if len(response) > 0 and 'num=' in response[-1]: poll_fail_num = 0 nbrs = {} for line in response: if '\t' not in line or ',' not in line: continue line = line.replace('\t', '') nbr_info = line.split(',') if len(nbr_info) < 10: continue nbrs[nbr_info[0]] = {'relation':nbr_info[1], \ 'netid':nbr_info[2], \ 'sid':nbr_info[3], \ 'link_cost':nbr_info[4], \ 'child_num':nbr_info[5], \ 'channel':nbr_info[6], \ 'reverse_rssi':nbr_info[7], \ 'forward_rssi':nbr_info[8], \ 'last_heard':nbr_info[9]} if len(nbr_info) > 10: nbrs[nbr_info[0]]['awake'] = nbr_info[10] self.devices[port]['attributes']['nbrs'] = nbrs else: poll_fail_num += 1 elif cmd == 'umesh extnetid': #poll mesh extnetid if len(response) == 1 and response[0].count(':') == 5: poll_fail_num += 1 self.devices[port]['attributes'][ 'extnetid'] = response[0] else: poll_fail_num += 1 elif cmd == 'uuid': #poll uuid if len(response) == 1 and 'uuid:' in response[0]: poll_fail_num = 0 self.devices[port]['attributes']['uuid'] = response[ 0].replace('uuid: ', '') else: poll_fail_num += 1 else: print "error: unrecognized poll cmd '{0}'".format(cmd) continue if poll_fail_num >= 7: if self.devices[port]['attributes']['status'] == 'active': print "device {0} become inactive".format(port) self.devices[port]['attributes']['status'] = 'inactive' else: if self.devices[port]['attributes'][ 'status'] == 'inactive': print "device {0} become active".format(port) self.devices[port]['attributes']['status'] = 'active' if poll_queue.empty() == False: continue content = port + ':' + json.dumps( self.devices[port]['attributes'], sort_keys=True) data = TBframe.construct(TBframe.DEVICE_STATUS, content) try: self.service_socket.send(data) except: self.connected = False continue except: if os.path.exists(port) == False: exit_condition.set() break if exit_condition.is_set() == True: break if DEBUG: traceback.print_exc() self.devices[port]['serial'].close() self.devices[port]['serial'].open() print 'devie command process thread for {0} exited'.format(port)
def send_file_to_client(self, devname, filename): #argument check if devname not in self.subscribed: print "{0} is not subscribed".format(devname) return False try: expandfilename = os.path.expanduser(filename) except: print "{0} does not exist".format(filename) return False if os.path.exists(expandfilename) == False: print "{0} does not exist".format(filename) return False filename = expandfilename filehash = TBframe.hash_of_file(filename) devstr = self.subscribed[devname] #send file begin content = devstr + ':' + filehash + ':' + filename.split('/')[-1] data = TBframe.construct(TBframe.FILE_BEGIN, content) retry = 4 while retry > 0: self.send_data(data) self.wait_cmd_excute_done(0.2) if self.cmd_excute_state == 'timeout': retry -= 1; continue if self.cmd_excute_return == 'busy': print "file transfer busy: wait..." time.sleep(5) continue elif self.cmd_excute_return == 'ok' or self.cmd_excute_return == 'exist': break else: print "file transfer error: unexpected response '{0}'".format(self.cmd_excute_return) return False if retry == 0: print 'file transfer error: retry timeout' return False if self.cmd_excute_return == 'exist': return True #send file data seq = 0 file = open(filename,'r') header = devstr + ':' + filehash + ':' + str(seq) + ':' content = file.read(1024) while(content): data = TBframe.construct(TBframe.FILE_DATA, header + content) retry = 4 while retry > 0: self.send_data(data) self.wait_cmd_excute_done(0.2) if self.cmd_excute_return == None: retry -= 1; continue elif self.cmd_excute_return != 'ok': file.close() return False break if retry == 0: file.close() return False seq += 1 header = devstr + ':' + filehash + ':' + str(seq) + ':' content = file.read(1024) file.close() #send file end content = devstr + ':' + filehash + ':' + filename.split('/')[-1] data = TBframe.construct(TBframe.FILE_END, content) retry = 4 while retry > 0: self.send_data(data) self.wait_cmd_excute_done(0.2) if self.cmd_excute_return == None: retry -= 1; continue elif self.cmd_excute_return != 'ok': return False break if retry == 0: return False return True
def send_file_to_client(self, devname, filepath): #argument check if devname not in self.subscribed: print "{0} is not subscribed".format(devname) return False try: expandfilepath = path.expanduser(filepath) except: print "{0} does not exist".format(filepath) return False if path.exists(expandfilepath) == False: print "{0} does not exist".format(filepath) return False filepath = expandfilepath filehash = pkt.hash_of_file(filepath) devstr = self.subscribed[devname] #send file begin content = devstr + ':' + filehash + ':' + path.basename(filepath) retry = 4 while retry > 0: self.send_packet(pkt.FILE_BEGIN, content) response = self.wait_cmd_response(pkt.FILE_BEGIN, 0.6) if response == None: #timeout retry -= 1 continue if response == 'busy': print "file transfer busy: wait..." time.sleep(5) continue elif response == 'ok' or response == 'exist': break else: print "file transfer error: unexpected response '{0}'".format( response) return False if retry == 0: print 'file transfer error: retry timeout' return False if response == 'exist': return True #send file data seq = 0 file = open(filepath, 'r') header = devstr + ':' + filehash + ':' + str(seq) + ':' content = file.read(1024) while (content): retry = 4 while retry > 0: self.send_packet(pkt.FILE_DATA, header + content) response = self.wait_cmd_response(pkt.FILE_DATA, 0.6) if response == None: #timeout retry -= 1 continue elif response != 'ok': print('send data fragement {0} failed, error: {1}'.format( header, response)) file.close() return False break if retry == 0: file.close() return False seq += 1 header = devstr + ':' + filehash + ':' + str(seq) + ':' content = file.read(1024) file.close() #send file end content = devstr + ':' + filehash + ':' + path.basename(filepath) retry = 4 while retry > 0: self.send_packet(pkt.FILE_END, content) response = self.wait_cmd_response(pkt.FILE_END, 0.6) if response == None: #timeout retry -= 1 continue elif response != 'ok': print('send file failed, error: {0}'.format(response)) return False break if retry == 0: return False return True
def server_interaction(self): msg = '' while self.keep_running: try: if self.connected == False: raise ConnectionLost new_msg = self.service_socket.recv(MAX_MSG_LENGTH) if new_msg == '': raise ConnectionLost break msg += new_msg while msg != '': type, length, value, msg = pkt.parse(msg) if type == pkt.TYPE_NONE: break #print type, length if type == pkt.ALL_DEV: new_list = {} clients = value.split(':') for c in clients: if c == '': continue devs = c.split(',') uuid = devs[0] devs = devs[1:] for d in devs: if d == '': continue [dev, using] = d.split('|') new_list[uuid + ',' + dev] = using for dev in list(new_list): self.device_list[dev] = new_list[dev] continue if type == pkt.DEVICE_LOG: dev = value.split(':')[0] logtime = value.split(':')[1] log = value[len(dev) + 1 + len(logtime) + 1:] try: logtime = float(logtime) logtimestr = time.strftime("%Y-%m-%d %H-%M-%S", time.localtime(logtime)) logtimestr += ("{0:.3f}".format(logtime - int(logtime)))[1:] except: continue if dev not in list(self.device_list): continue devname = self.get_devname_by_devstr(dev) if devname != "": self.response_filter(devname, log) if self.logfile != None: log = logtimestr + ":" + devname + ":" + log self.logfile.write(log) continue if type == pkt.RESPONSE: type = value.split(',')[0] value = value[len(type) + 1:] try: self.response_queue.put([type, value], False) except: pass continue except ConnectionLost: self.connected = False self.service_socket.close() print 'connection to server lost, try reconnecting...' while True: result = self.connect_to_server(self.server_ip, self.server_port) if result == 'success': break time.sleep(2) print 'connection to server resumed' random.seed() time.sleep(1.2 + random.random()) for devname in self.subscribed: self.send_packet(pkt.LOG_SUB, self.subscribed[devname]) self.send_packet(pkt.DEVICE_CMD, self.subscribed[devname] + ':help') except socket.error as e: if e.errno == errno.ECONNRESET: print 'Warning: connection closed by server' self.connected = False continue if DEBUG: traceback.print_exc() break except: if DEBUG: traceback.print_exc() break self.keep_running = False
def server_interaction(self): msg = '' while self.keep_running: try: new_msg = self.service_socket.recv(MAX_MSG_LENTH) if new_msg == '': raise ConnectionLost break msg += new_msg while msg != '': type, length, value, msg = TBframe.parse(msg) if type == TBframe.TYPE_NONE: break #print type, length if type == TBframe.ALL_DEV: new_list = {} clients = value.split(':') for c in clients: if c == '': continue devs = c.split(',') uuid = devs[0] devs = devs[1:] for d in devs: if d == '': continue [dev, using] = d.split('|') new_list[uuid + ',' + dev] = using for dev in list(new_list): self.device_list[dev] = new_list[dev] if type == TBframe.DEVICE_LOG: dev = value.split(':')[0] logtime = value.split(':')[1] log = value[len(dev) + 1 + len(logtime) + 1:] try: logtime = float(logtime) logtimestr = time.strftime("%Y-%m-%d %H-%M-%S", time.localtime(logtime)); logtimestr += ("{0:.3f}".format(logtime-int(logtime)))[1:] except: continue if dev not in list(self.device_list): continue devname = self.get_devname_by_devstr(dev) if devname != "": self.response_filter(devname, log) if self.logfile != None: log = devname + ":" + logtimestr + ":" + log self.logfile.write(log) if type == TBframe.CMD_DONE: self.cmd_excute_return = value self.cmd_excute_state = 'done' self.cmd_excute_event.set() if type == TBframe.CMD_ERROR: self.cmd_excute_return = value self.cmd_excute_state = 'error' self.cmd_excute_event.set() if type == TBframe.DEVICE_ALLOC: values = value.split(',') if len(values) != 2: continue result = values[0] allocated = values[1].split('|') if result != 'success': self.cmd_excute_return = [] continue self.cmd_excute_return = allocated self.cmd_excute_state = 'done' self.cmd_excute_event.set() except ConnectionLost: self.connected = False self.service_socket.close() print 'connection to server lost, try reconnecting...' while True: result = self.connect_to_server(self.server_ip, self.server_port) if result == 'success': break time.sleep(1) print 'connection to server resumed' random.seed() time.sleep(1.2 + random.random()) for devname in self.subscribed: data = TBframe.construct(TBframe.LOG_SUB, self.subscribed[devname]) self.send_data(data) data = TBframe.construct(TBframe.DEVICE_CMD, self.subscribed[devname] + ':help') self.send_data(data) except: if DEBUG: traceback.print_exc() raise break self.keep_running = False;