Commit 3ad4cb99 authored by 张晓彤's avatar 张晓彤

穿越装载区代码优化

parent 85a08dd5
...@@ -12,6 +12,7 @@ from data.dispatchInfo import DispatchInfo ...@@ -12,6 +12,7 @@ from data.dispatchInfo import DispatchInfo
from core.submit import DispatchSubmission from core.submit import DispatchSubmission
from core.group import GroupDispatcher from core.group import GroupDispatcher
from core.group import group_direct2redis from core.group import group_direct2redis
import uuid
config = { config = {
"DEBUG": True, # some Flask specific configs "DEBUG": True, # some Flask specific configs
...@@ -194,4 +195,535 @@ def dispatch_request(): ...@@ -194,4 +195,535 @@ def dispatch_request():
print(f'调度时耗 {rtd_end_time - rtd_start_time}') print(f'调度时耗 {rtd_end_time - rtd_start_time}')
return jsonify(msg="success", code=0) return jsonify(msg="success", code=0)
\ No newline at end of file
@app.route("/go_through", methods=["POST"])
def redispatch_request():
# 获取报文数据
data_json = request.get_json()
# 车辆id
request_truck_id = data_json.get("truck_id")
# request_truck_id = '0349fbdf-3c37-4fb3-867f-bea98a42af4a'
# 调度开始时间
rtd_start_time = datetime.now()
# 初始化日志
set_log()
# 获取日志器
logger = get_logger("zxt.Request")
# 更新周期参数
logger.info("#####################################请求调度更新开始#####################################")
'''
1. 更新全局参数信息
'''
try:
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
except Exception as es:
logger.error("数据库访问异常")
logger.error(es)
return jsonify(msg="未知异常, 请联系管理员", code=501)
try:
# 全局参数更新
global_period_para_update()
# get_global_para_from_cache(cache)
except Exception as es:
logger.error("全局参数更新异常")
logger.error(es)
session_mysql.rollback()
session_postgre.rollback()
return jsonify(msg="未知异常, 请联系管理员", code=502)
try:
# 更新调度信息
DispatchInfo.reset()
DispatchInfo.update_device_group_structure()
DispatchInfo.update_route_distance()
DispatchInfo.update_group_mode()
DispatchInfo.update_group_name()
except Exception as es:
logger.error("调度信息更新异常")
logger.error(es)
session_mysql.rollback()
session_postgre.rollback()
return jsonify(msg="未知异常, 请联系管理员", code=503)
logger.info("Dispatchinfo,更新后信息")
logger.info("group_set")
logger.info(DispatchInfo.group_set)
logger.info("group_excavator_dict")
logger.info(DispatchInfo.group_excavator_dict)
logger.info("group_unload_area_dict")
logger.info(DispatchInfo.group_unload_area_dict)
logger.info("group_truck_dict")
logger.info(DispatchInfo.group_truck_dict)
logger.info("group_mode")
logger.info(DispatchInfo.group_mode)
logger.info("load_distance")
logger.info(DispatchInfo.load_distance)
logger.info("unload_distance")
logger.info(DispatchInfo.unload_distance)
try:
# # 实例化设备对象
dump = DumpInfo()
excavator = ExcavatorInfo()
truck = TruckInfo(dump, excavator)
# 设备信息更新
dump.dump_para_period_update()
excavator.excavator_para_period_update()
truck.truck_para_period_update(dump, excavator)
truck.state_period_update()
except Exception as es:
logger.error("对象实例化异常")
logger.error(es)
session_mysql.rollback()
session_postgre.rollback()
return jsonify(msg="未知异常, 请联系管理员", code=504)
'''
2. 读取二次调度所需信息(车辆位置、分组、挖机等)
'''
try:
truck_uuid_to_name_dict = get_value("truck_uuid_to_name_dict")
# 获取请调车辆名
request_truck_name = truck_uuid_to_name_dict[request_truck_id]
except Exception as es:
logger.error(es)
return jsonify(msg="数据库异常, 车辆编号未知", code=510)
try:
# 读取请调车辆所属分组
group_id = DispatchInfo.truck_group_dict[request_truck_id]
# 读取分组挖机集合
excavators_id = DispatchInfo.get_excavator(group_id)
# 读取车辆位置信息
truck_locates_dict = get_trucks_locate()
logger.info("truck_locates_dict")
logger.info(truck_locates_dict)
closer_area_id = '7ff73575-2134-afd4-1065-d5d60e8751c9'
further_area_id = '79584290-1134-8b85-f4cc-1dcf64fc3456'
logger.info("近端装载区id")
logger.info(closer_area_id)
logger.info("远端装载区id")
logger.info(further_area_id)
# 读取两个挖机id
if closer_area_id in DispatchInfo.load_excavator_dict and further_area_id in DispatchInfo.load_excavator_dict:
closer_excavator_id, further_excavator_id = DispatchInfo.load_excavator_dict[closer_area_id], \
DispatchInfo.load_excavator_dict[further_area_id]
else:
return jsonify(msg="装载点信息错误", code=506)
# 读取挖机状态
closer_excavator_state, further_excavator_state = get_excavator_state(closer_excavator_id), \
get_excavator_state(further_excavator_id)
# 读取两个装载区入场点id
closer_entrance_node_id = session_postgre.query(DiggingWorkArea).filter_by(Id=closer_area_id).first().EntranceNodeId
further_entrance_node_id = session_postgre.query(DiggingWorkArea).filter_by(
Id=further_area_id).first().EntranceNodeId
logger.info("近端装载区入场点")
logger.info(closer_entrance_node_id)
logger.info("远端装载区入场点")
logger.info(further_entrance_node_id)
except Exception as es:
logger.error("读取装载区及车辆信息异常")
logger.error(es)
return jsonify(msg="未知异常, 请联系管理员", code=505)
try:
# 读取请调车辆所在路段信息
request_truck_lane_id = truck_locates_dict[request_truck_id]
logger.info("request_truck_lane_id:")
logger.info(request_truck_lane_id)
logger.info(truck_locates_dict)
except Exception as es:
logger.error(f'车辆 {request_truck_name} 位置信息不可用')
logger.error(es)
return jsonify(msg=f'车辆 {request_truck_name} 位置信息不可用, 请联系管理员', code=505)
'''
3. 调度判断逻辑
'''
# 车辆已驶过第一个装载点,车辆只能驶往远端装载区
if not truck_pass_first_area(request_truck_id, request_truck_lane_id, closer_entrance_node_id, further_entrance_node_id):
logger.info("车辆已经过近端装载区")
target_excavator = DispatchInfo.load_excavator_dict[further_area_id]
# truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[further_area_id])
# 车辆未驶过第一个装载点,进入二次调度逻辑
else:
# 近端挖机空闲
if closer_excavator_state == 0:
logger.info("近端挖机空闲, 调度车辆前往")
target_excavator = DispatchInfo.load_excavator_dict[closer_area_id]
# truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[closer_area_id])
# 远端挖机空闲
elif further_excavator_state == 0:
logger.info("远端挖机空闲, 调度车辆前往")
target_excavator = DispatchInfo.load_excavator_dict[further_area_id]
# truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[further_area_id])
# 两挖机均不空闲
else:
# 两装载点间路段集合
lane_set = get_lanes_between_entrances(closer_entrance_node_id, further_entrance_node_id)
# 选择合适装载区
target_excavator = area_choose(excavators_id, closer_area_id, further_area_id, lane_set, logger, truck, truck_locates_dict)
# 派车计划写入redis
truck_dispatch_to_redis(request_truck_id, group_id, target_excavator)
# except Exception as es:
# logger.error(" ")
# logger.error(es)
# session_mysql.rollback()
# session_postgre.rollback()
# return jsonify(msg="未知异常, 请联系管理员", code=504)
logger.info("#####################################请求调度更新结束#####################################")
# 调度结束时间
rtd_end_time = datetime.now()
print(f'调度时耗 {rtd_end_time - rtd_start_time}')
return jsonify(msg="success", code=0)
def area_choose(excavators_id, closer_area_id, further_area_id, lane_set,
logger, truck, truck_locates_dict):
"""
两装载区均不空闲,执行二次调度
:param excavators_id: 挖机集合
:param closer_area_id: 近端装载区id
:param further_area_id: 远端装载区id
:param lane_set: 近端及远端装载区间路段集合
:param logger: 日志器
:param truck: 车辆对象
:param truck_locates_dict: 车辆位置
:return: target_excavator
"""
logger.info("excavator_hold_truck_list")
logger.info(truck.excavator_hold_truck_list)
logger.info(list(excavators_id)[0])
logger.info(list(excavators_id)[1])
logger.info(truck.excavator_hold_truck_list[list(excavators_id)[0]])
logger.info(truck.excavator_hold_truck_list[list(excavators_id)[1]])
# 统计驶往两装载区的车辆
arrival_truck_set = truck.excavator_hold_truck_list[list(excavators_id)[0]] \
+ truck.excavator_hold_truck_list[list(excavators_id)[1]]
# 统计车辆抵达时间
arrival_truck_reach_time = [truck.cur_truck_reach_excavator[truck.truck_uuid_to_index_dict[truck_id]] for \
truck_id in arrival_truck_set]
# arrival_truck_set = ['309705a0-5ddf-4559-b6c4-ee17a57677ad', '899705a0-5ddf-4559-b6c4-ee17a57677ad']
#
# arrival_truck_reach_time = [8.04, 6.05]
logger.info("arrival_truck_reach_time")
logger.info(arrival_truck_reach_time)
logger.info("arrival_truck_set")
logger.info(arrival_truck_set)
arrival_truck_list = list(zip(np.array(arrival_truck_set), np.array(arrival_truck_reach_time)))
arrival_truck_list = sorted(arrival_truck_list, key=lambda item: item[1])
logger.info("arrival_truck_list")
logger.info(arrival_truck_list)
logger.info("arrival_truck_list")
logger.info(arrival_truck_list)
# 统计不同状态车辆数量
goto_closer_area_num = 0
goto_further_area_num = 0
for truck_id, reach_time in arrival_truck_list:
if truck_id in truck_locates_dict:
truck_lane_id = truck_locates_dict[truck_id]
# 车辆已经经过近端装载区
if truck_lane_id in lane_set:
# 前往远端装载区车辆数加1
goto_further_area_num += 1
# 车辆未经过近端装载区
else:
# 前往近端或近端装载区车辆数加1
goto_closer_area_num += 1
else:
continue
# goto_further_area_num -= 1
logger.info("goto_further_area_num-goto_closer_area_num")
logger.info(goto_further_area_num)
logger.info(goto_closer_area_num)
# 默认当前请调车辆与近端装载点前没有车辆,因此前往近端装载区的车辆仅其本身
goto_closer_area_num = 1
# 在远处排队等待的车辆更少
if goto_closer_area_num > goto_further_area_num:
logger.info("远端挖机排队时间短, 调度车辆前往")
target_excavator = DispatchInfo.load_excavator_dict[further_area_id]
# truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[further_area_id])
else:
logger.info("近端挖机排队时间短, 调度车辆前往")
target_excavator = DispatchInfo.load_excavator_dict[closer_area_id]
# truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[closer_area_id])
return target_excavator
def area_analysis(load_area_uuid):
"""
Analysis which area is closer.
:param load_area_uuid:
:return: closer_area_uuid, further_area_uuid
"""
try:
excavator_uuid_to_load_area_uuid_dict = get_value("excavator_uuid_to_load_area_uuid_dict")
load_area_uuid = list(load_area_uuid)
load_area_uuid[0] = excavator_uuid_to_load_area_uuid_dict[load_area_uuid[0]]
load_area_uuid[1] = excavator_uuid_to_load_area_uuid_dict[load_area_uuid[1]]
distance_a = session_postgre.query(WalkTimePark)\
.filter_by(load_area_id=load_area_uuid[0]).first().park_load_distance
distance_b = session_postgre.query(WalkTimePark)\
.filter_by(load_area_id=load_area_uuid[1]).first().park_load_distance
if distance_a > distance_b:
return load_area_uuid[1], load_area_uuid[0]
else:
return load_area_uuid[0], load_area_uuid[1]
except Exception as es:
logger.error("装载区距离分析异常")
logger.error(es)
return load_area_uuid[0], load_area_uuid[1]
def truck_pass_first_area(truck_id, lane_id, closer_entrance_node_id, further_entrance_node_id):
"""
Truck has gone through the first area.
:param truck_id:
:param lane_id:
:param closer_entrance_node_id:
:param further_entrance_node_id:
:return:
"""
# try:
def backtracking(root_node):
from collections import deque
que = deque([root_node])
while que:
size = len(que)
for _ in range(size):
cur_node = que.popleft()
if cur_node is None:
continue
logger.info(cur_node)
if cur_node == closer_entrance_node_id:
logger.info("closer_entrance_node")
return 0
if cur_node == further_entrance_node_id:
logger.info("further_entrance_node")
return 1
for item in session_postgre.query(Lane).filter_by(StartNodeId=cur_node).all():
if item:
que.append(item.EndNodeId)
node_id = session_postgre.query(Lane).filter_by(Id=lane_id).first().EndNodeId
if backtracking(root_node=node_id) == 0:
return True
else:
return False
# except Exception as es:
# logger.error("车辆行驶位置判断异常")
# logger.error(es)
# return True
def get_trucks_locate():
"""
get trucks locates.
:return: truck_locate_dict
"""
try:
truck_name_to_uuid_dict = get_value("truck_name_to_uuid_dict")
truck_locate_dict = {}
device_name_set = redis2.keys()
for item in device_name_set:
item = item.decode(encoding='utf-8')
key_value_dict = redis2.hgetall(item)
if str_to_byte('type') in key_value_dict:
device_type = key_value_dict[str_to_byte('type')]
is_online = key_value_dict[str_to_byte('online')]
key_set = key_value_dict.keys()
if (device_type == str_to_byte("1")) \
and (str_to_byte('online') in key_set) \
and (bytes.decode(is_online) in ["true" or "True"]) \
and (str_to_byte('laneId') in key_set):
truck_locate = key_value_dict[str_to_byte('laneId')]
# logger.error(item)
# logger.error(eval(truck_locate))
if eval(truck_locate) is not '':
truck_locate_dict[truck_name_to_uuid_dict[item]] = eval(truck_locate)
logger.error(truck_locate_dict)
else:
continue
return truck_locate_dict
except Exception as es:
logger.error("车辆所在路段读取异常")
logger.error(es)
return {}
def truck_dispatch_to_redis(truck_id, group_id, excavator_id):
"""
write truck dispatch to redis.
:param truck_id:
:param group_id:
:param excavator_id:
:return:
"""
# 查询车辆相关派车计划
record = {}
try:
# dump_id = DispatchInfo.unload_area_dump_dict[unload_area_id]
item = (session_mysql.query(DispatchSetting).filter_by(exactor_id=excavator_id, group_id=group_id,
isdeleted=0, ).first())
if item is None:
raise Exception("调度计划配置异常")
except Exception as es:
item = (session_mysql.query(DispatchSetting).filter_by(group_id=group_id, isdeleted=0, ).first())
logger.error(es)
# 其余调度信息写入
try:
# record["dispatchId"] = item.id
record["dispatchId"] = str(uuid.uuid1())
record["exactorId"] = item.exactor_id
record["loadAreaId"] = item.load_area_id
record["dumpId"] = item.dump_id
record["unloadAreaId"] = item.unload_area_id
record["groupId"] = group_id
record["isdeleted"] = False
record["isTemp"] = False
record["haulFlag"] = -1
record["groupName"] = DispatchInfo.group_name[group_id]
logger.info(f'{truck_id} redis 注入 {record}')
except Exception as es:
logger.error("调度结果写入异常-矿卡空载")
logger.error(es)
finally:
redis5.set(truck_id, str(json.dumps(record)))
def get_lanes_between_entrances(closer_node_id, further_node_id):
"""
get lanes between two entrance nodes.
:param closer_node_id:
:param further_node_id:
:return: lane set
"""
try:
max_find_it = 100
next_node_id = closer_node_id
lane_set = []
while max_find_it > 0 and next_node_id != further_node_id:
item = session_postgre.query(Lane).filter_by(StartNodeId=next_node_id, Type=2).first()
if item:
next_lane_id = item.Id
next_node_id = item.EndNodeId
lane_set.append(next_lane_id)
max_find_it -= 1
max_find_it -= 1
return lane_set
except Exception as es:
logger.error("获取装载区间路段异常")
logger.error(es)
return []
def get_excavator_state(excavator_id):
"""
get group_excavators state.
:param excavator_id:
:return: state
"""
try:
logger.error(excavator_id)
device_name = session_mysql.query(Equipment).filter_by(id=excavator_id, device_type=2).first().device_name
key_value_dict = redis2.hgetall(device_name)
if str_to_byte('online') in key_value_dict:
is_online = key_value_dict[str_to_byte('online')]
else:
logger.warning(f'挖机 {device_name} 不在线')
return 0
key_set = key_value_dict.keys()
state = 100
if (str_to_byte('online') in key_set) and (bytes.decode(is_online) in ["true" or "True"]):
if str_to_byte('workState') in key_set:
state = key_value_dict[str_to_byte('workState')]
else:
logger.warning(f'挖机 {device_name} 状态未知')
return 0
return int(float(byte_to_str(state)))
except Exception as es:
logger.error("挖机状态读取异常")
logger.error(es)
return 0
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment