first commit

This commit is contained in:
2026-02-02 11:47:53 +08:00
commit cc59e8b8da
35 changed files with 6733 additions and 0 deletions

479
globals/apis.py Normal file
View File

@@ -0,0 +1,479 @@
import requests
import json
import logging
import socket
from typing import Optional, Dict, Any
import globals.global_variable as global_variable
def send_tcp_command(command="StartMultiple", host="127.0.0.1", port=8888, timeout=10):
"""
使用TCP协议发送命令到指定地址和端口
参数:
command: 要发送的命令字符串(默认:"StartMultiple"
host: 目标主机地址(默认:"127.0.0.1"
port: 目标端口默认8888
timeout: 连接超时时间默认10
返回:
成功返回服务器响应字符串失败返回None
"""
# 创建TCP套接字
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
try:
# 设置超时时间
sock.settimeout(timeout)
# 连接到目标服务器
sock.connect((host, port))
logging.info(f"已成功连接到 {host}:{port}")
# 发送命令注意需要根据服务器要求的编码格式发送这里用UTF-8
sock.sendall(command.encode('utf-8'))
logging.info(f"已发送命令: {command}")
# 接收服务器响应缓冲区大小1024字节可根据实际情况调整
response = sock.recv(1024)
if response:
response_str = response.decode('utf-8')
logging.info(f"收到响应: {response_str}")
return response_str
else:
logging.info("未收到服务器响应")
return None
except ConnectionRefusedError:
logging.info(f"连接被拒绝,请检查 {host}:{port} 是否开启服务")
return None
except socket.timeout:
logging.info(f"连接超时({timeout}秒)")
return None
except Exception as e:
logging.info(f"发送命令时发生错误: {str(e)}")
return None
def get_breakpoint_list():
"""
获取需要处理的断点列表
"""
# 请求参数
params = {
'user_name': global_variable.GLOBAL_USERNAME
}
# 请求地址
url = "https://engineering.yuxindazhineng.com/index/index/get_name_all"
try:
# 发送GET请求
response = requests.get(url, params=params, timeout=30)
# 检查请求是否成功
if response.status_code == 200:
result = response.json()
# 检查接口返回状态
if result.get('code') == 0:
data = result.get('data', [])
logging.info("成功获取断点列表,数据条数:", len(data))
# 打印断点信息
# for item in data:
# logging.info(f"线路编码: {item.get('line_num')}, "
# f"线路名称: {item.get('line_name')}, "
# f"状态: {item.get('status')}, "
# f"用户: {item.get('name')}")
return data
else:
logging.info(f"接口返回错误: {result.get('code')}")
return [{"id": 37,
"user_name": "wangshun",
"name": "wangshun",
"line_num": "L193588",
"line_name": "CDWZQ-2标-155号路基左线-461221-461570-155左-平原",
"status": 3
}]
else:
logging.info(f"请求失败,状态码: {response.status_code}")
return []
except requests.exceptions.RequestException as e:
logging.info(f"请求异常: {e}")
return []
except ValueError as e:
logging.info(f"JSON解析错误: {e}")
return []
def get_measurement_task():
"""
获取测量任务
返回: 如果有状态为1的数据返回任务信息否则返回None
"""
try:
url = "https://engineering.yuxindazhineng.com/index/index/getOne"
# 获取用户名
user_name = global_variable.GLOBAL_USERNAME
if not user_name:
logging.error("未设置用户名,无法获取测量任务")
return None
# 构造请求参数
data = {
"user_name": user_name
}
logging.info(f"请求参数: user_name={user_name}")
response = requests.post(url, data=data, timeout=10)
response.raise_for_status()
data = response.json()
logging.info(f"接口返回数据: {data}")
if data.get('code') == 0 and data.get('data'):
task_data = data['data']
if task_data.get('status') == 1:
logging.info(f"获取到测量任务: {task_data}")
return task_data
else:
logging.info("获取到的任务状态不为1不执行测量")
return None
else:
logging.warning("未获取到有效任务数据")
return None
except Exception as e:
logging.error(f"获取测量任务失败: {str(e)}")
return None
def get_end_with_num():
"""
根据线路编码获取测量任务
返回: 如果有状态为1的数据返回任务信息否则返回None
"""
try:
url = "https://engineering.yuxindazhineng.com/index/index/getOne3"
# 获取用户名
user_name = global_variable.GLOBAL_USERNAME
line_num = global_variable.GLOBAL_LINE_NUM
if not line_num:
logging.error("未设置线路编码,无法获取测量任务")
return None
if not user_name:
logging.error("未设置用户名,无法获取测量任务")
return None
# 构造请求参数
data = {
"user_name": user_name,
"line_num": line_num
}
# logging.info(f"请求参数: user_name={user_name}, line_num={line_num}")
response = requests.post(url, data=data, timeout=10)
response.raise_for_status()
data = response.json()
logging.info(f"接口返回数据: {data}")
if data.get('code') == 0 and data.get('data'):
task_data = data['data']
if task_data.get('status') == 3:
logging.info(f"获取到测量任务: {task_data}")
return task_data
else:
logging.info("获取到的任务状态不为3不执行测量")
return None
else:
# logging.warning("未获取到有效任务数据")
return None
except Exception as e:
logging.error(f"获取测量任务失败: {str(e)}")
return None
def get_work_conditions_by_linecode(linecode: str) -> Optional[Dict[str, Dict]]:
"""
通过线路编码获取工况信息
Args:
linecode: 线路编码,如 "L118134"
Returns:
返回字典,格式为 {point_id: {"sjName": "", "workinfoname": "", "work_type": ""}}
如果请求失败返回None
"""
url="http://www.yuxindazhineng.com:3002/api/comprehensive_data/get_settlement_by_linecode"
max_retries = 3 # 最大重试次数
retry_count = 0 # 当前重试计数
while retry_count < max_retries:
try:
# 准备请求参数
payload = {"linecode": linecode}
headers = {
'Content-Type': 'application/json',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
logging.info(f"发送POST请求到: {url}")
logging.info(f"请求参数: {payload}")
# 发送POST请求
response = requests.post(
url,
json=payload,
headers=headers,
timeout=30
)
# 检查响应状态
if response.status_code != 200:
logging.error(f"HTTP请求失败状态码: {response.status_code}")
retry_count += 1
if retry_count < max_retries:
logging.info(f"准备重试... (剩余 {max_retries - retry_count} 次)")
continue # 继续重试
# 解析响应数据
try:
result = response.json()
except json.JSONDecodeError as e:
logging.error(f"JSON解析失败: {str(e)}")
retry_count += 1
if retry_count < max_retries:
logging.info(f"准备重试... (剩余 {max_retries - retry_count} 次)")
continue # 继续重试
# 检查API返回码
if result.get('code') != 0:
logging.error(f"API返回错误: {result.get('message', '未知错误')}")
return None
# 提取数据
data_list = result.get('data', [])
if not data_list:
logging.warning("未找到工况数据")
return {}
# 处理数据,提取所需字段
work_conditions = {}
for item in data_list:
point_id = item.get('aname')
if point_id:
work_conditions[point_id] = {
"sjName": item.get('sjName', ''),
"workinfoname": item.get('next_workinfo', ''),
"work_type": item.get('work_type', '')
}
logging.info(f"成功提取 {len(work_conditions)} 个测点的工况信息")
return work_conditions
except requests.exceptions.RequestException as e:
logging.error(f"网络请求异常: {str(e)}")
retry_count += 1
if retry_count < max_retries:
logging.info(f"准备重试... (剩余 {max_retries - retry_count} 次)")
except json.JSONDecodeError as e:
logging.error(f"JSON解析失败: {str(e)}")
retry_count += 1
if retry_count < max_retries:
logging.info(f"准备重试... (剩余 {max_retries - retry_count} 次)")
except Exception as e:
logging.error(f"获取工况信息时发生未知错误: {str(e)}")
retry_count += 1
if retry_count < max_retries:
logging.info(f"准备重试... (剩余 {max_retries - retry_count} 次)")
# 达到最大重试次数仍失败
logging.error(f"已达到最大重试次数 ({max_retries} 次),请求失败")
return None
def get_user_max_variation(username: str) -> Optional[int]:
"""
调用POST接口根据用户名获取用户的max_variation信息
Args:
username: 目标用户名,如 "chzq02-02guoyu"
Returns:
成功返回用户的max_variation整数值
失败返回None
"""
# 接口基础配置
api_url = "http://www.yuxindazhineng.com:3002/api/accounts/get"
timeout = 30 # 超时时间(避免请求长时间阻塞)
# 1. 准备请求参数与头部
# 接口要求的POST参数JSON格式
payload = {"username": username}
# 请求头部指定JSON格式模拟浏览器UA避免被接口拦截
headers = {
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
try:
# 2. 发送POST请求
response = requests.post(
url=api_url,
json=payload, # 自动将字典转为JSON字符串无需手动json.dumps()
headers=headers,
timeout=timeout
)
# 3. 检查HTTP响应状态200表示请求成功到达服务器
response.raise_for_status() # 若状态码非200如404、500直接抛出HTTPError
logging.info(f"接口请求成功HTTP状态码{response.status_code}")
# 4. 解析JSON响应处理文档中提到的"网页解析失败"风险)
try:
response_data = response.json()
except json.JSONDecodeError as e:
logging.error(f"接口返回数据非JSON格式解析失败{str(e)}")
logging.error(f"接口原始返回内容:{response.text[:500]}") # 打印前500字符便于排查
return None
# 5. 检查接口业务逻辑是否成功(按需求中"code=0表示查询成功"
if response_data.get("code") != 0:
logging.error(f"接口查询失败,业务错误信息:{response_data.get('message', '未知错误')}")
return None
# 6. 验证返回数据结构并提取max_variation
data_list = response_data.get("data", [])
if not data_list:
logging.warning(f"查询到用户名 {username},但未返回账号数据")
return None
# 检查第一条数据是否包含max_variation
first_user = data_list[0]
if "max_variation" not in first_user:
logging.warning(f"用户 {username} 的返回数据中缺少 max_variation 字段")
return None
max_variation = first_user["max_variation"]
logging.info(f"成功查询到用户 {username} 的 max_variation{max_variation}")
# 7. 直接返回max_variation的值
return max_variation
# 处理请求过程中的异常(网络问题、超时等)
except requests.exceptions.RequestException as e:
logging.error(f"接口请求异常(网络/超时/服务器不可达):{str(e)}")
# 若为连接错误,提示检查文档中提到的"不支持的网页类型"或域名有效性
if "ConnectionRefusedError" in str(e) or "Failed to establish a new connection" in str(e):
logging.error(f"建议排查1. 接口域名 {api_url} 是否可访问2. 服务器是否正常运行3. 端口3002是否开放")
return None
# 处理其他未知异常
except Exception as e:
logging.error(f"获取用户 {username} 的 max_variation 时发生未知错误:{str(e)}")
return None
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
def get_line_info_and_save_global(user_name: str) -> bool:
"""
调用get_name_all接口提取status=3的line_num和line_name存入全局字典
:param user_name: 接口请求参数,如"wangshun"
:return: 执行成功返回True失败/异常返回False
"""
# 接口基础配置
api_url = "https://engineering.yuxindazhineng.com/index/index/get_name_all"
request_params = {"user_name": user_name} # GET请求参数
timeout = 10 # 请求超时时间(秒),避免卡进程
try:
# 1. 发送GET请求
response = requests.get(
url=api_url,
params=request_params, # GET参数用params传递自动拼接到URL后规范且防乱码
timeout=timeout,
verify=False # 禁用SSL验证适配HTTPS接口
)
# 2. 校验HTTP状态码先确保请求本身成功
if response.status_code != 200:
logging.error(f"接口请求失败HTTP状态码异常{response.status_code},响应内容:{response.text}")
return False
# 3. 解析JSON响应接口返回是JSON格式需解析为字典
try:
response_data = response.json()
except Exception as e:
logging.error(f"接口返回内容非合法JSON无法解析{response.text},错误:{str(e)}")
return False
# 4. 校验业务状态码接口约定code=0成功-1失败
business_code = response_data.get("code")
if business_code == 0:
logging.info("接口业务请求成功,开始解析数据")
elif business_code == -1:
logging.error(f"接口业务请求失败业务状态码code=-1返回数据{response_data}")
return False
else:
logging.warning(f"接口返回未知业务状态码:{business_code},请确认接口文档")
return False
# 5. 提取data字段校验数据是否存在
api_data_list = response_data.get("data")
if not api_data_list:
logging.warning("接口业务成功但data字段为空或无数据")
return False
# 6. 校验data是否为列表类型
if not isinstance(api_data_list, list):
logging.error(f"data字段不是列表类型实际类型{type(api_data_list)},内容:{api_data_list}")
return False
found_valid_data = False
# 7. 遍历列表提取所有status=3的数据
for item in api_data_list:
# 确保每个item是字典
if not isinstance(item, dict):
logging.warning(f"列表中的元素不是字典类型,跳过:{item}")
continue
# 获取字段值
data_status = item.get("status")
line_num = item.get("line_num")
line_name = item.get("line_name")
# 校验status是否为3且目标字段非空
if data_status == 3 and line_num and line_name:
# # 存入全局字典key=line_numvalue=line_name
# global_variable.GLOBAL_UPLOAD_BREAKPOINT_DICT[line_num] = line_name
# 存入全局字典key=line_namevalue=line_num
global_variable.GLOBAL_UPLOAD_BREAKPOINT_DICT[line_name] = line_num
# 如果line_name不在列表中则添加
if line_name not in global_variable.GLOBAL_UPLOAD_BREAKPOINT_LIST:
global_variable.GLOBAL_UPLOAD_BREAKPOINT_LIST.append(line_name)
logging.info(f"找到status=3的线路信息line_num={line_num}, line_name={line_name}")
found_valid_data = True
if found_valid_data:
logging.info(f"成功提取所有status=3的线路信息当前全局字典数据{global_variable.GLOBAL_UPLOAD_BREAKPOINT_DICT}")
return True
else:
logging.warning("data列表中未找到任何status=3且字段完整的线路信息")
return False
# 捕获所有请求相关异常(超时、连接失败、网络异常等)
except requests.exceptions.Timeout:
logging.error(f"调用get_name_all接口超时超时时间{timeout}秒,请求参数:{request_params}")
return False
except requests.exceptions.ConnectionError:
logging.error(f"调用get_name_all接口连接失败检查网络或接口地址是否正确{api_url}")
return False
except Exception as e:
logging.error(f"调用get_name_all接口时发生未知异常{str(e)}", exc_info=True) # exc_info=True打印异常堆栈方便排查
return False