mirror of https://github.com/OpenIPC/python-dvr
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1143 lines
39 KiB
1143 lines
39 KiB
#!/usr/bin/env python3
|
|
|
|
import os, sys, struct, json
|
|
from locale import getdefaultlocale
|
|
from subprocess import check_output
|
|
from socket import *
|
|
import platform
|
|
from datetime import *
|
|
import hashlib, base64
|
|
from dvrip import DVRIPCam
|
|
|
|
try:
|
|
try:
|
|
from tkinter import *
|
|
except:
|
|
from Tkinter import *
|
|
from tkinter.filedialog import asksaveasfilename, askopenfilename
|
|
from tkinter.messagebox import showinfo, showerror
|
|
from tkinter.ttk import *
|
|
|
|
GUI_TK = True
|
|
except:
|
|
GUI_TK = False
|
|
|
|
devices = {}
|
|
log = "search.log"
|
|
icon = "R0lGODlhIAAgAPcAAAAAAAkFAgwKBwQBABQNBRAQDQQFERAOFA4QFBcWFSAaFCYgGAoUMhwiMSUlJCsrKyooJy8wLjUxLjkzKTY1Mzw7OzY3OEpFPwsaSRsuTRUsWD4+QCo8XQAOch0nYB05biItaj9ARjdHYiRMfEREQ0hIR0xMTEdKSVNOQ0xQT0NEUVFNUkhRXlVVVFdYWFxdXFtZVV9wXGZjXUtbb19fYFRda19gYFZhbF5wfWRkZGVna2xsa2hmaHFtamV0Ynp2aHNzc3x8fHh3coF9dYJ+eH2Fe3K1YoGBfgIgigwrmypajDtXhw9FpxFFpSdVpzlqvFNzj0FvnV9zkENnpUh8sgdcxh1Q2jt3zThi0SJy0Dl81Rhu/g50/xp9/x90/zB35TJv8DJ+/EZqzj2DvlGDrlqEuHqLpHeQp26SuhqN+yiC6imH/zSM/yqa/zeV/zik/1aIwlmP0mmayWSY122h3VWb6kyL/1yP8UGU/UiW/VWd/miW+Eqp/12k/1Co/1yq/2Gs/2qr/WKh/nGv/3er9mK3/3K0/3e4+4ODg4uLi4mHiY+Qj5WTjo+PkJSUlJycnKGem6ShnY2ZrKOjo6urrKqqpLi0prS0tLu8vMO+tb+/wJrE+bzf/sTExMfIx8zMzMjIxtrWyM/Q0NXU1NfY193d3djY1uDf4Mnj+931/OTk5Ozs7O/v8PLy8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAgACAAAAj+AAEIHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mgx4iVMnTyJInVKlclSpD550nRpUqKGmD59EjWqlMlVOFWdIgWq0iNNoBIhSujokidPn0aNKrmqVStWqjxRumTqyI5KOxI5OpiIkiakNG2yelqK5alKLSAJgbBBB6RIjArmCKLIkV1HjyZNpTTJFKgSQoI4cGBiBxBIR6QM6TGQxooWL3LwMBwkSJEcLUq8YATDAZAdMkKh+GGpAo0cL1wInJuokSNIeqdeCgLBAoVMR2CEMkHDzAcnTCzsCAKERwsXK3wYKYLIdd6pjh4guCGJw5IpT7R8CeNlCwsikx7+JTJ+PAZlRHXxOgqBAQMTLXj0AAKkJw+eJw6CXGqJyAWNyT8QgZ5rsD2igwYEOOEGH38EEoghgcQhQgJAxISJI/8ZNoQUijiX1yM7NIBAFm3wUcghh9yBhQcCFEBDJ6V8MskKhgERxBGMMILXI7AhsoAAGSgRBRlliLHHHlZgMAAJmLByCiUnfGajFEcgotVzjkhggAYjjBHFFISgkoodSDAwAyStqDIJAELs4CYQQxChVSRTQcJCFWmUyAcghmzCCRgdXCEHEU69VJiNdDmnV0s4rNHFGmzgkUcfhgiShAd0nNHDVAc9YIEFFWxAQgkVpKAGF1yw4UYdc6AhhQohJFiwQAIRPQCHFlRAccMJFCRAgAAVJXDBBAsQEEBHDwUEADs="
|
|
help = """
|
|
Usage: %s [-q] [-n] [Command];[Command];...
|
|
-q No output
|
|
-n No gui
|
|
Command Description
|
|
|
|
help This help
|
|
echo Just echo
|
|
log [filename] Set log file
|
|
logLevel [0..100] Set log verbosity
|
|
search [brand] Searching devices of [brand] or all
|
|
table Table of devices
|
|
json JSON String of devices
|
|
device [MAC] JSON String of [MAC]
|
|
config [MAC] [IP] [MASK] [GATE] [Pasword] - Configure searched divice
|
|
""" % os.path.basename(
|
|
sys.argv[0]
|
|
)
|
|
lang, charset = getdefaultlocale()
|
|
locale = {
|
|
"ru_RU": {
|
|
"Type help or ? to display help(q or quit to exit)": u"Введите help или ? для справки, для выхода q или quit",
|
|
"Name": u"Наименование",
|
|
"Vendor": u"Марка",
|
|
"IP Address": u"IP Адрес",
|
|
"Mask": "Маска сети",
|
|
"Gateway": "Шлюз",
|
|
"TCP Port": u"TCP Порт",
|
|
"HTTP Port": u"HTTP Порт",
|
|
"Port": u"Порт",
|
|
"MAC Address": u"МАК Адрес",
|
|
"SN": u"Серийный №",
|
|
"As on PC": u"Как на ПК",
|
|
"Password": u"Пароль",
|
|
"Apply": u"Применить",
|
|
"Search": u"Поиск",
|
|
"Reset": u"Сброс",
|
|
"Export": u"Экспорт",
|
|
"Flash": u"Прошивка",
|
|
"All files": u"Все файлы",
|
|
"Text files": u"Текстовые файлы",
|
|
"Searching %s, found %d devices": u"Поиск %s, нашли %d устройств",
|
|
"Found %d devices": u"Найденно %d устройств",
|
|
"All": "По всем",
|
|
"Error": "Ошибка",
|
|
},
|
|
}
|
|
|
|
|
|
def _(msg):
|
|
if lang in locale.keys():
|
|
if msg in locale[lang].keys():
|
|
return locale[lang][msg]
|
|
return msg
|
|
|
|
|
|
CODES = {
|
|
100: _("Success"),
|
|
101: _("Unknown error"),
|
|
102: _("Version not supported"),
|
|
103: _("Illegal request"),
|
|
104: _("User has already logged in"),
|
|
105: _("User is not logged in"),
|
|
106: _("Username or Password is incorrect"),
|
|
107: _("Insufficient permission"),
|
|
108: _("Timeout"),
|
|
109: _("Find failed, file not found"),
|
|
110: _("Find success, returned all files"),
|
|
111: _("Find success, returned part of files"),
|
|
112: _("User already exists"),
|
|
113: _("User does not exist"),
|
|
114: _("User group already exists"),
|
|
115: _("User group does not exist"),
|
|
116: _("Reserved"),
|
|
117: _("Message is malformed"),
|
|
118: _("No PTZ protocol is set"),
|
|
119: _("No query to file"),
|
|
120: _("Configured to be enabled"),
|
|
121: _("Digital channel is not enabled"),
|
|
150: _("Success, device restart required"),
|
|
202: _("User is not logged in"),
|
|
203: _("Incorrect password"),
|
|
204: _("User is illegal"),
|
|
205: _("User is locked"),
|
|
206: _("User is in the blacklist"),
|
|
207: _("User already logged in"),
|
|
208: _("Invalid input"),
|
|
209: _("User already exists"),
|
|
210: _("Object not found"),
|
|
211: _("Object does not exist"),
|
|
212: _("Account in use"),
|
|
213: _("Permission table error"),
|
|
214: _("Illegal password"),
|
|
215: _("Password does not match"),
|
|
216: _("Keep account number"),
|
|
502: _("Illegal command"),
|
|
503: _("Talk channel has ben opened"),
|
|
504: _("Talk channel is not open"),
|
|
511: _("Update started"),
|
|
512: _("Update did not start"),
|
|
513: _("Update data error"),
|
|
514: _("Update failed"),
|
|
515: _("Update succeeded"),
|
|
521: _("Failed to restore default config"),
|
|
522: _("Device restart required"),
|
|
523: _("Default config is illegal"),
|
|
602: _("Application restart required"),
|
|
603: _("System restart required"),
|
|
604: _("Write file error"),
|
|
605: _("Features are not supported"),
|
|
606: _("Verification failed"),
|
|
607: _("Configuration does not exist"),
|
|
608: _("Configuration parsing error"),
|
|
}
|
|
|
|
|
|
def tolog(s):
|
|
print(s)
|
|
if logLevel >= 20:
|
|
logfile = open(log, "wb")
|
|
logfile.write(bytes(s, "utf-8"))
|
|
logfile.close()
|
|
|
|
|
|
def get_nat_ip():
|
|
s = socket(AF_INET, SOCK_DGRAM)
|
|
try:
|
|
# doesn't even have to be reachable
|
|
s.connect(("10.255.255.255", 1))
|
|
IP = s.getsockname()[0]
|
|
except Exception:
|
|
IP = "127.0.0.1"
|
|
finally:
|
|
s.close()
|
|
return IP
|
|
|
|
|
|
def local_ip():
|
|
ip = get_nat_ip()
|
|
ipn = struct.unpack(">I", inet_aton(ip))
|
|
return (
|
|
inet_ntoa(struct.pack(">I", ipn[0] + 10)),
|
|
"255.255.255.0",
|
|
inet_ntoa(struct.pack(">I", (ipn[0] & 0xFFFFFF00) + 1)),
|
|
)
|
|
|
|
|
|
def sofia_hash(self, password):
|
|
md5 = hashlib.md5(bytes(password, "utf-8")).digest()
|
|
chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
return "".join([chars[sum(x) % 62] for x in zip(md5[::2], md5[1::2])])
|
|
|
|
|
|
def GetIP(s):
|
|
return inet_ntoa(struct.pack("I", int(s, 16)))
|
|
|
|
|
|
def SetIP(ip):
|
|
return "0x%08X" % struct.unpack("I", inet_aton(ip))
|
|
|
|
|
|
def GetAllAddr():
|
|
if os.name == "nt":
|
|
return [
|
|
x.split(":")[1].strip()
|
|
for x in str(check_output(["ipconfig"]), "866").split("\r\n")
|
|
if "IPv4" in x
|
|
]
|
|
else:
|
|
iptool = ["ip", "address"]
|
|
if platform.system() == "Darwin":
|
|
iptool = ["ifconfig"]
|
|
return [
|
|
x.split("/")[0].strip().split(" ")[1]
|
|
for x in str(check_output(iptool), "ascii").split("\n")
|
|
if "inet " in x and "127.0." not in x
|
|
]
|
|
|
|
|
|
def SearchXM(devices):
|
|
server = socket(AF_INET, SOCK_DGRAM)
|
|
server.bind(("", 34569))
|
|
server.settimeout(1)
|
|
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
|
server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
|
server.sendto(
|
|
struct.pack("BBHIIHHI", 255, 0, 0, 0, 0, 0, 1530, 0), ("255.255.255.255", 34569)
|
|
)
|
|
while True:
|
|
data = server.recvfrom(1024)
|
|
head, ver, typ, session, packet, info, msg, leng = struct.unpack(
|
|
"BBHIIHHI", data[0][:20]
|
|
)
|
|
if (msg == 1531) and leng > 0:
|
|
answer = json.loads(
|
|
data[0][20 : 20 + leng].replace(b"\x00", b""))
|
|
if answer["NetWork.NetCommon"]["MAC"] not in devices.keys():
|
|
devices[answer["NetWork.NetCommon"]["MAC"]] = answer[
|
|
"NetWork.NetCommon"
|
|
]
|
|
devices[answer["NetWork.NetCommon"]["MAC"]][u"Brand"] = u"xm"
|
|
server.close()
|
|
return devices
|
|
|
|
|
|
def SearchDahua(devices):
|
|
server = socket(AF_INET, SOCK_DGRAM)
|
|
server.bind(("", 5050))
|
|
server.settimeout(1)
|
|
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
|
server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
|
server.sendto(
|
|
b"\xa3\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
|
("255.255.255.255", 5050),
|
|
)
|
|
while True:
|
|
try:
|
|
data = server.recvfrom(1024)
|
|
if data[0][0] == "\xb3" and len(data[0]) > 137:
|
|
answer = {}
|
|
answer[u"Brand"] = u"dahua"
|
|
info, name = struct.unpack("8s16s", data[0][32:56])
|
|
answer[u"HostName"] = name.replace("\x00", "")
|
|
ip, mask, gate, dns, answer[u"TCPPort"] = struct.unpack(
|
|
"<IIII26xH", data[0][56:100]
|
|
)
|
|
(
|
|
answer[u"HostIP"],
|
|
answer[u"Submask"],
|
|
answer[u"GateWay"],
|
|
answer[u"DNS"],
|
|
) = ("0x%08X" % ip, "0x%08X" % mask, "0x%08X" % gate, "0x%08X" % dns)
|
|
answer[u"MAC"] = data[0][120:137]
|
|
answer[u"Model"] = data[0][137:]
|
|
answer[u"HttpPort"] = 80
|
|
answer[u"SN"] = ""
|
|
if answer[u"MAC"] not in devices.keys():
|
|
devices[answer[u"MAC"]] = answer
|
|
except:
|
|
break
|
|
server.close()
|
|
return devices
|
|
|
|
|
|
def SearchFros(devices):
|
|
server = socket(AF_INET, SOCK_DGRAM)
|
|
server.bind(("", 10000))
|
|
server.settimeout(1)
|
|
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
|
server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
|
server.sendto(
|
|
b"MO_I\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x01",
|
|
("255.255.255.255", 10000),
|
|
)
|
|
while True:
|
|
try:
|
|
data = server.recvfrom(1024)
|
|
cmd, legth = struct.unpack("<4xh9xi4x", data[0][:23])
|
|
ser, name = struct.unpack("<13s21s", data[0][23:57])
|
|
ip, mask, gate, dns = struct.unpack("<IIII", data[0][57:73])
|
|
ser = ser.replace("\x00", "")
|
|
mac = (
|
|
ser[:2]
|
|
+ ":"
|
|
+ ser[2:4]
|
|
+ ":"
|
|
+ ser[4:6]
|
|
+ ":"
|
|
+ ser[6:8]
|
|
+ ":"
|
|
+ ser[8:10]
|
|
+ ":"
|
|
+ ser[10:12]
|
|
)
|
|
name = name.replace("\x00", "")
|
|
ip, mask, gate, dns = (
|
|
"0x%08X" % ip,
|
|
"0x%08X" % mask,
|
|
"0x%08X" % gate,
|
|
"0x%08X" % dns,
|
|
)
|
|
ver, webver = struct.unpack("<4s4s", data[0][77:85])
|
|
ver = ".".join([str(ord(x)) for x in ver])
|
|
webver = ".".join([str(ord(x)) for x in webver])
|
|
if mac not in devices.keys():
|
|
devices[mac] = {
|
|
u"Brand": "fros",
|
|
u"GateWay": gate,
|
|
u"DNS": dns,
|
|
u"HostIP": ip,
|
|
u"HostName": name,
|
|
u"HttpPort": 80,
|
|
u"TCPPort": 80,
|
|
u"MAC": mac,
|
|
u"MaxBps": 0,
|
|
u"MonMode": u"HTTP",
|
|
u"SN": ser,
|
|
u"Submask": mask,
|
|
u"SwVer": ver,
|
|
u"WebVer": webver,
|
|
}
|
|
except:
|
|
break
|
|
server.close()
|
|
return devices
|
|
|
|
|
|
def SearchWans(devices):
|
|
server = socket(AF_INET, SOCK_DGRAM)
|
|
server.bind(("", 8600))
|
|
server.settimeout(1.3)
|
|
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
|
server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
|
server.sendto(b"DH\x01\x01", ("255.255.255.255", 8600))
|
|
while True:
|
|
try:
|
|
data = server.recvfrom(1024)
|
|
mac = [0, 0, 0, 0, 0, 0]
|
|
(
|
|
head,
|
|
pver,
|
|
type,
|
|
ip,
|
|
mask,
|
|
gate,
|
|
dns2,
|
|
dns,
|
|
mac[0],
|
|
mac[1],
|
|
mac[2],
|
|
mac[3],
|
|
mac[4],
|
|
mac[5],
|
|
port,
|
|
ser,
|
|
name,
|
|
ver,
|
|
webver,
|
|
user,
|
|
passwd,
|
|
dhcp,
|
|
) = struct.unpack(
|
|
"2sBB16s16s16s16s16s6BH32s32s48x16s16s32s32sxB22x", data[0][:324]
|
|
)
|
|
mac = "%02x:%02x:%02x:%02x:%02x:%02x" % (
|
|
mac[0],
|
|
mac[1],
|
|
mac[2],
|
|
mac[3],
|
|
mac[4],
|
|
mac[5],
|
|
)
|
|
name, ser, ver, webver = (
|
|
name.replace("\x00", ""),
|
|
ser.replace("\x00", ""),
|
|
ver.replace("\x00", ""),
|
|
webver.replace("\x00", ""),
|
|
)
|
|
ip, mask, gate, dns = (
|
|
SetIP(ip.replace("\x00", "")),
|
|
SetIP(mask.replace("\x00", "")),
|
|
SetIP(gate.replace("\x00", "")),
|
|
SetIP(dns.replace("\x00", "")),
|
|
)
|
|
if mac not in devices.keys():
|
|
devices[mac] = {
|
|
u"Brand": u"wans",
|
|
u"GateWay": gate,
|
|
u"DNS": dns,
|
|
u"HostIP": ip,
|
|
u"HostName": name,
|
|
u"HttpPort": port,
|
|
u"TCPPort": port,
|
|
u"MAC": mac,
|
|
u"MaxBps": 0,
|
|
u"MonMode": u"HTTP",
|
|
u"SN": ser,
|
|
u"Submask": mask,
|
|
u"SwVer": ver,
|
|
u"WebVer": webver,
|
|
}
|
|
except:
|
|
break
|
|
server.close()
|
|
return devices
|
|
|
|
|
|
# b'gE\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
def SearchBeward(devices):
|
|
server = socket(AF_INET, SOCK_DGRAM)
|
|
server.bind(("", 6667))
|
|
server.settimeout(1)
|
|
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
|
server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
|
server.sendto(b"u4aRnryQk5CN08/P08DAwMD/", ("255.255.255.255", 6666))
|
|
while True:
|
|
try:
|
|
data = server.recvfrom(1024)
|
|
tolog(repr((base64.b64decode(data[0]), data[1])) + "\n")
|
|
# head,ver,typ,session,packet,info,msg,leng = struct.unpack('BBHIIHHI',data[0][:20])
|
|
# if (msg == 1531) and leng > 0:
|
|
# answer = json.loads(data[0][20:20+leng].replace(b'\x00',b''))
|
|
# if answer['NetWork.NetCommon']['MAC'] not in devices.keys():
|
|
# devices[answer['NetWork.NetCommon']['MAC']] = answer['NetWork.NetCommon']
|
|
# devices[answer['NetWork.NetCommon']['MAC']][u'Brand'] = u"xm"
|
|
except:
|
|
break
|
|
server.close()
|
|
return devices
|
|
|
|
|
|
def ConfigXM(data):
|
|
config = {}
|
|
#TODO: may be just copy whwole devices[data[1]] to config?
|
|
for k in [u"HostName",u"HttpPort",u"MAC",u"MaxBps",u"MonMode",u"SSLPort",u"TCPMaxConn",u"TCPPort",u"TransferPlan",u"UDPPort","UseHSDownLoad"]:
|
|
if k in devices[data[1]]:
|
|
config[k] = devices[data[1]][k]
|
|
config[u"DvrMac"] = devices[data[1]][u"MAC"]
|
|
config[u"EncryptType"] = 1
|
|
config[u"GateWay"] = SetIP(data[4])
|
|
config[u"HostIP"] = SetIP(data[2])
|
|
config[u"Submask"] = SetIP(data[3])
|
|
config[u"Username"] = "admin"
|
|
config[u"Password"] = sofia_hash(data[5])
|
|
devices[data[1]][u"GateWay"] = config[u"GateWay"]
|
|
devices[data[1]][u"HostIP"] = config[u"HostIP"]
|
|
devices[data[1]][u"Submask"] = config[u"Submask"]
|
|
config = json.dumps(
|
|
config, ensure_ascii=False, sort_keys=True, separators=(", ", " : ")
|
|
).encode("utf8")
|
|
server = socket(AF_INET, SOCK_DGRAM)
|
|
server.bind(("", 34569))
|
|
server.settimeout(1)
|
|
server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
|
server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
|
clen = len(config)
|
|
server.sendto(
|
|
struct.pack(
|
|
"BBHIIHHI%ds2s" % clen,
|
|
255,
|
|
0,
|
|
254,
|
|
0,
|
|
0,
|
|
0,
|
|
1532,
|
|
clen + 2,
|
|
config,
|
|
b"\x0a\x00",
|
|
),
|
|
("255.255.255.255", 34569),
|
|
)
|
|
answer = {"Ret": 203}
|
|
e = 0
|
|
while True:
|
|
try:
|
|
data = server.recvfrom(1024)
|
|
head, ver, typ, session, packet, info, msg, leng = struct.unpack(
|
|
"BBHIIHHI", data[0][:20]
|
|
)
|
|
if (msg == 1533) and leng > 0:
|
|
answer = json.loads(
|
|
data[0][20 : 20 + leng].replace(b"\x00", b""))
|
|
break
|
|
except:
|
|
e += 1
|
|
if e > 3:
|
|
break
|
|
server.close()
|
|
return answer
|
|
|
|
|
|
def ConfigFros(data):
|
|
devices[data[1]][u"GateWay"] = SetIP(data[4])
|
|
devices[data[1]][u"HostIP"] = SetIP(data[2])
|
|
devices[data[1]][u"Submask"] = SetIP(data[3])
|
|
client = socket(AF_INET, SOCK_DGRAM)
|
|
client.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
|
client.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
|
client.sendto(
|
|
struct.pack(
|
|
"<4sB10xB3xB6xB12sx12sx12sxIIIIxB",
|
|
"MO_I",
|
|
2,
|
|
61,
|
|
61,
|
|
1,
|
|
devices[data[1]][u"MAC"].replace(":", ""),
|
|
"admin",
|
|
data[5],
|
|
int(SetIP(data[2]), 16),
|
|
int(SetIP(data[3]), 16),
|
|
int(SetIP(data[4]), 16),
|
|
int(SetIP(data[4]), 16),
|
|
80,
|
|
),
|
|
("255.255.255.255", 10000),
|
|
)
|
|
answer = {}
|
|
while True:
|
|
try:
|
|
data = client.recvfrom(1024)
|
|
if data[0][4] == "\x03":
|
|
s, type, n, n, result = struct.unpack("<4sB10xB3xB3xBx", data[0])
|
|
if result == 0:
|
|
answer[u"Ret"] = 100
|
|
else:
|
|
answer[u"Ret"] = 101
|
|
break
|
|
except:
|
|
break
|
|
e = 1
|
|
client.close()
|
|
return answer
|
|
|
|
|
|
def ConfigWans(data):
|
|
devices[data[1]][u"GateWay"] = SetIP(data[4])
|
|
devices[data[1]][u"HostIP"] = SetIP(data[2])
|
|
devices[data[1]][u"Submask"] = SetIP(data[3])
|
|
devices[data[1]][u"TCPPort"] = devices[data[1]][u"HttpPort"]
|
|
client = socket(AF_INET, SOCK_DGRAM)
|
|
# client.bind(('',8600))
|
|
client.settimeout(1)
|
|
client.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
|
client.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
|
mac = [int(x, 16) for x in data[1].split(":")]
|
|
client.sendto(
|
|
struct.pack(
|
|
"2sBB16s16s16s16s16s6BH32s32s48x16s16s32s32sxB22x",
|
|
"DH",
|
|
2,
|
|
1,
|
|
data[2],
|
|
data[3],
|
|
data[4],
|
|
"8.8.8.8",
|
|
data[4],
|
|
mac[0],
|
|
mac[1],
|
|
mac[2],
|
|
mac[3],
|
|
mac[4],
|
|
mac[5],
|
|
devices[data[1]][u"HttpPort"],
|
|
devices[data[1]][u"SN"],
|
|
devices[data[1]][u"HostName"],
|
|
devices[data[1]][u"SwVer"],
|
|
devices[data[1]][u"WebVer"],
|
|
"admin",
|
|
data[5],
|
|
0,
|
|
),
|
|
("255.255.255.255", 8600),
|
|
)
|
|
answer = {}
|
|
while True:
|
|
try:
|
|
data = client.recvfrom(1024)
|
|
mac = [0, 0, 0, 0, 0, 0]
|
|
(
|
|
head,
|
|
pver,
|
|
type,
|
|
ip,
|
|
mask,
|
|
gate,
|
|
dns2,
|
|
dns,
|
|
mac[0],
|
|
mac[1],
|
|
mac[2],
|
|
mac[3],
|
|
mac[4],
|
|
mac[5],
|
|
port,
|
|
ser,
|
|
name,
|
|
ver,
|
|
webver,
|
|
user,
|
|
passwd,
|
|
dhcp,
|
|
err,
|
|
) = struct.unpack(
|
|
"2sBB16s16s16s16s16s6BH32s32s48x16s16s32s32sxB22xB", data[0][:325]
|
|
)
|
|
mac = "%02x:%02x:%02x:%02x:%02x:%02x" % (
|
|
mac[0],
|
|
mac[1],
|
|
mac[2],
|
|
mac[3],
|
|
mac[4],
|
|
mac[5],
|
|
)
|
|
name, ser, ver, webver = (
|
|
name.replace("\x00", ""),
|
|
ser.replace("\x00", ""),
|
|
ver.replace("\x00", ""),
|
|
webver.replace("\x00", ""),
|
|
)
|
|
ip, mask, gate, dns = (
|
|
SetIP(ip.replace("\x00", "")),
|
|
SetIP(mask.replace("\x00", "")),
|
|
SetIP(gate.replace("\x00", "")),
|
|
SetIP(dns.replace("\x00", "")),
|
|
)
|
|
devices[mac] = {
|
|
u"Brand": u"wans",
|
|
u"GateWay": gate,
|
|
u"DNS": dns,
|
|
u"HostIP": ip,
|
|
u"HostName": name,
|
|
u"HttpPort": port,
|
|
u"TCPPort": port,
|
|
u"MAC": mac,
|
|
u"MaxBps": 0,
|
|
u"MonMode": u"HTTP",
|
|
u"SN": ser,
|
|
u"Submask": mask,
|
|
u"SwVer": ver,
|
|
u"WebVer": webver,
|
|
}
|
|
if err == 0:
|
|
answer[u"Ret"] = 100
|
|
else:
|
|
answer[u"Ret"] = 101
|
|
break
|
|
except:
|
|
break
|
|
e = 1
|
|
client.close()
|
|
return answer
|
|
|
|
|
|
def FlashXM(cmd):
|
|
cam = DVRIPCam(GetIP(devices[cmd[1]]["HostIP"]), "admin", cmd[2])
|
|
if cam.login():
|
|
cmd[4](_("Auth success"))
|
|
cam.upgrade(cmd[3], 0x4000, cmd[4])
|
|
else:
|
|
cmd[4](_("Auth failed"))
|
|
|
|
|
|
def ProcessCMD(cmd):
|
|
global log, logLevel, devices, searchers, configure, flashers
|
|
if logLevel == 20:
|
|
tolog(datetime.now().strftime("[%Y-%m-%d %H:%M:%S] >") + " ".join(cmd))
|
|
if cmd[0].lower() == "q" or cmd[0].lower() == "quit":
|
|
sys.exit(1)
|
|
if cmd[0].lower() in ["help", "?", "/?", "-h", "--help"]:
|
|
return help
|
|
if cmd[0].lower() == "search":
|
|
tolog("%s" % (_("Search")))
|
|
if len(cmd) > 1 and cmd[1].lower() in searchers.keys():
|
|
try:
|
|
devices = searchers[cmd[1].lower()](devices)
|
|
except Exception as error:
|
|
print(" ".join([str(x) for x in list(error.args)]))
|
|
print(_("Searching %s, found %d devices") % (cmd[1], len(devices)))
|
|
else:
|
|
for s in searchers:
|
|
tolog(_("Search") + " %s\r" % s)
|
|
try:
|
|
devices = searchers[s](devices)
|
|
except Exception as error:
|
|
print(" ".join([str(x) for x in list(error.args)]))
|
|
tolog(_("Found %d devices") % len(devices))
|
|
if len(devices) > 0:
|
|
if logLevel > 0:
|
|
cmd[0] = "table"
|
|
print("")
|
|
if cmd[0].lower() == "table":
|
|
logs = (
|
|
_("Vendor")
|
|
+ "\t"
|
|
+ _("MAC Address")
|
|
+ "\t\t"
|
|
+ _("Name")
|
|
+ "\t"
|
|
+ _("IP Address")
|
|
+ "\t"
|
|
+ _("Port")
|
|
+ "\n"
|
|
)
|
|
for dev in devices:
|
|
logs += "%s\t%s\t%s\t%s\t%s\n" % (
|
|
devices[dev]["Brand"],
|
|
devices[dev]["MAC"],
|
|
devices[dev]["HostName"],
|
|
GetIP(devices[dev]["HostIP"]),
|
|
devices[dev]["TCPPort"],
|
|
)
|
|
if logLevel >= 20:
|
|
tolog(logs)
|
|
if logLevel >= 10:
|
|
return logs
|
|
if cmd[0].lower() == "csv":
|
|
logs = (
|
|
_("Vendor")
|
|
+ ";"
|
|
+ _("MAC Address")
|
|
+ ";"
|
|
+ _("Name")
|
|
+ ";"
|
|
+ _("IP Address")
|
|
+ ";"
|
|
+ _("Port")
|
|
+ ";"
|
|
+ _("SN")
|
|
+ "\n"
|
|
)
|
|
for dev in devices:
|
|
logs += "%s;%s;%s;%s;%s;%s\n" % (
|
|
devices[dev]["Brand"],
|
|
devices[dev]["MAC"],
|
|
devices[dev]["HostName"],
|
|
GetIP(devices[dev]["HostIP"]),
|
|
devices[dev]["TCPPort"],
|
|
devices[dev]["SN"],
|
|
)
|
|
if logLevel >= 20:
|
|
tolog(logs)
|
|
if logLevel >= 10:
|
|
return logs
|
|
if cmd[0].lower() == "html":
|
|
logs = (
|
|
"<table border=1><th>"
|
|
+ _("Vendor")
|
|
+ "</th><th>"
|
|
+ _("MAC Address")
|
|
+ "</th><th>"
|
|
+ _("Name")
|
|
+ "</th><th>"
|
|
+ _("IP Address")
|
|
+ "</th><th>"
|
|
+ _("Port")
|
|
+ "</th><th>"
|
|
+ _("SN")
|
|
+ "</th>\r\n"
|
|
)
|
|
for dev in devices:
|
|
logs += (
|
|
"<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\r\n"
|
|
% (
|
|
devices[dev]["Brand"],
|
|
devices[dev]["MAC"],
|
|
devices[dev]["HostName"],
|
|
GetIP(devices[dev]["HostIP"]),
|
|
devices[dev]["TCPPort"],
|
|
devices[dev]["SN"],
|
|
)
|
|
)
|
|
logs += "</table>\r\n"
|
|
if logLevel >= 20:
|
|
tolog(logs)
|
|
if logLevel >= 10:
|
|
return logs
|
|
if cmd[0].lower() == "json":
|
|
logs = json.dumps(devices)
|
|
if logLevel >= 20:
|
|
tolog(logs)
|
|
if logLevel >= 10:
|
|
return logs
|
|
if cmd[0].lower() == "device":
|
|
if len(cmd) > 1 and cmd[1] in devices.keys():
|
|
return json.dumps(devices[cmd[1]])
|
|
else:
|
|
return "device [MAC]"
|
|
if cmd[0].lower() == "config":
|
|
if (
|
|
len(cmd) > 5
|
|
and cmd[1] in devices.keys()
|
|
and devices[cmd[1]]["Brand"] in configure.keys()
|
|
):
|
|
return configure[devices[cmd[1]]["Brand"]](cmd)
|
|
else:
|
|
return "config [MAC] [IP] [MASK] [GATE] [Pasword]"
|
|
if cmd[0].lower() == "flash":
|
|
if (
|
|
len(cmd) > 3
|
|
and cmd[1] in devices.key(s)
|
|
and devices[cmd[1]]["Brand"] in flashers.keys()
|
|
):
|
|
if len(cmd) == 4:
|
|
cmd[4] = tolog
|
|
return flashers[devices[cmd[1]]["Brand"]](cmd)
|
|
else:
|
|
return "flash [MAC] [password] [file]"
|
|
if cmd[0].lower() == "loglevel":
|
|
if len(cmd) > 1:
|
|
logLevel = int(cmd[1])
|
|
else:
|
|
return "loglevel [int]"
|
|
if cmd[0].lower() == "log":
|
|
if len(cmd) > 1:
|
|
log = " ".join(cmd[1:])
|
|
else:
|
|
return "log [filename]"
|
|
if cmd[0].lower() == "echo":
|
|
if len(cmd) > 1:
|
|
return " ".join(cmd[1:])
|
|
return ""
|
|
|
|
|
|
class GUITk:
|
|
def __init__(self, root):
|
|
self.root = root
|
|
self.root.wm_title(_("Device Manager"))
|
|
self.root.tk.call("wm", "iconphoto", root._w, PhotoImage(data=icon))
|
|
self.f = Frame(self.root)
|
|
self.f.pack(fill=BOTH, expand=YES)
|
|
|
|
self.f.columnconfigure(0, weight=1)
|
|
self.f.rowconfigure(0, weight=1)
|
|
|
|
self.fr = Frame(self.f)
|
|
self.fr.grid(row=0, column=0, columnspan=3, sticky="nsew")
|
|
self.fr_tools = Frame(self.f)
|
|
self.fr_tools.grid(row=1, column=0, columnspan=6, sticky="ew")
|
|
self.fr_config = Frame(self.f)
|
|
self.fr_config.grid(row=0, column=5, sticky="nsew")
|
|
|
|
self.fr.columnconfigure(0, weight=1)
|
|
self.fr.rowconfigure(0, weight=1)
|
|
|
|
self.table = Treeview(self.fr, show="headings", selectmode="browse", height=10)
|
|
self.table.grid(column=0, row=0, sticky="nsew")
|
|
self.table["columns"] = ("ID", "vendor", "addr", "port", "name", "mac", "sn")
|
|
self.table["displaycolumns"] = ("vendor", "addr", "port", "name", "mac", "sn")
|
|
|
|
self.table.heading("vendor", text=_("Vendor"), anchor="w")
|
|
self.table.heading("addr", text=_("IP Address"), anchor="w")
|
|
self.table.heading("port", text=_("Port"), anchor="w")
|
|
self.table.heading("name", text=_("Name"), anchor="w")
|
|
self.table.heading("mac", text=_("MAC Address"), anchor="w")
|
|
self.table.heading("sn", text=_("SN"), anchor="w")
|
|
|
|
self.table.column("vendor", stretch=0, width=50)
|
|
self.table.column("addr", stretch=0, width=100)
|
|
self.table.column("port", stretch=0, width=50)
|
|
self.table.column("name", stretch=0, width=100)
|
|
self.table.column("mac", stretch=0, width=110)
|
|
self.table.column("sn", stretch=0, width=120)
|
|
|
|
self.scrollY = Scrollbar(self.fr, orient=VERTICAL)
|
|
self.scrollY.config(command=self.table.yview)
|
|
self.scrollY.grid(row=0, column=1, sticky="ns")
|
|
self.scrollX = Scrollbar(self.fr, orient=HORIZONTAL)
|
|
self.scrollX.config(command=self.table.xview)
|
|
self.scrollX.grid(row=1, column=0, sticky="ew")
|
|
self.table.config(
|
|
yscrollcommand=self.scrollY.set, xscrollcommand=self.scrollX.set
|
|
)
|
|
|
|
self.table.bind("<ButtonRelease>", self.select)
|
|
self.popup_menu = Menu(self.table, tearoff=0)
|
|
self.popup_menu.add_command(
|
|
label="Copy SN",
|
|
command=lambda: (
|
|
self.root.clipboard_clear()
|
|
or self.root.clipboard_append(
|
|
self.table.item(self.table.selection()[0], option="values")[6]
|
|
)
|
|
)
|
|
if len(self.table.selection()) > 0
|
|
else None,
|
|
)
|
|
self.popup_menu.add_command(
|
|
label="Copy line",
|
|
command=lambda: (
|
|
self.root.clipboard_clear()
|
|
or self.root.clipboard_append(
|
|
"\t".join(
|
|
self.table.item(self.table.selection()[0], option="values")[1:]
|
|
)
|
|
)
|
|
)
|
|
if len(self.table.selection()) > 0
|
|
else None,
|
|
)
|
|
self.table.bind("<Button-3>", self.popup)
|
|
|
|
self.l0 = Label(self.fr_config, text=_("Name"))
|
|
self.l0.grid(row=0, column=0, pady=3, padx=5, sticky=W + N)
|
|
self.name = Entry(self.fr_config, width=15, font="6")
|
|
self.name.grid(row=0, column=1, pady=3, padx=5, sticky=W + N)
|
|
self.l1 = Label(self.fr_config, text=_("IP Address"))
|
|
self.l1.grid(row=1, column=0, pady=3, padx=5, sticky=W + N)
|
|
self.addr = Entry(self.fr_config, width=15, font="6")
|
|
self.addr.grid(row=1, column=1, pady=3, padx=5, sticky=W + N)
|
|
self.l2 = Label(self.fr_config, text=_("Mask"))
|
|
self.l2.grid(row=2, column=0, pady=3, padx=5, sticky=W + N)
|
|
self.mask = Entry(self.fr_config, width=15, font="6")
|
|
self.mask.grid(row=2, column=1, pady=3, padx=5, sticky=W + N)
|
|
self.l3 = Label(self.fr_config, text=_("Gateway"))
|
|
self.l3.grid(row=3, column=0, pady=3, padx=5, sticky=W + N)
|
|
self.gate = Entry(self.fr_config, width=15, font="6")
|
|
self.gate.grid(row=3, column=1, pady=3, padx=5, sticky=W + N)
|
|
self.aspc = Button(self.fr_config, text=_("As on PC"), command=self.addr_pc)
|
|
self.aspc.grid(row=4, column=1, pady=3, padx=5, sticky="ew")
|
|
self.l4 = Label(self.fr_config, text=_("HTTP Port"))
|
|
self.l4.grid(row=5, column=0, pady=3, padx=5, sticky=W + N)
|
|
self.http = Entry(self.fr_config, width=5, font="6")
|
|
self.http.grid(row=5, column=1, pady=3, padx=5, sticky=W + N)
|
|
self.l5 = Label(self.fr_config, text=_("TCP Port"))
|
|
self.l5.grid(row=6, column=0, pady=3, padx=5, sticky=W + N)
|
|
self.tcp = Entry(self.fr_config, width=5, font="6")
|
|
self.tcp.grid(row=6, column=1, pady=3, padx=5, sticky=W + N)
|
|
self.l6 = Label(self.fr_config, text=_("Password"))
|
|
self.l6.grid(row=7, column=0, pady=3, padx=5, sticky=W + N)
|
|
self.passw = Entry(self.fr_config, width=15, font="6")
|
|
self.passw.grid(row=7, column=1, pady=3, padx=5, sticky=W + N)
|
|
self.aply = Button(self.fr_config, text=_("Apply"), command=self.setconfig)
|
|
self.aply.grid(row=8, column=1, pady=3, padx=5, sticky="ew")
|
|
|
|
self.l7 = Label(self.fr_tools, text=_("Vendor"))
|
|
self.l7.grid(row=0, column=0, pady=3, padx=5, sticky="wns")
|
|
self.ven = Combobox(self.fr_tools, width=10)
|
|
self.ven.grid(row=0, column=1, padx=5, sticky="w")
|
|
self.ven["values"] = [_("All"), "XM", "Dahua", "Fros", "Wans", "Beward"]
|
|
self.ven.current(0)
|
|
self.search = Button(self.fr_tools, text=_("Search"), command=self.search)
|
|
self.search.grid(row=0, column=2, pady=5, padx=5, sticky=W + N)
|
|
self.reset = Button(self.fr_tools, text=_("Reset"), command=self.clear)
|
|
self.reset.grid(row=0, column=3, pady=5, padx=5, sticky=W + N)
|
|
self.exp = Button(self.fr_tools, text=_("Export"), command=self.export)
|
|
self.exp.grid(row=0, column=4, pady=5, padx=5, sticky=W + N)
|
|
self.fl_state = StringVar(value=_("Flash"))
|
|
self.fl = Button(self.fr_tools, textvar=self.fl_state, command=self.flash)
|
|
self.fl.grid(row=0, column=5, pady=5, padx=5, sticky=W + N)
|
|
|
|
def popup(self, event):
|
|
try:
|
|
self.popup_menu.tk_popup(event.x_root, event.y_root, 0)
|
|
finally:
|
|
self.popup_menu.grab_release()
|
|
|
|
def addr_pc(self):
|
|
_addr, _mask, _gate = local_ip()
|
|
self.addr.delete(0, END)
|
|
self.addr.insert(END, _addr)
|
|
self.mask.delete(0, END)
|
|
self.mask.insert(END, _mask)
|
|
self.gate.delete(0, END)
|
|
self.gate.insert(END, _gate)
|
|
|
|
def search(self):
|
|
self.clear()
|
|
if self.ven["values"].index(self.ven.get()) == 0:
|
|
ProcessCMD(["search"])
|
|
else:
|
|
ProcessCMD(["search", self.ven.get()])
|
|
self.pop()
|
|
|
|
def pop(self):
|
|
for dev in devices:
|
|
self.table.insert(
|
|
"",
|
|
"end",
|
|
values=(
|
|
dev,
|
|
devices[dev]["Brand"],
|
|
GetIP(devices[dev]["HostIP"]),
|
|
devices[dev]["TCPPort"],
|
|
devices[dev]["HostName"],
|
|
devices[dev]["MAC"],
|
|
devices[dev]["SN"],
|
|
),
|
|
)
|
|
|
|
def clear(self):
|
|
global devices
|
|
for i in self.table.get_children():
|
|
self.table.delete(i)
|
|
devices = {}
|
|
|
|
def select(self, event):
|
|
if len(self.table.selection()) == 0:
|
|
return
|
|
dev = self.table.item(self.table.selection()[0], option="values")[0]
|
|
if logLevel >= 20:
|
|
print(json.dumps(devices[dev], indent=4, sort_keys=True))
|
|
self.name.delete(0, END)
|
|
self.name.insert(END, devices[dev]["HostName"])
|
|
self.addr.delete(0, END)
|
|
self.addr.insert(END, GetIP(devices[dev]["HostIP"]))
|
|
self.mask.delete(0, END)
|
|
self.mask.insert(END, GetIP(devices[dev]["Submask"]))
|
|
self.gate.delete(0, END)
|
|
self.gate.insert(END, GetIP(devices[dev]["GateWay"]))
|
|
self.http.delete(0, END)
|
|
self.http.insert(END, devices[dev]["HttpPort"])
|
|
self.tcp.delete(0, END)
|
|
self.tcp.insert(END, devices[dev]["TCPPort"])
|
|
|
|
def setconfig(self):
|
|
dev = self.table.item(self.table.selection()[0], option="values")[0]
|
|
devices[dev][u"TCPPort"] = int(self.tcp.get())
|
|
devices[dev][u"HttpPort"] = int(self.http.get())
|
|
devices[dev][u"HostName"] = self.name.get()
|
|
result = ProcessCMD(
|
|
[
|
|
"config",
|
|
dev,
|
|
self.addr.get(),
|
|
self.mask.get(),
|
|
self.gate.get(),
|
|
self.passw.get(),
|
|
]
|
|
)
|
|
if result["Ret"] == 100:
|
|
self.table.item(
|
|
self.table.selection()[0],
|
|
values=(
|
|
dev,
|
|
devices[dev]["Brand"],
|
|
GetIP(devices[dev]["HostIP"]),
|
|
devices[dev]["TCPPort"],
|
|
devices[dev]["HostName"],
|
|
devices[dev]["MAC"],
|
|
devices[dev]["SN"],
|
|
),
|
|
)
|
|
else:
|
|
showerror(_("Error"), CODES[result["Ret"]])
|
|
|
|
def export(self):
|
|
filename = asksaveasfilename(
|
|
filetypes=(
|
|
(_("JSON files"), "*.json"),
|
|
(_("HTML files"), "*.html;*.htm"),
|
|
(_("Text files"), "*.csv;*.txt"),
|
|
(_("All files"), "*.*"),
|
|
)
|
|
)
|
|
if filename == "":
|
|
return
|
|
ProcessCMD(["log", filename])
|
|
ProcessCMD(["loglevel", str(100)])
|
|
if ".json" in filename:
|
|
ProcessCMD(["json"])
|
|
elif ".csv" in filename:
|
|
ProcessCMD(["csv"])
|
|
elif ".htm" in filename:
|
|
ProcessCMD(["html"])
|
|
else:
|
|
ProcessCMD(["table"])
|
|
ProcessCMD(["loglevel", str(10)])
|
|
|
|
def flash(self):
|
|
self.fl_state.set("Processing...")
|
|
filename = askopenfilename(
|
|
filetypes=((_("Flash"), "*.bin"), (_("All files"), "*.*"))
|
|
)
|
|
if filename == "":
|
|
return
|
|
if len(self.table.selection()) == 0:
|
|
_mac = "all"
|
|
else:
|
|
_mac = self.table.item(self.table.selection()[0], option="values")[4]
|
|
result = ProcessCMD(
|
|
["flash", _mac, self.passw.get(), filename, self.fl_state.set]
|
|
)
|
|
if (
|
|
hasattr(result, "keys")
|
|
and "Ret" in result.keys()
|
|
and result["Ret"] in CODES.keys()
|
|
):
|
|
showerror(_("Error"), CODES[result["Ret"]])
|
|
|
|
|
|
searchers = {
|
|
"wans": SearchWans,
|
|
"xm": SearchXM,
|
|
"dahua": SearchDahua,
|
|
"fros": SearchFros,
|
|
"beward": SearchBeward,
|
|
}
|
|
configure = {
|
|
"wans": ConfigWans,
|
|
"xm": ConfigXM,
|
|
"fros": ConfigFros,
|
|
} # ,"dahua":ConfigDahua
|
|
flashers = {"xm": FlashXM} # ,"dahua":FlashDahua,"fros":FlashFros
|
|
logLevel = 30
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) > 1:
|
|
cmds = " ".join(sys.argv[1:])
|
|
if cmds.find("-q ") != -1:
|
|
cmds = cmds.replace("-q ", "").replace("-n ", "").strip()
|
|
logLevel = 0
|
|
for cmd in cmds.split(";"):
|
|
ProcessCMD(cmd.split(" "))
|
|
if GUI_TK and "-n" not in sys.argv:
|
|
root = Tk()
|
|
app = GUITk(root)
|
|
if (
|
|
"--theme" in sys.argv
|
|
): # ('winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative')
|
|
style = Style()
|
|
theme = [sys.argv.index("--theme") + 1]
|
|
if theme in style.theme_names():
|
|
style.theme_use(theme)
|
|
root.mainloop()
|
|
sys.exit(1)
|
|
print(_("Type help or ? to display help(q or quit to exit)"))
|
|
while True:
|
|
data = input("> ").split(";")
|
|
for cmd in data:
|
|
result = ProcessCMD(cmd.split(" "))
|
|
if hasattr(result, "keys") and "Ret" in result.keys():
|
|
print(CODES[result["Ret"]])
|
|
else:
|
|
print(result)
|
|
sys.exit(1)
|
|
|