2025-09-10 15:45:35 +08:00

887 lines
36 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import asyncio
from typing import Dict, Any
EXTERNAL_CALLBACK_URL = "http://roh.vwfawedl.mobi:9001/AGVService/ContainerSendBackRequest" # 生产线到毛坯库任务
async def test1(a: int, b: int) -> int:
return {"name": a + b}
def name1(*args, **kwargs):
return {"test": "12333"}
async def validate_task_condition(function_args: Dict[str, Any]) -> Dict[str, Any]:
"""
任务状态验证功能,用于验证关联任务的状态
Args:
function_args: 包含以下参数的字典
- task_code: 任务代码,用于查询外部任务记录
- task_type: 任务类型,用于判断验证逻辑
- end_node: 终点节点仅对GT类型任务需要
Returns:
Dict[str, Any]: 验证结果
"""
from services.external_task_record_service import ExternalTaskRecordService
from services.task_record_service import TaskRecordService
from data.session import get_async_session
from data.models.operate_point_layer import OperatePointLayer
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")
# print(function_args, "=========================")
try:
# 获取参数
task_code = function_args.get('task_code')
task_type = function_args.get('task_type')
end_node = function_args.get('end_node')
if not task_code:
return {
"success": False,
"message": "task_code参数为空"
}
if not task_type:
return {
"success": False,
"message": "task_type参数为空"
}
# 定义任务类型模板映射
TASK_TYPE_TEMPLATE_MAPPING = {
"GG2MP": "GG",
"GGFK2MP": "GG",
"GT2MP": "GT",
"GTFK2MP": "GT",
"ZG2MP": "ZG",
"QZ2MP": "QZ",
"LG2MP": "LG",
"PHZ2MP": "PHZ",
"MP2GG": "GG",
"MP2GGFK": "GG",
"MP2GT": "GT",
"MP2GTFK": "GT",
"MP2ZG": "ZG",
"MP2QZ": "QZ",
"MP2LG": "LG",
"MP2PHZ": "PHZ"
}
# 根据TaskCode查询external_task_record表获取task_record_id
external_records = await ExternalTaskRecordService.get_task_records_by_task_code(task_code)
logger.info(f"系统相关记录: {external_records}")
if not external_records:
return {
"success": False,
"message": f"找不到TaskCode={task_code}对应的叫料任务记录,无法监控叫料任务状态"
}
# 获取最新的记录
latest_record = max(external_records, key=lambda x: x.created_at)
if not latest_record.task_record_id:
return {
"success": False,
"message": "叫料任务记录对应关键字task_record_id值为空"
}
# 获取TaskType对应的模板类型
template_type = TASK_TYPE_TEMPLATE_MAPPING.get(task_type, "")
logger.info(f"TaskCode={task_code}, TaskType={task_type}, TemplateType={template_type}")
while True:
try:
async with get_async_session() as session:
# 查询end_node对应的库位锁定状态
stmt = select(OperatePointLayer).where(
OperatePointLayer.layer_name == end_node,
OperatePointLayer.is_deleted == False
).limit(1)
result = await session.execute(stmt)
end_layer = result.scalar_one_or_none()
task_detail_result = await TaskRecordService.get_task_record_detail(
latest_record.task_record_id)
task_detail = task_detail_result.get("data", {})
task_status = task_detail.get("status", "")
if task_status == TaskStatus.CANCELED:
return {
"success": True,
"message": f"任务被取消: TaskCode={task_code}, Status={task_status}"
}
if end_layer:
if not end_layer.is_locked:
return {
"success": True,
"message": f"任务验证通过end_node库位已解锁: {end_node}"
}
else:
logger.info(f"任务end_node库位被锁定等待解锁: TaskCode={task_code}, end_node={end_node}, locked_by={end_layer.locked_by}")
await asyncio.sleep(2) # 等待2秒后重试
else:
logger.warning(f"任务未找到end_node对应的库位继续执行: TaskCode={task_code}, end_node={end_node}")
return {
"success": True,
"message": f"任务验证通过,未找到对应库位,继续执行: {end_node}"
}
except Exception as e:
logger.error(f"任务检查end_node库位锁定状态时出现异常: {str(e)}, TaskCode={task_code}, end_node={end_node}")
await asyncio.sleep(2) # 等待2秒后重试
except Exception as e:
logger.error(f"任务状态验证异常: {str(e)}")
return {
"success": False,
"message": f"任务状态验证异常: {str(e)}"
}
async def call_external_callback(req_code: str, task_type: str, arrival_user: str = "000307" ) -> dict:
"""
调用外部回调接口
Args:
req_code: 到货编号ReqCode
task_type: 任务类型
arrival_user: 到货用户,固定值 000307
Returns:
bool: 调用是否成功返回result为0
"""
arrival_no = req_code
import aiohttp
from utils.logger import get_logger
logger = get_logger("scripts.user_save.test1")
if task_type not in ["GTFK2MP", "GGFK2MP"]:
return {"message": "不是返空类型 不需要过账"}
payload = {
"arrival_no": arrival_no,
"arrival_user": arrival_user
}
max_retries = 100 # 最大重试次数,防止无限循环
retry_count = 0
while retry_count < max_retries:
try:
async with aiohttp.ClientSession() as sessions:
async with sessions.post(EXTERNAL_CALLBACK_URL, json=payload) as response:
result = await response.json()
logger.info(f"外部接口调用响应: {result}, arrival_no={arrival_no}, 重试次数={retry_count}")
# 检查响应结果
if result.get("result") == "0":
logger.info(f"外部接口调用成功: arrival_no={arrival_no}, 总重试次数={retry_count}")
return {"message": "空托盘过账成功!"}
elif result.get("result") == "1":
logger.info(f"外部接口返回result=1继续重试: arrival_no={arrival_no}, 重试次数={retry_count}")
retry_count += 1
await asyncio.sleep(5) # 等待5秒后重试
else:
logger.error(f"外部接口返回异常结果: {result}, arrival_no={arrival_no}")
retry_count += 1
await asyncio.sleep(5)
except Exception as e:
logger.error(f"调用外部接口异常: {str(e)}, arrival_no={arrival_no}, 重试次数={retry_count}")
retry_count += 1
await asyncio.sleep(5) # 等待5秒后重试
logger.error(f"外部接口调用失败,已达到最大重试次数: arrival_no={arrival_no}, 最大重试次数={max_retries}")
return {"message": "空托盘过账失败,重新尝试次数达到最大值"}
async def get_location(location_list: list, location_key: str) -> dict:
"""
根据当前库位获取下一个库位站点(轮回逻辑)
Args:
location_list: 库位列表,格式如 ["1-1", "1-2", "1-3", "1-4"]
location_key: 当前库位的key"1-2"
Returns:
str: 下一个库位,如 "1-3"
Example:
location_list = ["1-1", "1-2", "1-3", "1-4"]
await get_location(location_list, "1-2") # 返回 "1-3"
await get_location(location_list, "1-4") # 返回 "1-1" (轮回到第一个)
"""
try:
if not location_list:
raise ValueError("location_list不能为空")
if location_key not in location_list:
raise ValueError(f"location_key '{location_key}' 不存在于location_list中")
# 找到当前库位在列表中的位置
current_index = location_list.index(location_key)
# 计算下一个位置的索引(轮回逻辑)
next_index = (current_index + 1) % len(location_list)
# 返回下一个位置的库位
next_location_key = location_list[next_index]
return {"next_location_key": next_location_key}
except Exception as e:
# 如果出现异常,返回错误信息或默认值
from utils.logger import get_logger
logger = get_logger("scripts.user_save.test1")
logger.error(f"get_location函数执行异常: {str(e)}")
# 可以选择抛出异常或返回默认值
raise ValueError(f"get_location执行失败: {str(e)}")
# print(asyncio.run(get_location(["1-1", "1-2", "1-3", "1-4"], "1-4")))
async def find_movable_vehicle_in_loop(vehicle_list: list, location_list: list) -> dict:
"""
在环线工区中找到可以移动的小车
根据库位锁定者来判断小车现在所在位置,并检查前方库位是否可用
Args:
vehicle_list: 小车名称列表,如 ['amd1', 'amd2', 'amd3']
location_list: 库位名称列表(按环线顺序),如 ['1-1', '1-2', '1-3', '1-4']
环线逻辑1-1->1-2->1-3->1-4->1-1循环
Returns:
dict: {
'movable_vehicle': str or None, # 可以移动的小车名称
'target_location': str or None, # 前方可用的库位名称
'current_location': str or None, # 当前锁定的库位名称
'message': str # 状态描述
}
Example:
vehicle_list = ['amd1', 'amd2', 'amd3']
location_list = ['1-1', '1-2', '1-3', '1-4']
result = await find_movable_vehicle_in_loop(vehicle_list, location_list)
# 返回: {'movable_vehicle': 'amd3', 'target_location': '1-4', 'current_location': '1-3', 'message': '...'}
"""
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_list:
return {
'movable_vehicle': None,
'target_location': None,
'current_location': None,
'message': 'vehicle_list参数为空'
}
if not location_list:
return {
'movable_vehicle': None,
'target_location': None,
'current_location': None,
'message': 'location_list参数为空'
}
async with get_async_session() as session:
# 1. 找出所有被指定小车锁定的库位,记录每个小车的当前位置
vehicle_positions = {} # {vehicle_name: {'location': str, 'location_index': int, 'location_obj': obj}}
# 查询所有库位的锁定情况
stmt = select(OperatePointLayer).where(
OperatePointLayer.layer_name.in_(location_list),
OperatePointLayer.is_deleted == False,
OperatePointLayer.is_locked == True,
OperatePointLayer.locked_by.in_(vehicle_list)
)
result = await session.execute(stmt)
locked_locations = result.scalars().all()
# 建立小车位置映射
for location in locked_locations:
vehicle_name = location.locked_by
if location.layer_name in location_list:
location_index = location_list.index(location.layer_name)
vehicle_positions[vehicle_name] = {
'location': location.layer_name,
'location_index': location_index,
'location_obj': location
}
if not vehicle_positions:
return {
'movable_vehicle': None,
'target_location': None,
'current_location': None,
'message': '环线中没有被指定小车锁定的库位'
}
logger.info(f"当前小车位置: {[(k, v['location']) for k, v in vehicle_positions.items()]}")
# 2. 按环线顺序检查每个小车前方的库位是否可用
location_count = len(location_list)
for vehicle_name, position_info in vehicle_positions.items():
current_location_index = position_info['location_index']
current_location = position_info['location']
# 计算下一个库位位置(环线循环)
next_location_index = (current_location_index + 1) % location_count
next_location_name = location_list[next_location_index]
# 检查下一个库位是否被锁定
stmt = select(OperatePointLayer).where(
OperatePointLayer.layer_name == next_location_name,
OperatePointLayer.is_deleted == False
).limit(1)
result = await session.execute(stmt)
next_location_obj = result.scalar_one_or_none()
if next_location_obj:
if not next_location_obj.is_locked:
# 前方库位没有被锁定,说明这个小车可以移动
message = f'小车 {vehicle_name} 可以从 {current_location} 移动到 {next_location_name}'
logger.info(message)
return {
'movable_vehicle': vehicle_name,
'target_location': next_location_name,
'current_location': current_location,
'message': message
}
else:
logger.info(f'小车 {vehicle_name} 前方库位 {next_location_name} 被锁定,锁定者: {next_location_obj.locked_by}')
else:
logger.warning(f'未找到库位 {next_location_name}')
return {
'movable_vehicle': None,
'target_location': None,
'current_location': None,
'message': '环线中所有小车前方库位都被锁定,暂时无法移动'
}
except Exception as e:
error_msg = f'查找可移动小车时发生错误: {str(e)}'
logger.error(error_msg)
return {
'movable_vehicle': None,
'target_location': None,
'current_location': None,
'message': error_msg
}
async def get_all_movable_vehicles_in_loop(vehicle_list: list, location_list: list) -> dict:
"""
获取环线工区中所有可以移动的小车列表用于一轮调度3次的场景
Args:
vehicle_list: 小车名称列表,如 ['amd1', 'amd2', 'amd3']
location_list: 库位名称列表(按环线顺序),如 ['1-1', '1-2', '1-3', '1-4']
Returns:
dict: {
'movable_vehicles': list, # [{'vehicle': str, 'target_location': str, 'current_location': str}, ...]
'total_count': int, # 可移动小车总数
'message': str # 状态描述
}
Example:
result = await get_all_movable_vehicles_in_loop(['amd1', 'amd2', 'amd3'], ['1-1', '1-2', '1-3', '1-4'])
# 返回: {
# 'movable_vehicles': [
# {'vehicle': 'amd3', 'target_location': '1-4', 'current_location': '1-3'},
# {'vehicle': 'amd1', 'target_location': '1-2', 'current_location': '1-1'}
# ],
# 'total_count': 2,
# 'message': '找到2个可移动的小车'
# }
"""
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:
movable_vehicles = []
if not vehicle_list or not location_list:
return {
'movable_vehicles': [],
'total_count': 0,
'message': '参数为空,无法获取可移动小车'
}
async with get_async_session() as session:
# 1. 找出所有被指定小车锁定的库位,记录每个小车的当前位置
vehicle_positions = {} # {vehicle_name: {'location': str, 'location_index': int, 'location_obj': obj}}
print("location_list::", location_list)
print("vehicle_list::", vehicle_list)
# 查询所有库位的锁定情况
stmt = select(OperatePointLayer).where(
OperatePointLayer.layer_name.in_(location_list),
OperatePointLayer.is_deleted == False,
OperatePointLayer.is_locked == True,
OperatePointLayer.locked_by.in_(vehicle_list)
)
result = await session.execute(stmt)
locked_locations = result.scalars().all()
print(locked_locations, "============")
# 建立小车位置映射
for location in locked_locations:
vehicle_name = location.locked_by
print(vehicle_name)
if location.layer_name in location_list:
location_index = location_list.index(location.layer_name)
vehicle_positions[vehicle_name] = {
'location': location.layer_name,
'location_index': location_index,
'location_obj': location
}
if not vehicle_positions:
return {
'movable_vehicles': [],
'total_count': 0,
'message': '环线中没有被指定小车锁定的库位'
}
# 2. 检查每个小车前方的库位是否可用
location_count = len(location_list)
for vehicle_name, position_info in vehicle_positions.items():
current_location_index = position_info['location_index']
current_location = position_info['location']
# 计算下一个库位位置(环线循环)
next_location_index = (current_location_index + 1) % location_count
next_location_name = location_list[next_location_index]
# 检查下一个库位是否被锁定
stmt = select(OperatePointLayer).where(
OperatePointLayer.layer_name == next_location_name,
OperatePointLayer.is_deleted == False
).limit(1)
result = await session.execute(stmt)
next_location_obj = result.scalar_one_or_none()
if next_location_obj and not next_location_obj.is_locked:
movable_vehicles.append({
'vehicle': vehicle_name,
'target_location': next_location_name,
'current_location': current_location
})
total_count = len(movable_vehicles)
if total_count > 0:
vehicle_names = [v['vehicle'] for v in movable_vehicles]
message = f'找到{total_count}个可移动的小车: {", ".join(vehicle_names)}'
else:
message = '环线中所有小车前方库位都被锁定,暂时无法移动'
logger.info(message)
return {
'movable_vehicles': movable_vehicles[0],
# 'total_count': total_count,
# 'message': message
}
except Exception as e:
error_msg = f'获取可移动小车列表时发生错误: {str(e)}'
logger.error(error_msg)
return {
'movable_vehicles': [],
'total_count': 0,
'message': error_msg
}
async def judgment_condition(location: str, batteryLevel: float, threshold: float, back_task_id: str, agv_id: str) -> dict:
"""
判断是否满足执行条件
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}
# 检查是否有相同任务模板的运行任务且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: 库位IDlayer_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():
# """测试可移动小车功能的示例代码"""
# vehicle_list = ['amd1', 'amd2', 'amd3']
# action_point_list = ['1-1', '1-2', '1-3', '1-4']
#
# # 测试找到一个可移动的小车
# movable = await find_movable_vehicle_in_loop(vehicle_list, action_point_list)
# print("可移动小车:", movable)
#
# # 测试获取所有可移动的小车
# # all_movable = await get_all_movable_vehicles_in_loop(vehicle_list, action_point_list)
# # print("所有可移动小车:", all_movable)
#
# print(asyncio.run(test_movable_functions()))