db-api
This commit is contained in:
1
service/__init__.py
Normal file
1
service/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# Service package initialization
|
||||
285
service/api_http_client.py
Normal file
285
service/api_http_client.py
Normal file
@ -0,0 +1,285 @@
|
||||
from logging import exception
|
||||
from typing import Optional, Dict, Any
|
||||
import time
|
||||
import threading
|
||||
import requests
|
||||
from models import LoginResponse
|
||||
from config.ini_manager import ini_manager
|
||||
|
||||
|
||||
class BaseHttpClient:
|
||||
"""基础HTTP客户端 - 纯网络请求功能"""
|
||||
|
||||
def __init__(self):
|
||||
"""初始化基础HTTP客户端"""
|
||||
self._session = requests.Session()
|
||||
self._settings = None
|
||||
|
||||
def request(self, method: str, url: str, data: Dict[str, Any] = None,
|
||||
headers: Dict[str, str] = None, timeout: int = None,
|
||||
retries: int = 0, retry_interval: float = 1.0,
|
||||
**kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
发送HTTP请求,支持重试机制
|
||||
|
||||
Args:
|
||||
method: HTTP方法
|
||||
url: 请求URL
|
||||
data: 请求数据
|
||||
headers: 请求头
|
||||
timeout: 超时时间
|
||||
retries: 重试次数(可选,默认使用配置中的重试次数)
|
||||
retry_interval: 重试间隔(秒,默认1秒)
|
||||
**kwargs: 其他参数
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 响应数据
|
||||
"""
|
||||
|
||||
if headers is None:
|
||||
headers = {}
|
||||
# 重试逻辑
|
||||
for attempt in range(retries + 1):
|
||||
try:
|
||||
if method.upper() == 'GET':
|
||||
response = self._session.get(
|
||||
url, headers=headers, timeout=timeout, **kwargs
|
||||
)
|
||||
elif method.upper() == 'POST':
|
||||
response = self._session.post(
|
||||
url, json=data, headers=headers, timeout=timeout, **kwargs
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"不支持的HTTP方法: {method}")
|
||||
|
||||
# 检查响应状态
|
||||
response.raise_for_status()
|
||||
|
||||
# 解析JSON响应
|
||||
return response.json()
|
||||
|
||||
except exception as e:
|
||||
# 如果是最后一次尝试,直接抛出异常
|
||||
if attempt == retries:
|
||||
print(f"请求失败(第{attempt + 1}次尝试): {e}")
|
||||
raise
|
||||
# 打印重试信息
|
||||
print(f"请求失败(第{attempt + 1}次尝试),{retry_interval}秒后重试: {e}")
|
||||
# 等待重试间隔
|
||||
time.sleep(retry_interval)
|
||||
|
||||
def get(self, url: str, headers: Dict[str, str] = None,
|
||||
timeout: int = None, retries: int = 0, retry_interval: float = 1.0,
|
||||
**kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
GET请求
|
||||
|
||||
Args:
|
||||
url: 请求URL
|
||||
headers: 请求头
|
||||
timeout: 超时时间
|
||||
**kwargs: 其他参数
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 响应数据
|
||||
"""
|
||||
return self.request('GET', url, headers=headers, timeout=timeout, retries=retries, retry_interval=retry_interval, **kwargs)
|
||||
|
||||
def post(self, url: str, data: Dict[str, Any] = None,
|
||||
headers: Dict[str, str] = None, timeout: int = None,
|
||||
retries: int = 0, retry_interval: float = 1.0,
|
||||
**kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
POST请求
|
||||
|
||||
Args:
|
||||
url: 请求URL
|
||||
data: 请求数据
|
||||
headers: 请求头
|
||||
timeout: 超时时间
|
||||
retries: 重试次数(可选,默认使用配置中的重试次数)
|
||||
retry_interval: 重试间隔(秒,默认1秒)
|
||||
**kwargs: 其他参数
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 响应数据
|
||||
"""
|
||||
return self.request('POST', url, data=data, headers=headers, timeout=timeout, retries=retries, retry_interval=retry_interval, **kwargs)
|
||||
|
||||
|
||||
class ApiHttpClient(BaseHttpClient):
|
||||
"""API客户端 - 业务API调用,整合认证和单例功能"""
|
||||
|
||||
def __init__(self):
|
||||
"""初始化API客户端"""
|
||||
"""初始化API客户端"""
|
||||
super().__init__()
|
||||
# 认证缓存
|
||||
self._auth_cache = {
|
||||
'app_id': None,
|
||||
'expire_time': None,
|
||||
'sign_token': None,
|
||||
'zr_jwt': None
|
||||
}
|
||||
self._cache_lock = threading.RLock()
|
||||
|
||||
@property
|
||||
def settings(self):
|
||||
"""获取配置对象,由子类实现"""
|
||||
if self._settings is None:
|
||||
self._settings = ini_manager
|
||||
return self._settings
|
||||
|
||||
|
||||
def login(self) -> bool:
|
||||
"""
|
||||
用户登录获取AppID
|
||||
|
||||
Args:
|
||||
url: 登录URL(可选,默认使用配置中的URL)
|
||||
login_model: 登录请求模型(可选,默认使用配置中的模型)
|
||||
|
||||
Returns:
|
||||
bool: 登录是否成功
|
||||
"""
|
||||
url = self.settings.api_login_url
|
||||
login_model = self.settings.api_login_model
|
||||
|
||||
print("开始登录...")
|
||||
try:
|
||||
# 发送登录请求
|
||||
response_data = self.request(
|
||||
method='POST',
|
||||
url=url,
|
||||
data=login_model,
|
||||
timeout=self.settings.api_timeout
|
||||
)
|
||||
|
||||
# 解析登录响应
|
||||
login_response = LoginResponse(**response_data)
|
||||
|
||||
if login_response.Code != 200:
|
||||
error_msg = login_response.Message or "登录失败"
|
||||
print(f"获取AppID失败: {error_msg}")
|
||||
return False
|
||||
|
||||
# 更新认证缓存
|
||||
with self._cache_lock:
|
||||
self._auth_cache.update({
|
||||
'app_id': login_response.app_id,
|
||||
'expire_time': login_response.expire_time,
|
||||
'sign_token': login_response.sign_token,
|
||||
'zr_jwt': login_response.zr_jwt
|
||||
})
|
||||
|
||||
print(f"成功获取AppID: {self._auth_cache['app_id']}")
|
||||
print(f"过期时间: {self._auth_cache['expire_time']}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"登录过程中出现异常: {e}")
|
||||
self._clear_auth_cache()
|
||||
return False
|
||||
|
||||
def is_app_id_valid(self) -> bool:
|
||||
"""检查AppID是否有效"""
|
||||
with self._cache_lock:
|
||||
expire_time = self._auth_cache.get('expire_time')
|
||||
|
||||
if not expire_time:
|
||||
return False
|
||||
|
||||
# 检查是否过期(提前12小时过期,避免临界情况)
|
||||
try:
|
||||
expire_timestamp = time.mktime(time.strptime(expire_time, '%Y-%m-%d %H:%M:%S'))
|
||||
is_valid = time.time() < expire_timestamp - self.settings.api_auth_timeout
|
||||
if not is_valid:
|
||||
print("认证信息已过期")
|
||||
return is_valid
|
||||
except (ValueError, TypeError):
|
||||
print("日期格式不正确")
|
||||
return False
|
||||
|
||||
def _get_auth_headers(self) -> Dict[str, str]:
|
||||
"""获取认证头信息"""
|
||||
with self._cache_lock:
|
||||
app_id = self._auth_cache.get('app_id')
|
||||
|
||||
headers = {
|
||||
'AppID': app_id,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
return headers
|
||||
|
||||
|
||||
def get(self, url: str, auth: bool = True, **kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
GET请求(支持认证检查)
|
||||
|
||||
Args:
|
||||
url: 请求URL
|
||||
auth: 是否需要认证
|
||||
timeout: 超时时间
|
||||
retries: 重试次数
|
||||
retry_interval: 重试间隔
|
||||
**kwargs: 其他参数
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 响应数据
|
||||
"""
|
||||
if auth:
|
||||
if not self.is_app_id_valid():
|
||||
self.login()
|
||||
if not self.is_app_id_valid():
|
||||
raise Exception("登录失败,无法获取有效AppID")
|
||||
auth_headers = self._get_auth_headers()
|
||||
return self.request(method='GET', url=url, headers=auth_headers, timeout=self.settings.api_timeout,
|
||||
retries=self.settings.api_max_retries, retry_interval=self.settings.api_retry_interval, **kwargs)
|
||||
else:
|
||||
return self.request(method='GET', url=url, timeout=self.settings.api_timeout,
|
||||
retries=self.settings.api_max_retries, retry_interval=self.settings.api_retry_interval, **kwargs)
|
||||
|
||||
def post(self, url: str, data: Dict[str, Any] = None, auth: bool = True,**kwargs) -> Dict[str, Any]:
|
||||
"""
|
||||
POST请求(支持认证检查)
|
||||
|
||||
Args:
|
||||
url: 请求URL
|
||||
data: 请求数据
|
||||
auth: 是否需要认证
|
||||
timeout: 超时时间
|
||||
retries: 重试次数
|
||||
retry_interval: 重试间隔
|
||||
**kwargs: 其他参数
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: 响应数据
|
||||
"""
|
||||
if auth:
|
||||
if not self.is_app_id_valid():
|
||||
self.login()
|
||||
if not self.is_app_id_valid():
|
||||
raise Exception("登录失败,无法获取有效AppID")
|
||||
auth_headers = self._get_auth_headers()
|
||||
return self.request(method='POST', url=url, data=data, headers=auth_headers, timeout=self.settings.api_timeout,
|
||||
retries=self.settings.api_max_retries, retry_interval=self.settings.api_retry_interval, **kwargs)
|
||||
else:
|
||||
return self.request(method='POST', url=url, data=data, timeout=self.settings.api_timeout,
|
||||
retries=self.settings.api_max_retries, retry_interval=self.settings.api_retry_interval, **kwargs)
|
||||
|
||||
def _clear_auth_cache(self):
|
||||
"""清除认证缓存"""
|
||||
with self._cache_lock:
|
||||
self._auth_cache.clear()
|
||||
# 重新初始化必要的键
|
||||
self._auth_cache.update({
|
||||
'app_id': None,
|
||||
'expire_time': None,
|
||||
'sign_token': None,
|
||||
'zr_jwt': None
|
||||
})
|
||||
print("认证缓存已清除")
|
||||
|
||||
|
||||
api_http_client = ApiHttpClient()
|
||||
158
service/mould_service.py
Normal file
158
service/mould_service.py
Normal file
@ -0,0 +1,158 @@
|
||||
from datetime import datetime, timedelta
|
||||
from common.sqlite_handler import SQLiteHandler
|
||||
from typing import Optional, List
|
||||
from api_http_client import api_http_client
|
||||
from busisness.models import ArtifactInfo, TaskInfo, LoginRequest
|
||||
from config.ini_manager import ini_manager
|
||||
|
||||
|
||||
class MouldService:
|
||||
"""模具服务类,提供模具相关的API调用"""
|
||||
|
||||
def __init__(self):
|
||||
"""初始化模具服务"""
|
||||
self._api_client = api_http_client
|
||||
self._host = ini_manager.api_base_url
|
||||
|
||||
def get_task_info(self, task_id: str) -> Optional[TaskInfo]:
|
||||
"""
|
||||
获取任务单信息
|
||||
|
||||
Args:
|
||||
task_id: 任务单编号
|
||||
|
||||
Returns:
|
||||
任务单信息对象,如果失败返回None
|
||||
"""
|
||||
url = f"{self._host}/api/ext/artifact/task?TaskId={task_id}"
|
||||
|
||||
try:
|
||||
# 调用API获取数据
|
||||
response_data = self._api_client.get(url, auth=True)
|
||||
|
||||
# 检查响应状态
|
||||
if response_data.get('Code') != 200:
|
||||
print(f"获取任务单信息失败: {response_data.get('Message')}")
|
||||
return None
|
||||
|
||||
# 解析数据
|
||||
data = response_data.get('Data', {})
|
||||
if not data:
|
||||
print(f"未获取到任务单 {task_id} 的信息")
|
||||
return None
|
||||
|
||||
# 转换为任务单信息对象
|
||||
task_info = TaskInfo(**data)
|
||||
return task_info
|
||||
|
||||
except Exception as e:
|
||||
print(f"请求任务单信息异常: {e}")
|
||||
return None
|
||||
|
||||
def get_not_pour_artifacts(self) -> Optional[List[ArtifactInfo]]:
|
||||
"""
|
||||
获取已入模绑定未浇筑的管片信息
|
||||
|
||||
Returns:
|
||||
未浇筑管片列表,如果失败返回None
|
||||
"""
|
||||
url = f"{self._host}/api/ext/artifact/not_pour"
|
||||
|
||||
try:
|
||||
# 调用API获取数据
|
||||
response_data = self._api_client.get(url, auth=True)
|
||||
|
||||
# 检查响应状态
|
||||
if response_data.get('Code') != 200:
|
||||
print(f"获取未浇筑管片信息失败: {response_data.get('Message')}")
|
||||
return None
|
||||
|
||||
# 解析数据
|
||||
data_list = response_data.get('Data', [])
|
||||
if not data_list:
|
||||
print("当前没有未浇筑的管片")
|
||||
return []
|
||||
|
||||
# 转换为管片信息对象列表
|
||||
artifacts = [ArtifactInfo(**item) for item in data_list]
|
||||
return artifacts
|
||||
|
||||
except Exception as e:
|
||||
print(f"请求未浇筑管片信息异常: {e}")
|
||||
return None
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 创建模具服务实例
|
||||
mould_service = MouldService()
|
||||
db = SQLiteHandler.get_instance("db/three.db", max_readers=50, busy_timeout=4000)
|
||||
# 测试获取未浇筑管片信息
|
||||
not_poured = mould_service.get_not_pour_artifacts()
|
||||
if not_poured:
|
||||
for item in not_poured:
|
||||
artifact = db.fetch_one("SELECT * FROM ArtifactTask WHERE ArtifactID = ?", (item.ArtifactID,))
|
||||
if not artifact:
|
||||
dict={
|
||||
"ArtifactID": item.ArtifactID,
|
||||
"ArtifactActionID": item.ArtifactActionID,
|
||||
"ArtifactIDVice1": item.ArtifactIDVice1,
|
||||
"ProduceRingNumber": item.ProduceRingNumber,
|
||||
"MouldCode": item.MouldCode,
|
||||
"SkeletonID": item.SkeletonID,
|
||||
"RingTypeCode": item.RingTypeCode,
|
||||
"SizeSpecification": item.SizeSpecification,
|
||||
"BuriedDepth": item.BuriedDepth,
|
||||
"BlockNumber": item.BlockNumber,
|
||||
"BetonVolume": item.BetonVolume,
|
||||
"BetonTaskID": item.BetonTaskID,
|
||||
"HoleRingMarking": item.HoleRingMarking,
|
||||
"GroutingPipeMarking": item.GroutingPipeMarking,
|
||||
"PolypropyleneFiberMarking": item.PolypropyleneFiberMarking,
|
||||
"Status": 1,
|
||||
"Source": 1
|
||||
}
|
||||
db.insert("ArtifactTask", dict)
|
||||
|
||||
dict={
|
||||
"TaskID": item.BetonTaskID,
|
||||
"ProjectName": "上海市轨道交通19号线工程盾构区间管片生产2标",
|
||||
"ProduceMixID": "20251030-02",
|
||||
"VinNo": "",
|
||||
"BetonVolume": item.BetonVolume,
|
||||
"MouldCode": item.MouldCode,
|
||||
"SkeletonID": item.SkeletonID,
|
||||
"RingTypeCode": item.RingTypeCode,
|
||||
"SizeSpecification": item.SizeSpecification,
|
||||
"BuriedDepth": item.BuriedDepth,
|
||||
"BlockNumber": item.BlockNumber,
|
||||
"Mode": 1,
|
||||
"Status": 1,
|
||||
"Source": 1,
|
||||
"OptTime": str(datetime.now() - timedelta(minutes=5)),
|
||||
"CreateTime": str(datetime.now())
|
||||
}
|
||||
db.insert("PDRecord", dict)
|
||||
# for i in range(2, 5):
|
||||
# row = db.fetch_one("SELECT * FROM ArtifactTask WHERE ID = ?", (i,))
|
||||
# if row:
|
||||
# dict={
|
||||
# "TaskID": row["BetonTaskID"],
|
||||
# "ProjectName": "上海市轨道交通19号线工程盾构区间管片生产2标",
|
||||
# "ProduceMixID": "20251030-02",
|
||||
# "VinNo": "",
|
||||
# "BetonVolume": row["BetonVolume"],
|
||||
# "MouldCode": row["MouldCode"],
|
||||
# "SkeletonID": row["SkeletonID"],
|
||||
# "RingTypeCode": row["RingTypeCode"],
|
||||
# "SizeSpecification": row["SizeSpecification"],
|
||||
# "BuriedDepth": row["BuriedDepth"],
|
||||
# "BlockNumber": row["BlockNumber"],
|
||||
# "Mode": 1,
|
||||
# "Status": 1,
|
||||
# "Source": 1,
|
||||
# "OptTime": str(datetime.now() - timedelta(minutes=5)),
|
||||
# "CreateTime": str(datetime.now())
|
||||
# }
|
||||
# db.insert("PDRecord", dict)
|
||||
|
||||
Reference in New Issue
Block a user