diff --git a/read_info.py b/read_info.py index f1bc5f5..756063f 100644 --- a/read_info.py +++ b/read_info.py @@ -603,19 +603,49 @@ class DevInfo(): print("") return self.env.fw - def download_syslog(self, timeout = 4): - self.syslog = [] - if self.gw is not None: + +class SysLog(): + gw = None # Gateway() + verbose = 1 + timeout = 10 + files = [] + mtdlist = [] + bdata = None # EnvBuffer() + + def __init__(self, gw, timeout = 10, verbose = 1, infolevel = 1): + self.gw = gateway.Gateway() if gw is None else gw + self.verbose = verbose + self.timeout = timeout + os.makedirs('outdir', exist_ok = True) + os.makedirs('tmp', exist_ok = True) + if infolevel > 0: + self.update(infolevel) + + def update(self, infolevel): + if infolevel >= 1: + self.download_syslog() + if infolevel >= 2: + self.parse_mtdlist() + if infolevel >= 3: + self.parse_bdata() + + def download_syslog(self, timeout = None): + timeout = timeout if timeout is not None else self.timeout + self.files = [] + if not self.gw: + gw = gateway.Gateway() + gw.web_login() + else: gw = self.gw if gw.status < 1: gw.detect_device() - else: - gw = gateway.Gateway(timeout = timeout) + if not gw.stok: + gw.web_login() if gw.status < 1: die("Xiaomi Mi Wi-Fi device not found (IP: {})".format(gw.ip_addr)) - stok = gw.web_login() - print("Start generating syslog...") - r2 = requests.get(gw.apiurl + "misystem/sys_log") + if self.verbose > 0: + print("Start generating syslog...") + r2 = requests.get(gw.apiurl + "misystem/sys_log", timeout = self.timeout) if r2.text.find('"code":0') < 0: die("SysLog not generated!") try: @@ -623,31 +653,89 @@ class DevInfo(): path = path.group(1).strip() except Exception: die("SysLog not generated! (2)") - #fn_local = 'syslog.tar.gz' url = "http://" + path - print('Downloading SysLog from file "{}" ...'.format(url)) + if self.verbose > 0: + print('Downloading SysLog from file "{}" ...'.format(url)) zip = b'' - with requests.get(url, stream=True) as r3: + with requests.get(url, stream=True, timeout = self.timeout) as r3: r3.raise_for_status() for chunk in r3.iter_content(chunk_size=8192): zip += chunk - file = io.BytesIO(zip) - tar = tarfile.open(fileobj = file, mode='r:gz') + fn_local = 'outdir/syslog.tar.gz' + with open(fn_local, "wb") as file: + file.write(zip) + if os.path.exists("syslog_test.tar.gz"): # TEST + fn_local = "syslog_test.tar.gz" + tar = tarfile.open(fn_local, mode='r:gz') for member in tar.getmembers(): if not member.isfile() or not member.name: continue - if member.name.find('usr/log/') >= 0: # skip syslog files + if member.name.find('usr/log/') >= 0: # skip raw syslog files continue - file = types.SimpleNamespace() - file.name = member.name - file.size = member.size - file.data = tar.extractfile(member).read() - self.syslog.append(file) - #print('name = "{}", size = {} ({})'.format(file.name, file.size, len(file.data))) - #if len(file.data) < 200: - # print(file.data) - tar.close() - return self.syslog + item = types.SimpleNamespace() + item.name = member.name + item.size = member.size + item.data = tar.extractfile(member).read() + self.files.append(item) + if self.verbose >= 2: + print('name = "{}", size = {} ({})'.format(item.name, item.size, len(item.data))) + if len(item.data) < 200: + print(item.data) + tar.close() + return self.files + + def get_file_by_name(self, filename, fatal_error = False): + if self.files: + for i, item in enumerate(self.files): + if os.path.basename(item.name) == filename: + return item + if fatal_error: + die('File "{}" not found in syslog!'.format(filename)) + return None + + def parse_mtdlist(self): + self.mtdlist = [] + file = self.get_file_by_name('xiaoqiang.log', fatal_error = True) + txt = file.data.decode('ascii') + x = txt.find("\nMTD table:\n") + if x <= 0: + die('MTD table not found into syslog!') + mtdtbl = re.findall(r'mtd([0-9]+): ([0-9a-fA-F]+) ([0-9a-fA-F]+) "(.*?)"', txt) + if len(mtdtbl) <= 0: + return [] + mtdlist = [] + if self.verbose: + print("SysLog MTD table:") + for i, mtd in enumerate(mtdtbl): + item = types.SimpleNamespace() + item.id = int(mtd[0]) + item.size = int(mtd[1], 16) + item.name = mtd[3] + mtdlist.append(item) + if self.verbose: + print(' %2d > size: 0x%08X name: "%s"' % (item.id, item.size, item.name)) + self.mtdlist = mtdlist + return mtdlist + + def get_mtd_by_name(self, name): + if self.mtdlist: + name = name.lower() + for i, mtd in enumerate(self.mtdlist): + if mtd.name.lower().endswith(name): + return mtd + return None + + def parse_bdata(self): + self.bdata = None + file = self.get_file_by_name('bdata.txt', fatal_error = True) + env = EnvBuffer(file.data.decode('ascii'), '\n') + if self.verbose >= 2: + print('SysLog BData List:') + for i, (k, v) in enumerate(env.var.items()): + v = '' if (v is None) else ('=' + v) + print(" " + k + v) + self.bdata = env + return env if __name__ == "__main__":