|
|
|
@ -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__":
|
|
|
|
|