修补登录问题
This commit is contained in:
parent
6f4d9d8181
commit
674da470d3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
3430
logs/app.log
3430
logs/app.log
File diff suppressed because it is too large
Load Diff
15720
logs/app.log.2025-09-09
Normal file
15720
logs/app.log.2025-09-09
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -93,7 +93,8 @@ class TaskBasicInfo(BaseModel):
|
|||||||
label: str = Field(..., description="任务名称")
|
label: str = Field(..., description="任务名称")
|
||||||
remark: Optional[str] = Field(None, description="备注")
|
remark: Optional[str] = Field(None, description="备注")
|
||||||
releaseSites: bool = Field(True, description="是否释放站点")
|
releaseSites: bool = Field(True, description="是否释放站点")
|
||||||
|
period: Optional[int]= Field(0, description="周期时间(定时任务 毫秒)")
|
||||||
|
delay: Optional[int]= Field(0, description="延迟时间(定时任务 毫秒)")
|
||||||
@validator('label')
|
@validator('label')
|
||||||
def label_must_not_be_empty_or_whitespace(cls, v):
|
def label_must_not_be_empty_or_whitespace(cls, v):
|
||||||
"""验证任务名称不为空且不只包含空白字符"""
|
"""验证任务名称不为空且不只包含空白字符"""
|
||||||
|
@ -512,12 +512,364 @@ async def get_all_movable_vehicles_in_loop(vehicle_list: list, location_list: li
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async def judgment_condition(location: str, batteryLevel: float, threshold: float, back_task_id: str) -> dict:
|
async def judgment_condition(location: str, batteryLevel: float, threshold: float, back_task_id: str, agv_id: str) -> dict:
|
||||||
if location.find("CP") != -1 and batteryLevel >= threshold:
|
"""
|
||||||
return {"bool": True}
|
判断是否满足执行条件
|
||||||
else:
|
|
||||||
|
Args:
|
||||||
|
location: 当前位置
|
||||||
|
batteryLevel: 电池电量
|
||||||
|
threshold: 电量阈值
|
||||||
|
back_task_id: 任务模板ID
|
||||||
|
agv_id: AGV设备ID
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: {"bool": True/False}
|
||||||
|
"""
|
||||||
|
from data.session import get_async_session
|
||||||
|
from data.models.taskrecord import VWEDTaskRecord
|
||||||
|
from data.enum.task_record_enum import TaskStatus
|
||||||
|
from sqlalchemy import select
|
||||||
|
from utils.logger import get_logger
|
||||||
|
|
||||||
|
logger = get_logger("scripts.user_save.test1")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 首先检查位置和电量条件
|
||||||
|
if location.find("CP") == -1 or batteryLevel < threshold:
|
||||||
return {"bool": False}
|
return {"bool": False}
|
||||||
# pass
|
|
||||||
|
# 检查是否有相同任务模板的运行任务且AGV相同
|
||||||
|
async with get_async_session() as session:
|
||||||
|
stmt = select(VWEDTaskRecord).where(
|
||||||
|
VWEDTaskRecord.def_id == back_task_id,
|
||||||
|
VWEDTaskRecord.agv_id == agv_id,
|
||||||
|
VWEDTaskRecord.status == TaskStatus.RUNNING,
|
||||||
|
VWEDTaskRecord.is_deleted == False
|
||||||
|
)
|
||||||
|
result = await session.execute(stmt)
|
||||||
|
running_tasks = result.scalars().all()
|
||||||
|
|
||||||
|
if running_tasks:
|
||||||
|
logger.info(f"发现相同任务模板的运行任务,AGV: {agv_id}, 任务模板: {back_task_id}, 运行任务数量: {len(running_tasks)}")
|
||||||
|
return {"bool": False}
|
||||||
|
|
||||||
|
logger.info(f"条件检查通过,位置: {location}, 电量: {batteryLevel}, 阈值: {threshold}, AGV: {agv_id}")
|
||||||
|
return {"bool": True}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"判断条件时发生错误: {str(e)}")
|
||||||
|
return {"bool": False}
|
||||||
|
|
||||||
|
|
||||||
|
async def check_location_lock_status(location_id: str) -> dict:
|
||||||
|
"""
|
||||||
|
查询库位是否被锁定
|
||||||
|
|
||||||
|
Args:
|
||||||
|
location_id: 库位ID(layer_name字段的值)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: {
|
||||||
|
"is_locked": bool, # 是否被锁定
|
||||||
|
"locked_by": str or None, # 锁定者,如果未锁定则为None
|
||||||
|
"location_exists": bool, # 库位是否存在
|
||||||
|
"message": str # 状态描述
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
from data.session import get_async_session
|
||||||
|
from data.models.operate_point_layer import OperatePointLayer
|
||||||
|
from sqlalchemy import select
|
||||||
|
from utils.logger import get_logger
|
||||||
|
|
||||||
|
logger = get_logger("scripts.user_save.test1")
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not location_id:
|
||||||
|
return {
|
||||||
|
"is_locked": False,
|
||||||
|
"locked_by": None,
|
||||||
|
"location_exists": False,
|
||||||
|
"message": "库位ID参数为空"
|
||||||
|
}
|
||||||
|
|
||||||
|
async with get_async_session() as session:
|
||||||
|
# 查询指定库位的锁定状态
|
||||||
|
stmt = select(OperatePointLayer).where(
|
||||||
|
OperatePointLayer.layer_name == location_id,
|
||||||
|
OperatePointLayer.is_deleted == False
|
||||||
|
).limit(1)
|
||||||
|
|
||||||
|
result = await session.execute(stmt)
|
||||||
|
location = result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if not location:
|
||||||
|
logger.warning(f"未找到库位: {location_id}")
|
||||||
|
return {
|
||||||
|
"is_locked": False,
|
||||||
|
"locked_by": None,
|
||||||
|
"location_exists": False,
|
||||||
|
"message": f"库位 {location_id} 不存在"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_locked = bool(location.is_locked)
|
||||||
|
locked_by = location.locked_by if is_locked else None
|
||||||
|
|
||||||
|
if is_locked:
|
||||||
|
message = f"库位 {location_id} 已被锁定,锁定者: {locked_by}"
|
||||||
|
logger.info(message)
|
||||||
|
else:
|
||||||
|
message = f"库位 {location_id} 未被锁定"
|
||||||
|
logger.info(message)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"is_locked": is_locked,
|
||||||
|
"locked_by": locked_by,
|
||||||
|
"location_exists": True,
|
||||||
|
"message": message
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = f"查询库位锁定状态时发生错误: {str(e)}"
|
||||||
|
logger.error(error_msg)
|
||||||
|
return {
|
||||||
|
"is_locked": False,
|
||||||
|
"locked_by": None,
|
||||||
|
"location_exists": False,
|
||||||
|
"message": error_msg
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def unlock_locations_when_last(current_location: str, location_list: list) -> dict:
|
||||||
|
"""
|
||||||
|
检查当前库位是否为库位集合的最后一个,如果是则解锁所有库位
|
||||||
|
|
||||||
|
Args:
|
||||||
|
current_location: 当前库位名称
|
||||||
|
location_list: 按照获取顺序的库位集合列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: {
|
||||||
|
"is_last": bool, # 是否为最后一个库位
|
||||||
|
"unlocked": bool, # 是否执行了解锁操作
|
||||||
|
"unlocked_count": int, # 解锁的库位数量
|
||||||
|
"message": str # 状态描述
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
from data.session import get_db
|
||||||
|
from services.operate_point_service import OperatePointService
|
||||||
|
from routes.model.operate_point_model import BatchStorageLocationStatusUpdateRequest, StorageLocationActionEnum
|
||||||
|
from utils.logger import get_logger
|
||||||
|
|
||||||
|
logger = get_logger("scripts.user_save.test1")
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not current_location:
|
||||||
|
return {
|
||||||
|
"is_last": False,
|
||||||
|
"unlocked": False,
|
||||||
|
"unlocked_count": 0,
|
||||||
|
"message": "当前库位参数为空"
|
||||||
|
}
|
||||||
|
|
||||||
|
if not location_list:
|
||||||
|
return {
|
||||||
|
"is_last": False,
|
||||||
|
"unlocked": False,
|
||||||
|
"unlocked_count": 0,
|
||||||
|
"message": "库位集合列表为空"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查当前库位是否在列表中
|
||||||
|
if current_location not in location_list:
|
||||||
|
return {
|
||||||
|
"is_last": False,
|
||||||
|
"unlocked": False,
|
||||||
|
"unlocked_count": 0,
|
||||||
|
"message": f"当前库位 {current_location} 不在库位集合中"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查是否为最后一个库位
|
||||||
|
is_last = current_location == location_list[-1]
|
||||||
|
|
||||||
|
if not is_last:
|
||||||
|
return {
|
||||||
|
"is_last": False,
|
||||||
|
"unlocked": False,
|
||||||
|
"unlocked_count": 0,
|
||||||
|
"message": f"当前库位 {current_location} 不是最后一个库位(最后一个为:{location_list[-1]})"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 当前库位是最后一个,执行批量解锁操作
|
||||||
|
logger.info(f"当前库位 {current_location} 是最后一个库位,开始解锁所有库位")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 创建批量解锁请求对象
|
||||||
|
batch_request = BatchStorageLocationStatusUpdateRequest(
|
||||||
|
layer_names=location_list,
|
||||||
|
action=StorageLocationActionEnum.UNLOCK,
|
||||||
|
reason="任务完成,自动解锁所有库位"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 使用数据库会话调用服务方法
|
||||||
|
db = next(get_db())
|
||||||
|
try:
|
||||||
|
# 调用批量更新库位状态服务
|
||||||
|
result = OperatePointService.batch_update_storage_location_status(db, batch_request)
|
||||||
|
|
||||||
|
logger.info(f"批量解锁完成:成功 {result.success_count} 个,失败 {result.failed_count} 个")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"is_last": True,
|
||||||
|
"unlocked": True,
|
||||||
|
"unlocked_count": result.success_count,
|
||||||
|
"message": f"当前库位是最后一个,已执行批量解锁:成功 {result.success_count} 个库位,失败 {result.failed_count} 个库位"
|
||||||
|
}
|
||||||
|
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"执行批量解锁时发生异常: {str(e)}")
|
||||||
|
return {
|
||||||
|
"is_last": True,
|
||||||
|
"unlocked": False,
|
||||||
|
"unlocked_count": 0,
|
||||||
|
"message": f"当前库位是最后一个,但解锁操作失败:{str(e)}"
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = f"检查库位和执行解锁时发生错误: {str(e)}"
|
||||||
|
logger.error(error_msg)
|
||||||
|
return {
|
||||||
|
"is_last": False,
|
||||||
|
"unlocked": False,
|
||||||
|
"unlocked_count": 0,
|
||||||
|
"message": error_msg
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def check_vehicle_at_location(vehicle_name: str, location_list: list, vehicle_current_position: str) -> dict:
|
||||||
|
"""
|
||||||
|
检查小车是否在被其锁定的库位对应的站点位置
|
||||||
|
|
||||||
|
Args:
|
||||||
|
vehicle_name: 小车名称
|
||||||
|
location_list: 库位列表
|
||||||
|
vehicle_current_position: 小车当前所在的位置/站点
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: {
|
||||||
|
"at_locked_location": bool, # 是否在被锁定的库位对应站点
|
||||||
|
"locked_location": str or None, # 被锁定的库位名称
|
||||||
|
"location_station": str or None,# 库位对应的站点名称
|
||||||
|
"vehicle_position": str, # 小车当前位置
|
||||||
|
"message": str # 状态描述
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
from data.session import get_async_session
|
||||||
|
from data.models.operate_point_layer import OperatePointLayer
|
||||||
|
from sqlalchemy import select
|
||||||
|
from utils.logger import get_logger
|
||||||
|
|
||||||
|
logger = get_logger("scripts.user_save.test1")
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not vehicle_name:
|
||||||
|
return {
|
||||||
|
"at_locked_location": False,
|
||||||
|
"locked_location": None,
|
||||||
|
"location_station": None,
|
||||||
|
"vehicle_position": vehicle_current_position,
|
||||||
|
"message": "小车名称参数为空"
|
||||||
|
}
|
||||||
|
|
||||||
|
if not location_list:
|
||||||
|
return {
|
||||||
|
"at_locked_location": False,
|
||||||
|
"locked_location": None,
|
||||||
|
"location_station": None,
|
||||||
|
"vehicle_position": vehicle_current_position,
|
||||||
|
"message": "库位列表为空"
|
||||||
|
}
|
||||||
|
|
||||||
|
if not vehicle_current_position:
|
||||||
|
return {
|
||||||
|
"at_locked_location": False,
|
||||||
|
"locked_location": None,
|
||||||
|
"location_station": None,
|
||||||
|
"vehicle_position": vehicle_current_position,
|
||||||
|
"message": "小车当前位置参数为空"
|
||||||
|
}
|
||||||
|
|
||||||
|
async with get_async_session() as session:
|
||||||
|
# 查询库位列表中被当前小车锁定的库位
|
||||||
|
stmt = select(OperatePointLayer).where(
|
||||||
|
OperatePointLayer.layer_name.in_(location_list),
|
||||||
|
OperatePointLayer.is_deleted == False,
|
||||||
|
OperatePointLayer.is_locked == True,
|
||||||
|
OperatePointLayer.locked_by == vehicle_name
|
||||||
|
)
|
||||||
|
|
||||||
|
result = await session.execute(stmt)
|
||||||
|
locked_locations = result.scalars().all()
|
||||||
|
|
||||||
|
if not locked_locations:
|
||||||
|
logger.info(f"小车 {vehicle_name} 未锁定库位列表中的任何库位")
|
||||||
|
return {
|
||||||
|
"at_locked_location": False,
|
||||||
|
"locked_location": None,
|
||||||
|
"location_station": None,
|
||||||
|
"vehicle_position": vehicle_current_position,
|
||||||
|
"message": f"小车 {vehicle_name} 未锁定库位列表中的任何库位"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查每个被锁定的库位
|
||||||
|
for locked_location in locked_locations:
|
||||||
|
location_station = locked_location.station_name
|
||||||
|
location_layer_name = locked_location.layer_name
|
||||||
|
|
||||||
|
logger.info(f"检查小车 {vehicle_name} 锁定的库位 {location_layer_name},对应站点: {location_station},小车当前位置: {vehicle_current_position}")
|
||||||
|
|
||||||
|
# 检查小车当前位置是否与库位对应的站点匹配
|
||||||
|
if vehicle_current_position == location_station:
|
||||||
|
logger.info(f"小车 {vehicle_name} 在被锁定的库位 {location_layer_name} 对应的站点 {location_station}")
|
||||||
|
return {
|
||||||
|
"at_locked_location": False,
|
||||||
|
"locked_location": location_layer_name,
|
||||||
|
"location_station": location_station,
|
||||||
|
"vehicle_position": vehicle_current_position,
|
||||||
|
"message": f"小车 {vehicle_name} 在被锁定的库位 {location_layer_name} 对应的站点 {location_station}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 如果有锁定库位但位置不匹配
|
||||||
|
locked_location_info = []
|
||||||
|
for locked_location in locked_locations:
|
||||||
|
locked_location_info.append(f"{locked_location.layer_name}(站点:{locked_location.station_name})")
|
||||||
|
|
||||||
|
message = f"小车 {vehicle_name} 不在被锁定库位的站点,当前位置: {vehicle_current_position},已锁定库位: {', '.join(locked_location_info)}"
|
||||||
|
logger.info(message)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"at_locked_location": True,
|
||||||
|
"locked_location": locked_locations[0].layer_name if locked_locations else None,
|
||||||
|
"location_station": locked_locations[0].station_name if locked_locations else None,
|
||||||
|
"vehicle_position": vehicle_current_position,
|
||||||
|
"message": message
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = f"检查小车位置时发生错误: {str(e)}"
|
||||||
|
logger.error(error_msg)
|
||||||
|
return {
|
||||||
|
"at_locked_location": False,
|
||||||
|
"locked_location": None,
|
||||||
|
"location_station": None,
|
||||||
|
"vehicle_position": vehicle_current_position,
|
||||||
|
"message": error_msg
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# 测试示例(注释掉的测试代码)
|
# 测试示例(注释掉的测试代码)
|
||||||
# async def test_movable_functions():
|
# async def test_movable_functions():
|
||||||
# """测试可移动小车功能的示例代码"""
|
# """测试可移动小车功能的示例代码"""
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -27,7 +27,7 @@ from utils.logger import get_logger
|
|||||||
from data.enum.call_device_enum import CallDeviceStatus, CallDeviceButtonStatus, CallDeviceButtonType
|
from data.enum.call_device_enum import CallDeviceStatus, CallDeviceButtonStatus, CallDeviceButtonType
|
||||||
from data.enum.task_record_enum import TaskStatus
|
from data.enum.task_record_enum import TaskStatus
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
from services.sync_service import set_task_terminated, get_login_token, refresh_token_if_needed
|
from services.sync_service import set_task_terminated, get_login_token, refresh_token_if_needed, refresh_token_if_needed_sync
|
||||||
|
|
||||||
from config.tf_api_config import TF_API_BASE_URL, TF_API_TOKEN_HEADER, TF_API_TOKEN
|
from config.tf_api_config import TF_API_BASE_URL, TF_API_TOKEN_HEADER, TF_API_TOKEN
|
||||||
# 设置日志
|
# 设置日志
|
||||||
@ -64,6 +64,20 @@ async def get_tf_api_token() -> str:
|
|||||||
return TF_API_TOKEN
|
return TF_API_TOKEN
|
||||||
|
|
||||||
|
|
||||||
|
def get_tf_api_token_sync() -> str:
|
||||||
|
try:
|
||||||
|
# 尝试刷新或获取新token
|
||||||
|
token = refresh_token_if_needed_sync()
|
||||||
|
if token:
|
||||||
|
logger.debug("成功获取动态token")
|
||||||
|
return token
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"获取动态token失败: {str(e)}")
|
||||||
|
|
||||||
|
# 如果获取失败,使用配置中的默认token
|
||||||
|
logger.info("使用默认配置中的token")
|
||||||
|
return TF_API_TOKEN
|
||||||
|
|
||||||
class CallDeviceService:
|
class CallDeviceService:
|
||||||
"""
|
"""
|
||||||
呼叫器设备服务类
|
呼叫器设备服务类
|
||||||
@ -1917,12 +1931,12 @@ class CallDeviceService:
|
|||||||
|
|
||||||
# 调用复位API
|
# 调用复位API
|
||||||
url = f"{api_url}{settings.CALLDEVICE_API_ENDPOINTS['set_device_state']}"
|
url = f"{api_url}{settings.CALLDEVICE_API_ENDPOINTS['set_device_state']}"
|
||||||
# tf_api_token = await get_tf_api_token()
|
tf_api_token = get_tf_api_token_sync()
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"User-Agent": "CallDeviceMonitor/1.0",
|
"User-Agent": "CallDeviceMonitor/1.0",
|
||||||
TF_API_TOKEN_HEADER: TF_API_TOKEN,
|
TF_API_TOKEN_HEADER: tf_api_token,
|
||||||
"x-tenant-id":"1000"
|
"x-tenant-id":"1000"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
@ -18,6 +18,7 @@ from typing import Dict, List, Any, Optional, Set, Tuple, Union
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from sqlalchemy import select, update, func
|
from sqlalchemy import select, update, func
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
from sqlalchemy.util import await_only
|
||||||
|
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
from data.models.taskdef import VWEDTaskDef
|
from data.models.taskdef import VWEDTaskDef
|
||||||
@ -541,7 +542,8 @@ class EnhancedTaskScheduler:
|
|||||||
select_agv_type = self.check_task_def_select_agv(task_def.detail)
|
select_agv_type = self.check_task_def_select_agv(task_def.detail)
|
||||||
|
|
||||||
# 导入同步服务
|
# 导入同步服务
|
||||||
from services.sync_service import create_task as tf_create_task
|
from services.sync_service import create_task as tf_create_task, refresh_token_if_needed
|
||||||
|
token =await refresh_token_if_needed()
|
||||||
|
|
||||||
# 调用主任务系统创建任务接口
|
# 调用主任务系统创建任务接口
|
||||||
sync_response = await tf_create_task(
|
sync_response = await tf_create_task(
|
||||||
@ -550,7 +552,7 @@ class EnhancedTaskScheduler:
|
|||||||
is_periodic=task_record.periodic_task,
|
is_periodic=task_record.periodic_task,
|
||||||
priority=task_record.priority,
|
priority=task_record.priority,
|
||||||
parent_id=task_record.parent_task_record_id or "",
|
parent_id=task_record.parent_task_record_id or "",
|
||||||
token=task_def.user_token,
|
token=token,
|
||||||
map_id=task_def.map_id,
|
map_id=task_def.map_id,
|
||||||
is_agv=select_agv_type
|
is_agv=select_agv_type
|
||||||
)
|
)
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -692,7 +692,7 @@ class GetBatteryLevelBlockHandler(RobotBlockHandler):
|
|||||||
from services.sync_service import get_amr_info
|
from services.sync_service import get_amr_info
|
||||||
|
|
||||||
# 获取关键参数用于验证
|
# 获取关键参数用于验证
|
||||||
vehicle = input_params.get("vehicle")
|
vehicle = str(input_params.get("vehicle")).strip()
|
||||||
|
|
||||||
# 参数检查
|
# 参数检查
|
||||||
if not vehicle:
|
if not vehicle:
|
||||||
@ -709,7 +709,8 @@ class GetBatteryLevelBlockHandler(RobotBlockHandler):
|
|||||||
if amr_info_result and amr_info_result.get("success", False):
|
if amr_info_result and amr_info_result.get("success", False):
|
||||||
# 获取AMR列表
|
# 获取AMR列表
|
||||||
amr_list = amr_info_result.get("result", [])
|
amr_list = amr_info_result.get("result", [])
|
||||||
|
# print(amr_list, "==")
|
||||||
|
# print(vehicle, "====")
|
||||||
# 根据机器人名称查找对应的AMR信息
|
# 根据机器人名称查找对应的AMR信息
|
||||||
target_amr = None
|
target_amr = None
|
||||||
for amr in amr_list:
|
for amr in amr_list:
|
||||||
|
@ -23,6 +23,8 @@ from services.execution.task_context import TaskContext
|
|||||||
from services.execution.block_executor import BlockExecutor
|
from services.execution.block_executor import BlockExecutor
|
||||||
from data.enum.task_record_enum import TaskStatus
|
from data.enum.task_record_enum import TaskStatus
|
||||||
from utils.logger import get_logger
|
from utils.logger import get_logger
|
||||||
|
from services.sync_service import set_task_in_progress, set_task_completed, set_task_failed, set_task_terminated, \
|
||||||
|
refresh_token_if_needed
|
||||||
|
|
||||||
# 获取日志记录器
|
# 获取日志记录器
|
||||||
logger = get_logger("services.execution.task_executor")
|
logger = get_logger("services.execution.task_executor")
|
||||||
@ -95,14 +97,14 @@ class TaskExecutor:
|
|||||||
# 解析任务输入参数
|
# 解析任务输入参数
|
||||||
input_params = json.loads(self.task_record.input_params) if self.task_record.input_params else {}
|
input_params = json.loads(self.task_record.input_params) if self.task_record.input_params else {}
|
||||||
# self.task_def.map_id
|
# self.task_def.map_id
|
||||||
|
token = await refresh_token_if_needed()
|
||||||
# 创建任务上下文
|
# 创建任务上下文
|
||||||
self.task_context = TaskContext(
|
self.task_context = TaskContext(
|
||||||
task_record_id=self.task_record_id,
|
task_record_id=self.task_record_id,
|
||||||
task_def_id=self.task_def.id,
|
task_def_id=self.task_def.id,
|
||||||
input_params=input_params,
|
input_params=input_params,
|
||||||
variables={},
|
variables={},
|
||||||
token=self.task_def.user_token,
|
token=token,
|
||||||
map_id=self.task_def.map_id
|
map_id=self.task_def.map_id
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -535,20 +537,19 @@ class TaskExecutor:
|
|||||||
task_detail: 任务详情
|
task_detail: 任务详情
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from services.sync_service import set_task_in_progress, set_task_completed, set_task_failed, set_task_terminated
|
token = await refresh_token_if_needed()
|
||||||
|
|
||||||
if not self.check_task_def_select_agv(task_detail):
|
if not self.check_task_def_select_agv(task_detail):
|
||||||
if status == TaskStatus.RUNNING:
|
if status == TaskStatus.RUNNING:
|
||||||
await set_task_in_progress(self.task_record_id, self.task_def.user_token)
|
await set_task_in_progress(self.task_record_id, token)
|
||||||
elif status == TaskStatus.COMPLETED:
|
elif status == TaskStatus.COMPLETED:
|
||||||
await set_task_completed(self.task_record_id, self.task_def.user_token)
|
await set_task_completed(self.task_record_id, token)
|
||||||
elif status == TaskStatus.FAILED:
|
elif status == TaskStatus.FAILED:
|
||||||
await set_task_failed(self.task_record_id, self.task_def.user_token)
|
await set_task_failed(self.task_record_id, token)
|
||||||
elif status == TaskStatus.CANCELED:
|
elif status == TaskStatus.CANCELED:
|
||||||
await set_task_terminated(self.task_record_id, self.task_def.user_token)
|
await set_task_terminated(self.task_record_id, token)
|
||||||
else:
|
else:
|
||||||
if status == TaskStatus.FAILED:
|
if status == TaskStatus.FAILED:
|
||||||
await set_task_failed(self.task_record_id, self.task_def.user_token)
|
await set_task_failed(self.task_record_id, token)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"外部API同步失败: {str(e)}")
|
logger.error(f"外部API同步失败: {str(e)}")
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
import json
|
import json
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import requests
|
||||||
from typing import Dict, Any, Optional
|
from typing import Dict, Any, Optional
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
@ -154,6 +155,7 @@ async def create_task(task_record_id: str, task_name: str, is_periodic: bool, pr
|
|||||||
# 尝试解析JSON
|
# 尝试解析JSON
|
||||||
try:
|
try:
|
||||||
response_data = json.loads(response_text)
|
response_data = json.loads(response_text)
|
||||||
|
# print(response_data, "-------------============================")
|
||||||
if response_data.get("success"):
|
if response_data.get("success"):
|
||||||
logger.info(f"成功同步任务到系统任务: {task_record_id}")
|
logger.info(f"成功同步任务到系统任务: {task_record_id}")
|
||||||
else:
|
else:
|
||||||
@ -965,6 +967,109 @@ def clear_cached_token():
|
|||||||
logger.info("已清除缓存的token")
|
logger.info("已清除缓存的token")
|
||||||
|
|
||||||
|
|
||||||
|
def get_login_token_sync(username: str = "vwed", password: str = "vwed_123456") -> Optional[str]:
|
||||||
|
"""
|
||||||
|
获取登录token (同步版本)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
username: 用户名,默认为"vwed"
|
||||||
|
password: 密码,默认为"vwed_123456"
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Optional[str]: 认证令牌,如果获取失败则返回None
|
||||||
|
"""
|
||||||
|
global _cached_token, _token_expire_time
|
||||||
|
|
||||||
|
# 检查是否有缓存的token且未过期
|
||||||
|
if _cached_token and _token_expire_time:
|
||||||
|
current_time = datetime.now().timestamp() * 1000 # 转换为毫秒
|
||||||
|
if current_time < _token_expire_time - 60000: # 提前1分钟刷新
|
||||||
|
logger.debug("使用缓存的token")
|
||||||
|
return _cached_token
|
||||||
|
|
||||||
|
# 构造请求参数
|
||||||
|
request_data = LoginRequest(
|
||||||
|
username=username,
|
||||||
|
password=password
|
||||||
|
)
|
||||||
|
|
||||||
|
# 调用接口
|
||||||
|
url = f"{TFApiConfig.BASE_URL}{TFApiConfig.LOGIN_PATH}"
|
||||||
|
|
||||||
|
# 构建请求头
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Tenant-Id": 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info(f"正在获取登录token,用户: {username}")
|
||||||
|
logger.debug(f"登录请求参数: {request_data.model_dump_json()}")
|
||||||
|
|
||||||
|
response = requests.post(
|
||||||
|
url,
|
||||||
|
json=request_data.model_dump(),
|
||||||
|
headers=headers,
|
||||||
|
timeout=TFApiConfig.TIMEOUT
|
||||||
|
)
|
||||||
|
|
||||||
|
# 尝试解析JSON
|
||||||
|
try:
|
||||||
|
response_data = response.json()
|
||||||
|
|
||||||
|
if response_data.get("success", False):
|
||||||
|
token = response_data.get("result", {}).get("token")
|
||||||
|
if token:
|
||||||
|
# 缓存token,设置过期时间为1小时后
|
||||||
|
_cached_token = token
|
||||||
|
_token_expire_time = datetime.now().timestamp() * 1000 + 3600000 # 1小时后过期
|
||||||
|
|
||||||
|
logger.info("成功获取登录token")
|
||||||
|
logger.debug(f"Token: {token[:20]}...") # 只记录token的前20个字符
|
||||||
|
return token
|
||||||
|
else:
|
||||||
|
logger.error("登录响应中未找到token")
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
logger.error(f"登录失败: {response_data.get('message', '未知错误')}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
except ValueError as e:
|
||||||
|
logger.error(f"解析登录响应JSON失败: {response.text}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
logger.error(f"调用登录接口失败: {str(e)}")
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"获取登录token时发生错误: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def refresh_token_if_needed_sync() -> Optional[str]:
|
||||||
|
"""
|
||||||
|
根据需要刷新token (同步版本)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Optional[str]: 有效的认证令牌,如果获取失败则返回None
|
||||||
|
"""
|
||||||
|
global _cached_token, _token_expire_time
|
||||||
|
|
||||||
|
# 检查token是否即将过期(提前5分钟刷新)
|
||||||
|
if _token_expire_time:
|
||||||
|
current_time = datetime.now().timestamp() * 1000
|
||||||
|
if current_time >= _token_expire_time - 300000: # 5分钟内过期
|
||||||
|
logger.info("Token即将过期,正在刷新...")
|
||||||
|
return get_login_token_sync()
|
||||||
|
|
||||||
|
# 如果没有token,获取新的
|
||||||
|
if not _cached_token:
|
||||||
|
logger.info("没有缓存的token,正在获取...")
|
||||||
|
return get_login_token_sync()
|
||||||
|
|
||||||
|
return _cached_token
|
||||||
|
|
||||||
|
|
||||||
# import asyncio
|
# import asyncio
|
||||||
# task_block_id = "1947858858043117570"
|
# task_block_id = "1947858858043117570"
|
||||||
# station_name = "AP1"
|
# station_name = "AP1"
|
||||||
|
@ -567,6 +567,8 @@ class TaskEditService:
|
|||||||
"changed": False,
|
"changed": False,
|
||||||
"message": "数据未发生变化",
|
"message": "数据未发生变化",
|
||||||
"id": task_def.id,
|
"id": task_def.id,
|
||||||
|
"delay": task_def.delay,
|
||||||
|
"period": task_def.period,
|
||||||
"label": task_def.label,
|
"label": task_def.label,
|
||||||
"remark": task_def.remark,
|
"remark": task_def.remark,
|
||||||
"releaseSites": bool(task_def.release_sites)
|
"releaseSites": bool(task_def.release_sites)
|
||||||
@ -576,6 +578,8 @@ class TaskEditService:
|
|||||||
task_def.label = basic_info.label
|
task_def.label = basic_info.label
|
||||||
task_def.remark = basic_info.remark
|
task_def.remark = basic_info.remark
|
||||||
task_def.release_sites = release_sites_new
|
task_def.release_sites = release_sites_new
|
||||||
|
task_def.period = basic_info.period
|
||||||
|
task_def.delay = basic_info.delay
|
||||||
|
|
||||||
# 保存到数据库
|
# 保存到数据库
|
||||||
await session.commit()
|
await session.commit()
|
||||||
@ -590,6 +594,8 @@ class TaskEditService:
|
|||||||
"id": task_def.id,
|
"id": task_def.id,
|
||||||
"label": task_def.label,
|
"label": task_def.label,
|
||||||
"remark": task_def.remark,
|
"remark": task_def.remark,
|
||||||
|
"period": task_def.period,
|
||||||
|
"delay": task_def.delay,
|
||||||
"releaseSites": bool(task_def.release_sites),
|
"releaseSites": bool(task_def.release_sites),
|
||||||
"updateTime": update_time
|
"updateTime": update_time
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -19,6 +19,23 @@ import json
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from config.tf_api_config import TF_API_TOKEN, TF_API_BASE_URL
|
from config.tf_api_config import TF_API_TOKEN, TF_API_BASE_URL
|
||||||
from config.settings import settings
|
from config.settings import settings
|
||||||
|
from services.sync_service import refresh_token_if_needed_sync
|
||||||
|
|
||||||
|
|
||||||
|
def get_tf_api_token_sync() -> str:
|
||||||
|
try:
|
||||||
|
# 尝试刷新或获取新token
|
||||||
|
token = refresh_token_if_needed_sync()
|
||||||
|
# print(token, "================")
|
||||||
|
if token:
|
||||||
|
# logger.debug("成功获取动态token")
|
||||||
|
return token
|
||||||
|
except Exception as e:
|
||||||
|
print(f"获取动态token失败: {str(e)}")
|
||||||
|
|
||||||
|
# 如果获取失败,使用配置中的默认token
|
||||||
|
print("使用默认配置中的token")
|
||||||
|
return TF_API_TOKEN
|
||||||
|
|
||||||
|
|
||||||
class AlertSyncService:
|
class AlertSyncService:
|
||||||
@ -186,7 +203,7 @@ class AlertSyncService:
|
|||||||
Returns:
|
Returns:
|
||||||
是否发送成功
|
是否发送成功
|
||||||
"""
|
"""
|
||||||
# get_tf_api_token()
|
token = get_tf_api_token_sync()
|
||||||
for attempt in range(self.retry_count):
|
for attempt in range(self.retry_count):
|
||||||
try:
|
try:
|
||||||
print("------------------====>>>", alert_data,"<<<<=================")
|
print("------------------====>>>", alert_data,"<<<<=================")
|
||||||
@ -195,7 +212,7 @@ class AlertSyncService:
|
|||||||
json=alert_data,
|
json=alert_data,
|
||||||
timeout=self.timeout,
|
timeout=self.timeout,
|
||||||
headers={'Content-Type': 'application/json',
|
headers={'Content-Type': 'application/json',
|
||||||
'x-access-token': TF_API_TOKEN
|
'x-access-token': token
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user