import os
import ssl
import json
import time
import logging
import platform
import subprocess
import urllib.error
import urllib.request
import tempfile, shutil
class BaseActions:
def __init__(self, config_path=None):
self.token = ""
self.req_process = ""
# 默认路径(库所在目录)
current_dir = os.path.dirname(os.path.abspath(__file__))
default_setting_path = os.path.join(current_dir, "setting.json")
# 如果外部传入路径,则使用外部的
self.setting_path = config_path if config_path else default_setting_path
with open(self.setting_path, "r", encoding="utf-8") as f:
config = json.load(f)
self.config = config
self.username = config["username"]
self.ip = config["ip"]
self.passwd = config["password"]
self.initial_passwd = config["initial_password"]
ssl._create_default_https_context = ssl._create_unverified_context
self.logger = self.create_file_logger("mouse_simulate", "log.txt")
@staticmethod
def create_file_logger(logger_name, file_name, level=logging.DEBUG):
logger = logging.getLogger(logger_name)
logger.setLevel(level)
if not logger.handlers:
fh = logging.FileHandler(file_name)
sh = logging.StreamHandler()
formatter = logging.Formatter('[%(asctime)s] %(filename)s:%(lineno)d %(levelname)s %(message)s')
fh.setFormatter(formatter)
sh.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(sh)
return logger
def genpasswd(self, passwd):
passwdDic = '''yLwVl0zKqws7LgKPRQ84Mdt708T1qQ3Ha7xv3H7NyU84p21BriUWBU43odz3iP4rBL3cD02KZciXTysVXiV8ngg6vL48rPJyAUw0HurW20xqxv9aYb4M9wK1Ae0wlro510qXeU07kV57fQMc8L6aLgMLwygtc0F10a0Dg70TOoouyFhdysuRMO51yY5ZlOZZLEal1h0t9YQW0Ko7oBwmCAHoic4HYbUyVeU3sfQ1xtXcPcf1aT303wAQhv66qzW'''
passwdStrDe = "RDpbLfCPsJZ7fiv"
SecurePasswd = ""
LenStrDe = len(passwdStrDe)
LenDic = len(passwdDic)
LenPasswd = len(passwd)
LenPasswdEncode = max(LenPasswd, LenStrDe)
for i in range(LenPasswdEncode):
cl = 0xBB
cr = 0xBB
if i >= LenPasswd:
cr = ord(passwdStrDe[i])
elif i >= LenStrDe:
cl = ord(passwd[i])
else:
cl = ord(passwd[i])
cr = ord(passwdStrDe[i])
index = (cl ^ cr) % LenDic
SecurePasswd += passwdDic[index]
return SecurePasswd
def get(self, req):
if not self.token:
login_payload = {
"login": {
"username": self.username,
"encrypt_type": "1",
"password": self.genpasswd(self.passwd)
},
"method": "do"
}
try:
login_json = json.dumps(login_payload)
response = urllib.request.urlopen(f'https://{self.ip}/{login_json}')
self.token = json.loads(response.read())['stok']
except urllib.error.URLError as e:
self.logger.error(f'Login failed: {e.reason}')
return "timeout"
req = req[1:] if req.startswith('/') else req
try:
response = urllib.request.urlopen(f'https://{self.ip}/stok={self.token}/{req}')
return response.read()
except urllib.error.URLError as e:
self.logger.error(f'GET request failed: {e.reason}')
return "timeout"
def post(self, req):
if not self.token:
login_payload = {
"login": {
"username": self.username,
"encrypt_type": "1",
"password": self.genpasswd(self.passwd)
},
"method": "do"
}
try:
login_json = json.dumps(login_payload)
response = urllib.request.urlopen(
f'https://{self.ip}',
data=bytes(login_json, encoding='utf8')
)
resp_bytes = response.read()
#self.logger.info(f'Response:: {resp_bytes}')
resp_json = json.loads(resp_bytes)
self.token = resp_json['stok']
except urllib.error.URLError as e:
self.logger.error(f'Login failed: {e.reason}, {self.ip}')
return "timeout"
try:
#self.logger.debug(f'[发送POST请求] {req}')
response = urllib.request.urlopen(
f'https://{self.ip}/stok={self.token}/ds',
data=bytes(req, encoding='utf8')
)
return json.loads(response.read())
except urllib.error.URLError as e:
self.logger.error(f'POST request failed: {e.reason}')
return "timeout"
def initial_post(self, req):
if not self.token:
login_payload = {
"login": {
"username": self.username,
"encrypt_type": "1",
"password": self.genpasswd(self.initial_passwd)
},
"method": "do"
}
try:
login_json = json.dumps(login_payload)
response = urllib.request.urlopen(
f'https://{self.ip}',
data=bytes(login_json, encoding='utf8')
)
resp_bytes = response.read()
#self.logger.info(f'Response:: {resp_bytes}')
resp_json = json.loads(resp_bytes)
self.token = resp_json['stok']
except urllib.error.URLError as e:
self.logger.error(f'Login failed: {e.reason}')
return "timeout"
try:
#self.logger.debug(f'[发送POST请求] {req}')
response = urllib.request.urlopen(
f'https://{self.ip}/stok={self.token}/ds',
data=bytes(req, encoding='utf8')
)
return json.loads(response.read())
except urllib.error.URLError as e:
self.logger.error(f'POST request failed: {e.reason}')
return "timeout"
def get_stok(self):
login_payload = {
"login": {
"username": self.username,
"encrypt_type": "1",
"password": self.genpasswd(self.passwd)
},
"method": "do"
}
try:
login_json = json.dumps(login_payload)
response = urllib.request.urlopen(
f'https://{self.ip}',
data=bytes(login_json, encoding='utf8')
)
resp_bytes = response.read()
#self.logger.info(f'Response:: {resp_bytes}')
resp_json = json.loads(resp_bytes)
self.token = resp_json['stok']
except urllib.error.URLError as e:
self.logger.error(f'Login failed: {e.reason}, {self.ip}')
return "timeout"
def initial_post_without_token(self, req):
try:
#self.logger.debug(f'[发送POST请求] {req}')
data = json.dumps(req).encode("utf-8")
response = urllib.request.urlopen("https://%s" % self.ip, data=data)
#response = urllib.request.Request('https://%s'%self.ip, data=req.encode('utf-8'))
return json.loads(response.read())
except urllib.error.URLError as e:
self.logger.error(f'POST request failed: {e.reason}')
return "timeout"
def set_resolution(self, width, height):
data = json.loads(self.req_process)
data['system']['simulate_mouse']['resolution_width'] = str(width)
data['system']['simulate_mouse']['resolution_height'] = str(height)
self.req_process = json.dumps(data)
def enable_mouse_log(self):
payload = {
"method": "do",
"system": {"simulate_mouse": {"status": "open"}}
}
self.post(json.dumps(payload))
def initial_enable_mouse_log(self):
payload = {
"method": "do",
"system": {"simulate_mouse": {"status": "open"}}
}
self.initial_post(json.dumps(payload))
def disable_mouse_log(self):
payload = {
"method": "do",
"system": {"simulate_mouse": {"status": "close"}}
}
self.post(json.dumps(payload))
def simulate_click(self, action, x, y):
payload = {
"method": "do",
"system": {
"simulate_mouse": {
"status": "simulate_manual",
"action": action,
"position_x": str(x),
"position_y": str(y)
}
}
}
self.post(json.dumps(payload))
def initial_simulate_click(self, action, x, y):
payload = {
"method": "do",
"system": {
"simulate_mouse": {
"status": "simulate_manual",
"action": action,
"position_x": str(x),
"position_y": str(y)
}
}
}
self.initial_post(json.dumps(payload))
#req = self.initial_post(json.dumps(payload))
#self.logger.info(f'Response:: {req}')
def click_right(self, coord, t=None):
x,y = coord
self.simulate_click("click_right", x, y)
wait_time = t if t is not None else 2
#self.logger.info(f'wait {wait_time} seconds to continue next step')
time.sleep(wait_time)
def click_left(self, coord_info, t=None):
name = None
x = y = None
# 如果 coord_info 是 ((x,y), "name")
if (isinstance(coord_info, tuple)
and len(coord_info) == 2
and isinstance(coord_info[0], tuple)):
(x, y), name = coord_info
# 如果 coord_info 是纯 (x,y)
elif isinstance(coord_info, tuple) and len(coord_info) == 2 and all(isinstance(i, int) for i in coord_info):
x, y = coord_info
name = f"({x},{y})"
else:
raise ValueError(f"click_left 参数错误: {coord_info}")
self.simulate_click("click_left", x, y)
wait_time = t if t is not None else 2
self.logger.info(f'----Clicking on [{name}] at ({x}, {y}), wait {wait_time}s...')
time.sleep(wait_time)
def initial_click_left(self, coord_info, t=None):
name = None
x = y = None
# 如果 coord_info 是 ((x,y), "name")
if (isinstance(coord_info, tuple)
and len(coord_info) == 2
and isinstance(coord_info[0], tuple)):
(x, y), name = coord_info
# 如果 coord_info 是纯 (x,y)
elif isinstance(coord_info, tuple) and len(coord_info) == 2 and all(isinstance(i, int) for i in coord_info):
x, y = coord_info
name = f"({x},{y})"
else:
raise ValueError(f"click_left 参数错误: {coord_info}")
self.initial_simulate_click("click_left", x, y)
wait_time = t if t is not None else 2
self.logger.info(f'----Clicking on [{name}] at ({x}, {y}), wait {wait_time}s...')
time.sleep(wait_time)
def input(self, string):
payload = {
"method": "do",
"system": {
"simulate_mouse": {
"status": "simulate_manual",
"action": "keyboard_input",
"string": string
}
}
}
self.post(json.dumps(payload))
time.sleep(1)
def initial_input(self, string):
payload = {
"method": "do",
"system": {
"simulate_mouse": {
"status": "simulate_manual",
"action": "keyboard_input",
"string": string
}
}
}
self.initial_post(json.dumps(payload))
time.sleep(1)
def click_and_input(self, coord_info, string):
self.click_left(coord_info)
self.input(string)
def simulate_scroll(self, direction, step=1):
payload = {
"method": "do",
"system": {
"simulate_mouse": {
"status": "simulate_manual",
"action": "scroll_middle",
"direction": direction,
"step": str(step)
}
}
}
self.post(json.dumps(payload))
def wait(self, seconds):
time.sleep(seconds)
def ping(self, ip_address):
try:
# 根据操作系统选择不同的ping命令参数
param = '-n' if platform.system().lower() == 'windows' else '-c'
response = subprocess.run(['ping', param, '1', ip_address], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if response.returncode == 0:
self.logger.info(f"----成功 ping 通 {ip_address}:\n{response.stdout}")
return True
else:
self.logger.info(f"----未能 ping 通 {ip_address}")
return False
except Exception as e:
print(f"----执行 ping 命令时发生错误: {e}")
return False
def _save_config_atomic(self):
d = os.path.dirname(self.setting_path) or "."
fd, tmp = tempfile.mkstemp(dir=d, prefix=".setting.", suffix=".json")
os.close(fd)
try:
with open(tmp, "w", encoding="utf-8") as f:
json.dump(self.config, f, indent=4, ensure_ascii=False)
shutil.move(tmp, self.setting_path)
finally:
if os.path.exists(tmp):
os.remove(tmp)
def set_config_value(self, key, value, persist=True):
self.config[key] = value
if key == "ip":
self.ip = value
if persist:
self._save_config_atomic()
return value
def update_ip(self, new_ip: str, persist=True):
# 也可在这里做格式校验
return self.set_config_value("ip", new_ip, persist=persist)
这里面有双击函数吗,没有仿照click_left编写