Commit e509f495 authored by 张晓彤's avatar 张晓彤

Merge branch 'master' of github.com:Allvey/integrated-scheduling-v4

parents 4de7cc31 8d18fe04
No preview for this file type
......@@ -2,3 +2,4 @@
/.idea/
/Logs/
/waytous/
*.pyc
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/5/30 16:32
# @Author : Opfer
# @Site :
# @File : alg.py
# @Software: PyCharm
from para_config import *
from equipment import ExcavatorInfo, DumpInfo, TruckInfo
from data.dispatchInfo import DispatchInfo
# from core.group import Group
from core.schedule import PreSchedule
class AlgorithmBase:
"""
Base class for dispatch alg.
"""
def __init__(self):
pass
def solve(self, *args, **kwargs):
"""
Dispatching calculation for subgroups.
"""
raise NotImplementedError
class Congestion(AlgorithmBase):
"""
class for congestion alg.
"""
def __init__(self, group, truck, pre_sch):
super().__init__()
self.group = group
self.truck = truck
self.pre_sch = pre_sch
self.logger = get_logger("zxt.algorithm.congestion")
def solve(self, truck_id):
"""
Receive a truck_id and calculate the associated route congestion.
:param truck_id: (uuid)
:return: congestion_value
"""
try:
truck_index = self.truck.truck_uuid_to_index_dict[truck_id]
trip = self.truck.get_truck_current_trip()[truck_index]
task = self.truck.get_truck_current_task()[truck_id]
group_dynamic_excavator_num = len(self.group.dump)
group_dynamic_dump_num = len(self.group.excavator)
except Exception as es:
self.logger.error("车辆调度信息读取异常")
self.logger.error(es)
if task == -2:
################################################ 矿卡启动 ###############################################
try:
self.logger.info("矿卡状态:矿卡启动或故障恢复")
self.logger.info(f"涉及挖机:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
transport_value = self.group.park_to_excavator_congestion
except Exception as es:
transport_value = np.zeros(group_dynamic_excavator_num)
self.logger.info(es)
if task in [0, 1, 2]:
################################################ 矿卡空载 ###############################################
try:
self.logger.info("矿卡状态:矿卡空载")
self.logger.info(f"涉及卸载设备:{list(DumpInfo.dump_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 车辆所在挖机 uuid
excavator_id = DeviceMap.excavator_index_to_uuid_dict[int(trip[1])]
# 挖机所在分组序号 index
excavator_group_index = self.group.excavator_uuid_index_dict[excavator_id]
transport_value = self.group.to_dump_congestion[excavator_group_index, :]
except Exception as es:
self.logger.error("矿卡空载调度异常")
self.logger.error(es)
transport_value = np.zeros(group_dynamic_dump_num)
elif task in [3, 4, 5]:
################################################ 矿卡重载 ###############################################
try:
self.logger.info("矿卡状态:矿卡重载")
self.logger.info(f"涉及挖机设备:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 车辆所在卸点
dump_id = DeviceMap.dump_index_to_uuid_dict[int(trip[1])]
# 卸点对应分组编号
dump_group_index = self.group.dump_uuid_index_dict[dump_id]
transport_value = self.group.to_excavator_congestion[dump_group_index, :]
except Exception as es:
self.logger.error("矿卡重载调度异常")
self.logger.error(es)
transport_value = np.zeros(group_dynamic_excavator_num)
return transport_value
class ExpectedTime(AlgorithmBase):
"""
class for expected traveling time alg.
"""
def __init__(self, group, truck, pre_sch):
super().__init__()
self.group = group
self.truck = truck
self.pre_sch = pre_sch
self.logger = get_logger("zxt.algorithm.expected")
def solve(self, truck_info):
"""
Receive a truck_id and calculate the associated route travelling time.
:param truck_info: (current truck obj)
:return: travel_time_value
"""
try:
# truck_index = self.truck.truck_uuid_to_index_dict[truck_id]
# trip = self.truck.get_truck_current_trip()[truck_index]
#
# task = self.truck.get_truck_current_task()[truck_id]
truck_id = truck_info.get_truck_id()
truck_index = self.truck.truck_uuid_to_index_dict[truck_id]
# task = truck_task
# trip = truck_trip
trip = truck_info.get_trip()
task = truck_info.get_task()
truck_avl_time = self.pre_sch.get_truck_avl_time(truck_id=truck_id)
group_dynamic_excavator_num = len(self.group.excavator)
group_dynamic_unload_area_num = len(self.group.unload_area)
except Exception as es:
self.logger.error("车辆调度信息读取异常")
self.logger.error(es)
if task == -2:
################################################ 矿卡启动 ###############################################
try:
self.logger.info("矿卡状态:矿卡启动或故障恢复")
self.logger.info(f"涉及挖机:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
# try:
# 挖机可用时间
excavator_val_time_global = self.pre_sch.get_excavator_avl_time()
excavator_val_time = np.full(len(self.group.excavator), 0)
for excavator_id, excavator_index in self.group.excavator_uuid_index_dict.items():
excavator_val_time[excavator_index] = excavator_val_time_global[excavator_id]
# 车辆驶往各目的地时间
truck_reach_time = 60 * self.group.park_to_excavator_distance[0, :] / 1000 / \
self.truck.empty_speed[truck_id] + truck_avl_time
# 计算车辆得到服务时间
truck_service_time = np.maximum(truck_reach_time, excavator_val_time)
# 计算行程时间
transport_value = truck_service_time - truck_avl_time
self.logger.info("expected_travelling_schedule-truck_avl_time")
self.logger.info(truck_avl_time)
self.logger.info("expected_travelling_schedule-truck_service_time")
self.logger.info(truck_service_time)
self.logger.info("expected_travelling_schedule-truck_reach_time")
self.logger.info(truck_reach_time)
self.logger.info("expected_travelling_schedule-excavator_val_time")
self.logger.info(excavator_val_time)
# except Exception as es:
# self.logger.error("矿卡启动调度异常")
# self.logger.error(es)
# transport_value = np.zeros(group_dynamic_excavator_num)
if task in [0, 1, 2]:
################################################ 矿卡空载 ###############################################
try:
self.logger.info("矿卡状态:矿卡空载")
self.logger.info(f"涉及卸载设备:{list(DeviceMap.dump_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 全局卸点可用时间 dict
dump_val_time_global = self.pre_sch.get_dump_avl_time()
# 局部卸点可用时间 list
dump_val_time = np.full(len(self.group.unload_area), 0)
bb = self.group.dump_uuid_index_dict
for dump_id, dump_index in self.group.dump_uuid_index_dict.items():
dump_val_time[dump_index] = dump_val_time_global[dump_id]
# 车辆所在挖机 uuid
excavator_id = DeviceMap.excavator_index_to_uuid_dict[int(trip[1])]
# 挖机所在分组序号 index
excavator_group_index = self.group.excavator_uuid_index_dict[excavator_id]
# 车辆驶往各目的地时间
truck_reach_time = 60 * self.group.to_unload_area_distance[excavator_group_index, :] \
/ 1000 / self.truck.heavy_speed[truck_id] + truck_avl_time
# 车辆得到服务时间
truck_service_time = np.maximum(truck_reach_time, dump_val_time)
# 计算行程时间
transport_value = truck_service_time - truck_avl_time
self.logger.info("expected_travelling_schedule-truck_avl_time")
self.logger.info(truck_avl_time)
self.logger.info("expected_travelling_schedule-truck_service_time")
self.logger.info(truck_service_time)
self.logger.info("expected_travelling_schedule-truck_reach_time")
self.logger.info(truck_reach_time)
self.logger.info("expected_travelling_schedule-dump_val_time")
self.logger.info(dump_val_time)
except Exception as es:
self.logger.error("矿卡空载调度异常")
self.logger.error(es)
transport_value = np.zeros(group_dynamic_unload_area_num)
elif task in [3, 4, 5]:
################################################ 矿卡重载 ###############################################
try:
self.logger.info("矿卡状态:矿卡重载")
self.logger.info(f"涉及挖机设备:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 挖机可用时间
excavator_val_time_global = self.pre_sch.get_excavator_avl_time()
excavator_val_time = np.full(len(self.group.excavator), 0)
for excavator_id, excavator_index in self.group.excavator_uuid_index_dict.items():
excavator_val_time[excavator_index] = excavator_val_time_global[excavator_id]
# 车辆所在卸点
dump_id = DeviceMap.dump_index_to_uuid_dict[int(trip[1])]
# 卸载区域id
unload_area_id = DispatchInfo.dump_unload_area_dict[dump_id]
# 卸点对应分组编号
unload_area_group_index = self.group.unload_area_uuid_index_dict[unload_area_id]
# 车辆驶往各目的地时间
truck_reach_time = 60 * self.group.to_excavator_distance[unload_area_group_index, :] \
/ 1000 / self.truck.empty_speed[truck_id] + truck_avl_time
# 计算车辆得到服务时间
truck_service_time = np.maximum(truck_reach_time, excavator_val_time)
# 计算行程时间
transport_value = truck_service_time - truck_avl_time
except Exception as es:
self.logger.error("矿卡重载调度异常")
self.logger.error(es)
transport_value = np.zeros(group_dynamic_unload_area_num)
return transport_value
class DistributionRatio(object):
"""
@date:2022/7/19 8:49
@author:maqc
@para:
truck_id:分流配比模式下,对应的卡车id
excavator_id:该卡车对应的电铲id
@return:{truck_id:unload_area_id}
@desc:计算分流配比模式下,卡车与卸载区的对应关系
"""
def __init__(self, exactor_id):
self.exactor_id = exactor_id
self.exactor_truck_num = DispatchInfo.get_exactor_truck_nums(exactor_id) # 获取该电铲下的卡车数量
self.exactor_unload_match = DispatchInfo.get_exactor_unload_match(exactor_id) # 获取电铲对应的所有卸载区id
self.unload_ratio = {}
self.logger = get_logger("mqc.DistributionRatio")
def get_unload_ratio(self):
"""
@date:2022/7/19 15:21
@author:maqc
@desc:初始化卸载区的比值
"""
ratio = 0
for value in self.exactor_unload_match:
ratio += DispatchInfo.unload_rate_dict[value]
for item in self.exactor_unload_match:
self.unload_ratio[item] = DispatchInfo.unload_rate_dict[item] / ratio
def get_unload_truck_num(self, unload_area_id):
"""
@date:2022/7/19 16:12
@author:maqc
@desc:计算正在派往当前卸载区的卡车数量
"""
item = session_mysql.query(EquipmentPair).filter_by(unload_area_id=unload_area_id, isdeleted=0).all()
return len(item)
def get_next_unload_id(self):
"""
@date:2022/7/19 15:39
@author:maqc
@desc:计算卡车与下一个卸载区的对应关系
"""
# 无论当前卡车是否在备停区,下一个卸载区选择比值最大值对应的区域
try:
temp = list(self.unload_ratio.values())
next_unload_id = list(self.unload_ratio.keys())[temp.index(max(temp))]
# 更新卸载区对应的比例值
self.logger.info(f"下一个卸载区对应的id:{next_unload_id}")
self.unload_ratio[next_unload_id] -= self.get_unload_truck_num(
next_unload_id) / self.exactor_truck_num
self.logger.info(f"当前卸载区对应的比值:{self.unload_ratio[next_unload_id]}")
except Exception as es:
self.logger.error("卡车与下一个卸载区的配对关系异常")
self.logger.error(es)
return next_unload_id
def ratio_main(self):
"""
@date:2022/7/19 9:10
@author:maqc
@desc:分流配比模式类函数主入口
"""
try:
self.get_unload_ratio()
next_unload_area_id = self.get_next_unload_id()
self.logger.info(f'当前卡车对应的卸载区:{next_unload_area_id}')
except Exception as es:
self.logger.error("分流配比主函数异常")
self.logger.error(es)
return next_unload_area_id
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/1/5 14:14
# @Author : Opfer
# @Site :
# @File : algorithm.py
# @Software: PyCharm
from para_config import *
from equipment.truck import TruckInfo
from equipment.dump import DumpInfo
from equipment.excavator import ExcavatorInfo
class ScheduleAlg(WalkManage):
""" class for the schedule algorithm.
Description:
根据设备状态计算调度价值
Attribute:
equipment class: truck, excavator, dump, group
"""
def __init__(self, dump, excavator, truck, group, pre_sch):
self._dump = dump
self._excavator = excavator
self._truck = truck
self._group = group
# 获取日志器
self.logger = get_logger("zxt.alg")
# 行程预测对象
self._pre_sch = pre_sch
def truck_schedule(self, current_truck, alg):
"""
计算矿卡驶往各目的地的调度价值
:param truck_id: 待调度矿卡uuid
:param alg: 启用的调度算法
:return: 调度价值
"""
transport_value = None
try:
if alg == "congestion":
transport_value = self.congestion_schedule(current_truck)
elif alg == "traffic_plan":
transport_value = self.traffic_plan_schedule(current_truck)
elif alg == "saturation":
transport_value = self.saturation_schedule(current_truck)
elif alg == "expected":
transport_value = self.expected_travelling_schedule(current_truck)
else:
return None
except Exception as es:
self.logger.error("调度算法计算异常")
self.logger.error(es)
return transport_value
def congestion_schedule(self, current_truck):
"""
计算车辆驶往各目的地的拥堵度
:param current_truck: 请求调度
:return: transport_value
"""
transport_value = None
truck_id = current_truck.get_truck_id()
group_id = current_truck.get_group_id()
task = current_truck.get_task()
trip = current_truck.get_trip()
dynamic_excavator_num = get_value("dynamic_excavator_num")
dynamic_dump_num = get_value("dynamic_dump_num")
if task == -2:
################################################ 矿卡启动 ###############################################
try:
self.logger.info("矿卡状态:矿卡启动或故障恢复")
self.logger.info(f"涉及挖机:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
transport_value = self._group.group_park_to_excavator[group_id]
except Exception as es:
transport_value = np.zeros(dynamic_excavator_num)
self.logger.info(es)
if task in [0, 1, 2]:
################################################ 矿卡空载 ###############################################
try:
self.logger.info("矿卡状态:矿卡空载")
self.logger.info(f"涉及卸载设备:{list(DumpInfo.dump_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
excavator_index = int(trip[1])
try:
transport_value = self._group.group_walk_to_dump_cost[group_id][:, excavator_index]
except Exception as es:
transport_value = np.zeros(dynamic_dump_num)
self.logger.error(es)
elif task in [3, 4, 5]:
################################################ 矿卡重载 ###############################################
try:
self.logger.info("矿卡状态:矿卡重载")
self.logger.info(f"涉及挖机设备:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 正常调度
dump_index = int(trip[1])
transport_value = self._group.group_walk_to_excavator_cost[group_id][dump_index, :]
except Exception as es:
transport_value = np.zeros(dynamic_excavator_num)
self.logger.info(es)
return transport_value
def expected_travelling_schedule(self, current_truck):
"""
车辆驶往各目的地预计行驶时间
:param current_truck: 请求调度车辆信息
:return: transport_value
"""
transport_value = None
truck_id = current_truck.get_truck_id()
group_id = current_truck.get_group_id()
task = current_truck.get_task()
trip = current_truck.get_trip()
dynamic_excavator_num = get_value("dynamic_excavator_num")
dynamic_dump_num = get_value("dynamic_dump_num")
# 车辆可用时间
truck_avl_time = self._pre_sch.get_truck_avl_time(truck_id=truck_id)
if task == -2:
################################################ 矿卡启动 ###############################################
try:
self.logger.info("矿卡状态:矿卡启动或故障恢复")
self.logger.info(f"涉及挖机:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
# try:
# 挖机可用时间
excavator_val_time = self._group.update_excavator_avl_time(self._pre_sch.get_excavator_avl_time())[group_id]
# 车辆驶往各目的地时间
truck_reach_time = 60 * self._group.group_park_to_excavator[group_id][0, :] / 1000 / \
self._truck.empty_speed[truck_id] + truck_avl_time
# 计算车辆得到服务时间
truck_service_time = np.maximum(truck_reach_time, excavator_val_time)
# 计算行程时间
transport_value = truck_service_time - truck_avl_time
self.logger.info("expected_travelling_schedule-truck_avl_time")
self.logger.info(truck_avl_time)
self.logger.info("expected_travelling_schedule-truck_service_time")
self.logger.info(truck_service_time)
self.logger.info("expected_travelling_schedule-truck_reach_time")
self.logger.info(truck_reach_time)
self.logger.info("expected_travelling_schedule-excavator_val_time")
self.logger.info(excavator_val_time)
# except Exception as es:
# transport_value = np.zeros(dynamic_excavator_num)
# self.logger.info(es)
if task in [0, 1, 2]:
################################################ 矿卡空载 ###############################################
try:
self.logger.info("矿卡状态:矿卡空载")
self.logger.info(f"涉及卸载设备:{list(DeviceMap.dump_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
# try:
# 卸点可用时间
dump_val_time = self._group.update_dump_avl_time(self._pre_sch.get_dump_avl_time())[group_id]
# 车辆所在挖机
excavator_id = DeviceMap.excavator_index_to_uuid_dict[int(trip[1])]
# 挖机对应分组编号
excavator_group_index = self._group.group_excavator_uuid_to_index_dict[group_id][excavator_id]
# 车辆驶往各目的地时间
truck_reach_time = 60 * self._group.group_walk_to_dump_cost[group_id][excavator_group_index, :] \
/ 1000 / self._truck.heavy_speed[truck_id] + truck_avl_time
# 计算车辆得到服务时间
truck_service_time = np.maximum(truck_reach_time, dump_val_time)
# 计算行程时间
transport_value = truck_service_time - truck_avl_time
self.logger.info("expected_travelling_schedule-truck_avl_time")
self.logger.info(truck_avl_time)
self.logger.info("expected_travelling_schedule-truck_service_time")
self.logger.info(truck_service_time)
self.logger.info("expected_travelling_schedule-truck_reach_time")
self.logger.info(truck_reach_time)
self.logger.info("expected_travelling_schedule-dump_val_time")
self.logger.info(dump_val_time)
# except Exception as es:
# transport_value = np.zeros(dynamic_dump_num)
# self.logger.error(es)
elif task in [3, 4, 5]:
################################################ 矿卡重载 ###############################################
try:
self.logger.info("矿卡状态:矿卡重载")
self.logger.info(f"涉及挖机设备:{list(DeviceMap.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 挖机可用时间
excavator_val_time = self._group.update_excavator_avl_time(self._pre_sch.get_excavator_avl_time())[group_id]
# 车辆所在卸点
dump_id = DeviceMap.dump_index_to_uuid_dict[int(trip[1])]
# 卸点对应分组编号
dump_group_index = self._group.group_dump_uuid_to_index_dict[group_id][dump_id]
# 车辆驶往各目的地时间
truck_reach_time = 60 * self._group.group_walk_to_excavator_cost[group_id][dump_group_index, :] \
/ 1000 / self._truck.empty_speed[truck_id] + truck_avl_time
# 计算车辆得到服务时间
truck_service_time = np.maximum(truck_reach_time, excavator_val_time)
# 计算行程时间
transport_value = truck_service_time - truck_avl_time
except Exception as es:
transport_value = np.zeros(dynamic_dump_num)
self.logger.error(es)
return transport_value
# def traffic_plan_schedule(self, current_truck):
#
# traffic_value = None
#
# truck_id = current_truck.get_truck_id()
#
# group_id = current_truck.get_group_id()
#
# task = current_truck.get_task()
#
# trip = current_truck.get_trip()
#
# if task in [0, 1, 2]:
#
# excavator_index = int(trip[1])
# excavator_id = self._excavator.excavator_index_to_uuid_dict[excavator_index]
#
# group_excavator_index = self._group.group_excavator_uuid_to_index_dict[group_id][excavator_id]
#
# try:
#
# # 计算 group actual traffic flow
# group_actual_goto_dump_traffic_flow = self._group.group_actual_goto_dump_traffic_flow[
# group_id]
#
# # 计算 group actual traffic flow
# group_opt_goto_dump_traffic_flow = self._group.group_opt_goto_dump_traffic_flow[group_id]
#
# self.logger.info("驶往卸点分组车流")
# self.logger.info(group_actual_goto_dump_traffic_flow)
# self.logger.info(group_opt_goto_dump_traffic_flow)
#
# try:
# traffic_value = (group_actual_goto_dump_traffic_flow[group_excavator_index, :] + 0.001) \
# / (group_opt_goto_dump_traffic_flow[group_excavator_index, :] + 0.001)
# except Exception as es:
# self.logger.error("error09")
# self.logger.error(es)
#
# except Exception as es:
# self.logger.error("error11")
# self.logger.error(es)
# self.logger.info("traffic_value")
# self.logger.info(traffic_value)
# self.logger.info("dump_material_bind_modify")
# self.logger.info(self._truck.dump_material_bind_modify[self.truck_uuid_to_index_dict[truck_id]])
#
# elif task in [3, 4, 5]:
#
# dump_index = int(trip[1])
# dump_id = self._dump.dump_uuid_to_index_dict[dump_index]
#
# group_dump_index = self._group.group_dump_uuid_to_index_dict[group_id][dump_id]
#
# # 提取group actual traffic flow
# group_actual_goto_excavator_traffic_flow = self._group.group_actual_goto_excavator_traffic_flow[
# group_id]
#
# # 提取group actual traffic flow
# group_opt_goto_excavator_traffic_flow = self._group.group_opt_goto_excavator_traffic_flow[
# group_id]
#
# self.logger.info("驶往挖机分组车流")
# self.logger.info(group_actual_goto_excavator_traffic_flow)
# self.logger.info(group_opt_goto_excavator_traffic_flow)
#
# traffic_value = (group_actual_goto_excavator_traffic_flow[group_dump_index, :] + 0.001) \
# / (group_opt_goto_excavator_traffic_flow[group_dump_index, :] + 0.001)
#
# # transport_value = (self.actual_goto_excavator_traffic_flow[trip[1], :] + 0.001) \
# # / (self.opt_goto_excavator_traffic_flow[trip[1], :] + 0.001)
# self.logger.info("traffic_value")
# self.logger.info(traffic_value)
#
# return traffic_value
def saturation_schedule(self, current_truck):
transport_value = None
group_id = current_truck.get_group_id()
task = current_truck.get_task()
trip = current_truck.get_trip()
if task == -2:
self.logger.info("饱和度调度")
transport_value = self._group.group_park_to_excavator[group_id]
excavator_hold_truck = self._group.update_excavator_hold_truck(self._truck.excavator_hold_truck_num)[
group_id]
# print(self._truck.payload)
# print(excavator_hold_truck)
# print(self._group.group_park_to_excavator[group_id].reshape(1, -1).flatten())
actual_flow_to_excavator = excavator_hold_truck * np.mean(self._truck.payload) / \
self._group.group_park_to_excavator[group_id].reshape(1, -1).flatten()
allow_flow_to_excavator = self._group.update_allow_flow_to_excavator()[group_id]
# 产量饱和度
saturation_value = 1 - (actual_flow_to_excavator + 0.01) / (allow_flow_to_excavator + 0.01)
# # 若产量欠饱和度异常小于0, 设为一个极小正值
# for val in flow_saturation.flatten():
# if val <= 0:
# val = 1 / M
#
# # 饱和度价值为产量饱和度与行驶成本之比值,行驶成本越小,欠缺饱和度越大,饱和度价值越大
# saturation_value = flow_saturation / transport_value
self.logger.info(f'实际车流 {actual_flow_to_excavator}')
# self.logger.info(actual_flow_to_excavator)
self.logger.info(f'最大车流 {allow_flow_to_excavator}')
# self.logger.info(allow_flow_to_excavator)
self.logger.info(f'行驶成本 {transport_value}')
# self.logger.info(transport_value)
self.logger.info(f'饱和度价值 {saturation_value}')
# self.logger.info(saturation_value)
return saturation_value
if task in [0, 1, 2]:
self.logger.info("饱和度调度")
excavator_index = int(trip[1])
transport_value = self._group.group_walk_to_dump_cost[group_id][:, excavator_index].reshape(1, -1)
dump_hold_truck = self._group.update_dump_hold_truck(self._truck.dump_hold_truck_num)[group_id]
actual_flow_to_dump = dump_hold_truck * np.mean(self._truck.payload) / \
self._group.group_walk_to_dump_cost[group_id][:, excavator_index].reshape(1, -1)
# allow_flow_to_dump = self.dump.dump_strength
allow_flow_to_dump = self._group.update_allow_flow_to_dump()[group_id]
# saturation_value = (1 - (actual_flow_to_dump + 0.01) / (allow_flow_to_dump + 0.01)) / transport_value
# 产量饱和度
saturation_value = 1 - (actual_flow_to_dump + 0.01) / (allow_flow_to_dump + 0.01)
# # 若产量欠饱和度异常小于0, 设为一个极小正值
# for val in flow_saturation.flatten():
# if val <= 0:
# val = 1 / M
#
# # 饱和度价值为产量饱和度与行驶成本之比值,行驶成本越小,欠缺饱和度越大,饱和度价值越大
# saturation_value = flow_saturation / transport_value
self.logger.info(f'实际车流 {actual_flow_to_dump}')
# self.logger.info(actual_flow_to_excavator)
self.logger.info(f'最大车流 {allow_flow_to_dump}')
# self.logger.info(allow_flow_to_excavator)
self.logger.info(f'行驶成本 {transport_value}')
# self.logger.info(transport_value)
self.logger.info(f'饱和度价值 {saturation_value}')
# self.logger.info(saturation_value)
return saturation_value
if task in [3, 4, 5]:
self.logger.info("饱和度调度")
dump_index = int(trip[1])
transport_value = self._group.group_walk_to_excavator_cost[group_id][dump_index, :].reshape(1, -1)
excavator_hold_truck = self._group.update_excavator_hold_truck(self._truck.excavator_hold_truck_num)[
group_id]
actual_flow_to_excavator = excavator_hold_truck * np.mean(self._truck.payload) / \
self._group.group_walk_to_excavator_cost[group_id][dump_index, :].reshape(1, -1)
allow_flow_to_excavator = self._group.update_allow_flow_to_excavator()[group_id]
# saturation_value = (1 - actual_flow_to_excavator / allow_flow_to_excavator) / transport_value
# 产量饱和度
saturation_value = 1 - (actual_flow_to_excavator + 0.01) / (allow_flow_to_excavator + 0.01)
# # 饱和度价值为产量饱和度与行驶成本之比值,行驶成本越小,欠缺饱和度越大,饱和度价值越大
# saturation_value = flow_saturation
self.logger.info(f'实际车流 {actual_flow_to_excavator}')
# self.logger.info(actual_flow_to_excavator)
self.logger.info(f'最大车流 {allow_flow_to_excavator}')
# self.logger.info(allow_flow_to_excavator)
self.logger.info(f'行驶成本 {transport_value}')
# self.logger.info(transport_value)
self.logger.info(f'饱和度价值 {saturation_value}')
# self.logger.info(saturation_value)
return saturation_value
......@@ -4,8 +4,12 @@ from para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
from dispatcher import Dispatcher, PreSchedule, DispatchSubmission
from core.dispatcher import Dispatcher, PreSchedule
from core.group import Group
from flask_caching import Cache
from alg.algorithm import ExpectedTime
from data.dispatchInfo import DispatchInfo
from core.dispatcher import DispatchSubmission
config = {
"DEBUG": True, # some Flask specific configs
......@@ -35,6 +39,9 @@ def dispatch_request():
# 获取日志器
logger = get_logger("zxt.request")
# 更新周期参数
logger.info("#####################################请求调度更新开始#####################################")
try:
# 清空数据库缓存
......@@ -47,7 +54,7 @@ def dispatch_request():
except Exception as es:
logger.error("数据库访问异常")
logger.error(es)
return jsonify(msg="未知异常, 请联系管理员", code=506)
return jsonify(msg="未知异常, 请联系管理员", code=501)
try:
......@@ -55,62 +62,109 @@ def dispatch_request():
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()
if group_id not in DispatchInfo.group_set:
raise Exception("请求调度分组不存在")
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()
# 实例化调度预测器
pre_sch = PreSchedule(truck, excavator, dump)
# 实例化矿卡调度器
dispatcher = Dispatcher(dump, excavator, truck, pre_sch, True)
# 实例化输出器
submission = DispatchSubmission(dump, excavator, truck)
# 实例化调度分组
group = Group(group_id, truck, pre_sch)
# 更新调度分组信息
group.info_update()
# 周期更新
dispatcher.dispatcher_period_update()
except Exception as es:
logger.error("参数更新异常")
logger.error("对象实例化异常")
logger.error(es)
session_mysql.rollback()
session_postgre.rollback()
return jsonify(msg="未知异常, 请联系管理员", code=505)
return jsonify(msg="未知异常, 请联系管理员", code=504)
request_trucks = []
try:
request_trucks = dispatcher.group.group_dispatch_truck[group_id]
# 调度分组派车计划计算
try:
truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime)
except Exception as es:
logger.error(es)
return jsonify(msg="未知异常, 请联系管理员", code=504)
logger.error(f'分组{group.group_id} 调度计算异常')
try:
# 更新周期参数
logger.info("#####################################请求调度更新开始#####################################")
if get_value("dynamic_dump_num") * get_value("dynamic_excavator_num") == 0:
# raise Exception("无动态派车计划可用")
return jsonify(msg="未知异常, 请联系管理员", code=503)
if get_value("dynamic_truck_num") == 0:
# raise Exception("无动态派车可用矿卡")
return jsonify(msg="未知异常, 请联系管理员", code=502)
# 更新请调矿卡派车计划
for truck_id in request_trucks:
# 调度计算
dispatcher.truck_request(truck_id)
logger.info("#####################################请求调度更新结束#####################################")
logger.info(f'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}')
submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict)
except Exception as es:
logger.error(es)
logger.error(f'分组{group.group_id} 调度写入异常')
except Exception as es:
logger.error("最外层异常捕获")
logger.error(es)
return jsonify(msg="未知异常, 请联系管理员", code=501)
# DBsession_postgre.close_all()
# DBsession_mysql.close_all()
return jsonify(msg="未知异常, 请联系管理员", code=505)
session_mysql.close()
session_postgre.close()
logger.info("#####################################请求调度更新结束#####################################")
# 调度结束时间
rtd_end_time = datetime.now()
......
{
"para": {
"log_path": "/usr/local/fleet-log/dispatch",
"log_path": "./Logs/",
"empty_speed": 17,
"heavy_speed": 17,
"dump_target_mass": 5000,
......@@ -8,23 +8,23 @@
},
"mysql": {
"host": "192.168.9.152",
"host": "172.16.0.103",
"port": "3306",
"user": "root",
"password": "Huituo@123",
"database": "waytous"
"database": "ht_zhunneng_0913"
},
"postgresql": {
"host": "192.168.9.152",
"host": "172.16.0.103",
"port": "5432",
"user": "postgres",
"password": "Huituo@123",
"database": "shenbao_2021520"
"database": "gis_zhunneng_0913"
},
"redis": {
"host": "192.168.9.152",
"host": "172.16.0.103",
"password": "Huituo@123"
}
}
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/6/1 16:35
# @Author : Opfer
# @Site :
# @File : dispatcher.py
# @Software: PyCharm
from data.dispatchInfo import DispatchInfo
from core.group import Group
from alg.algorithm import ExpectedTime
from settings import get_logger, session_mysql, redis5
from tables import Dispatch, DispatchMatch, DispatchEquipment, DispatchGroup, DispatchSetting
from para_config import DeviceMap, get_value, global_period_para_update
from equipment import TruckInfo, ExcavatorInfo, DumpInfo
from core.schedule import PreSchedule
import json
import uuid
from tables import session_mysql, session_postgre
import numpy as np
from datetime import datetime, timedelta
class Dispatcher:
"""
class for group dispatch program.
"""
def __init__(self, truck: TruckInfo, dump: DumpInfo, excavator: ExcavatorInfo, pre_sch: PreSchedule, request_mode=False):
self.group_list = {}
self.truck = truck
self.dump = dump
self.excavator = excavator
self.pre_sch = pre_sch
self.request_mode = request_mode
self.submission = DispatchSubmission(dump, excavator, truck)
self.logger = get_logger("zxt.dispatcher")
def period_update(self):
"""
Update global parameter and equipment information.
:return: None
"""
# global_period_para_update()
self.dump.dump_para_period_update()
self.excavator.excavator_para_period_update()
self.truck.truck_para_period_update(self.dump, self.excavator)
self.truck.state_period_update()
def group_generate(self):
"""
Generate and initialize dispatch groups.
:return: None
"""
self.group_list = {}
groups = DispatchInfo.get_all_group()
for group_id in groups:
if group_id not in self.group_list:
group = Group(group_id, self.truck, self.pre_sch)
self.group_list[group_id] = group
def group_info_update(self):
"""
Update group information.
:return: None
"""
for group in self.group_list.values():
group.info_update()
def group_dispatch(self):
"""
Group dispatching logic.
:return:
"""
a = len(self.group_list)
aa = self.group_list
for group in self.group_list.values():
try:
truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime)
except Exception as es:
self.logger.error(es)
self.logger.error(f'分组{group.group_id} 调度异常')
self.logger.info(f'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}')
self.submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict)
class DispatchSubmission:
""" class for the submission calculated dispatch.
Description:
将调度结果按照指定格式传递到云端机群
Attribute:
"""
def __init__(self, dump, excavator, truck):
self.logger = get_logger("zxt.submission")
self.dump = dump
self.excavator = excavator
self.truck = truck
def truck_dispatch_to_redis(self, truck_id, dispatch_seq):
"""
将truck_id对应矿卡派车计划写入redis
:param truck_id: (uuid) 矿卡uuid
:param dispatch_seq: (List[int]) 矿卡派车计划
:return: None
"""
try:
try:
group_id = DispatchInfo.truck_group_dict[truck_id]
record = {"truckId": truck_id}
task = self.truck.get_truck_current_task()[truck_id]
except Exception as es:
self.logger.error("调度结果写入异常-读取矿卡信息异常(uuid, group id, task)")
self.logger.error(es)
try:
group_mode = DispatchInfo.get_group_mode(group_id)
except Exception as es:
self.logger.error("调度模式读取异常")
self.logger.error(es)
group_mode = 3
if group_mode == 3:
try:
item = session_mysql.query(DispatchSetting).filter_by(truck_id=truck_id, isdeleted=0, ).first()
record["dispatchId"] = item.id
record["exactorId"] = item.exactor_id
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["groupId"] = item.group_id
record["isdeleted"] = False
record["isTemp"] = False
record["haulFlag"] = -1
record["groupName"] = DispatchInfo.group_name[group_id]
self.logger.info(f'redis 注入 {record}')
except Exception as es:
self.logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
finally:
redis5.set(truck_id, str(json.dumps(record)))
else:
if task in [0, 1, 2]: # 卡车空载或在装载区出场前, 可变更卸载目的地
# 查询车辆相关派车计划
try:
dump_id = DispatchInfo.unload_area_dump_dict[dispatch_seq[1]]
item = (session_mysql.query(DispatchSetting).filter_by(dump_id=dump_id, group_id=group_id,
isdeleted=0, ).first())
if item is None:
raise Exception("调度计划配置异常")
if dispatch_seq[0] is None:
raise Exception("调度计划表与实时监控不匹配")
except Exception as es:
item = (session_mysql.query(DispatchSetting).filter_by(group_id=group_id, isdeleted=0, ).first())
self.logger.error(es)
# # 调度目的地写入
# try:
# if dispatch_seq[0] is None:
# raise Exception("调度计划表与实时监控不匹配")
# record["dumpId"] = DispatchInfo.unload_area_dump_dict[dispatch_seq[1]]
# record["unloadAreaId"] = dispatch_seq[1]
# except Exception as es:
# # item = (session_mysql.query(DispatchSetting).filter_by(truck_id=truck_id, isdeleted=0, ).first())
# record["dumpId"] = item.dump_id
# record["unloadAreaId"] = item.unload_area_id
# self.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]
self.logger.info(f'redis 注入 {record}')
except Exception as es:
self.logger.error("调度结果写入异常-矿卡空载")
self.logger.error(es)
finally:
redis5.set(truck_id, str(json.dumps(record)))
elif task in [3, 4, 5]: # 卡车重载或在卸载区出场前, 可变更装载目的地
# 查询车辆相关派车计划
try:
item = (session_mysql.query(DispatchSetting).filter_by(exactor_id=dispatch_seq[0], group_id=group_id,
isdeleted=0, ).first())
if item is None:
raise Exception("调度计划配置异常")
if dispatch_seq[0] is None:
raise Exception("调度计划表与实时监控不匹配")
except Exception as es:
item = (session_mysql.query(DispatchSetting).filter_by(group_id=group_id, isdeleted=0, ).first())
self.logger.error(es)
# # 调度目的地写入
# try:
# if dispatch_seq[0] is None:
# raise Exception("调度计划表与实时监控不匹配")
# record["exactorId"] = dispatch_seq[0]
# record["loadAreaId"] = DispatchInfo.excavator_load_dict[dispatch_seq[0]]
# except Exception as es:
# # item = (session_mysql.query(DispatchSetting).filter_by(truck_id=truck_id, isdeleted=0, ).first())
# record["exactorId"] = item.exactor_id
# record["loadAreaId"] = item.load_area_id
# self.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]
self.logger.info(f'redis 注入 {record}')
except Exception as es:
self.logger.error("调度结果写入异常-矿卡重载")
finally:
redis5.set(truck_id, str(json.dumps(record)))
elif task == -2:
try:
# 查询车辆相关派车计划
try:
item = (session_mysql.query(DispatchSetting).filter_by(exactor_id=dispatch_seq[0],
group_id=group_id, isdeleted=0).first())
if item is None:
raise Exception("调度计划配置异常")
if dispatch_seq[0] is None:
raise Exception("调度计划表与实时监控不匹配")
except Exception as es:
item = (session_mysql.query(DispatchSetting).filter_by(group_id=group_id,
isdeleted=0, ).first())
self.logger.error(es)
# # 调度目的地写入
# try:
# if dispatch_seq[0] is None:
# raise Exception("调度计划表与实时监控不匹配")
# record["exactorId"] = dispatch_seq[0]
# record["loadAreaId"] = DispatchInfo.excavator_load_dict[dispatch_seq[0]]
# except Exception as es:
# item = (
# session_mysql.query(DispatchSetting)
# .filter_by(truck_id=truck_id,
# isdeleted=0).first())
# record["exactorId"] = item.exactor_id
# record["loadAreaId"] = item.load_area_id
# self.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]
self.logger.info(f'redis 注入 {record}')
# record["createtime"] = datetime.now().strftime(
# "%b %d, %Y %I:%M:%S %p")
except Exception as es:
self.logger.error("调度结果写入异常-矿卡故障或备停区-redis写入异常")
self.logger.error(es)
finally:
redis5.set(truck_id, str(json.dumps(record)))
except Exception as es:
self.logger.error("调度结果写入异常-矿卡故障或备停区")
self.logger.error(es)
else:
pass
except Exception as es:
self.logger.error("调度结果写入异常")
self.logger.error(f"调度结果:{dispatch_seq}")
self.logger.error(es)
def group_dispatch_to_redis(self, group: Group, dispatch_plan_dict):
"""
Update the dispatch plan in the group to redis
:param group: (Group)
:param dispatch_plan_dict: (Dict)
:return: None
"""
self.logger.info("dispatch_plan_dict")
self.logger.info(dispatch_plan_dict)
for truck_id, dispatch_plan in dispatch_plan_dict.items():
self.logger.info(f'======================================= 调度车辆 =======================================')
self.logger.info(f'矿车编号 {get_value("truck_uuid_to_name_dict")[truck_id]} {truck_id}')
self.logger.info(f'调度模式 {group.group_mode}')
self.logger.info(f'车辆任务 {group.truck_info_list[truck_id].get_task()}')
self.logger.info(f'配对挖机 {dispatch_plan[0]}')
self.logger.info(f'配对卸点 {dispatch_plan[1]}')
self.truck_dispatch_to_redis(truck_id, dispatch_plan)
self.logger.info("======================================== 完成写入 =======================================")
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/5/30 15:35
# @Author : Opfer
# @Site :
# @File : group.py
# @Software: PyCharm
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/5/30 15:35
# @Author : Opfer
# @Site :
# @File : group.py
# @Software: PyCharm
from data.dispatchInfo import *
from bidict import bidict
from alg.algorithm import AlgorithmBase,DistributionRatio
import numpy as np
# from settings import get_logger
from para_config import get_value
class CurrentTruck:
""" class for the information of current dispatching truck.
Description:
当前请求调度卡车信息
Attribute:
truck_id(uuid)
group_id(uuid)
trip(list)
task(int)
"""
def __init__(self, truck_id, group_id, trip, task):
self._truck_id = truck_id
self._group_id = group_id
self._trip = trip
self._task = task
def get_truck_id(self):
return self._truck_id
def get_trip(self):
return self._trip
def get_task(self):
return self._task
def get_group_id(self):
return self._group_id
class Group:
"""
class for group instance.
"""
def __init__(self, group_id, truck, pre_sch):
""" Generate a group obj.
:param group_id: (uuid) group_id
"""
self.logger = get_logger("ga.Group")
# basic info.
self.group_id = group_id
self.group_mode = 1
self.truck = truck
self.pre_sch = pre_sch
# group devices
self.excavator = {} # excavator_id -> unload_area_id
self.unload_area = {} # unload_area_id -> load_area_id
self.dump = {}
self.truck_set = set() # truck_id
# road network info.
self.to_excavator_distance = None
self.to_unload_area_distance = None
self.park_to_excavator_distance = None
# self.to_excavator_congestion = None
# self.to_unload_area_congestion = None
# self.park_to_excavator_congestion = None
# device map
self.truck_uuid_index_dict = bidict()
self.excavator_uuid_index_dict = bidict()
self.unload_area_uuid_index_dict = bidict()
self.dump_uuid_index_dict = bidict()
# truck info.
self.truck_info_list = {}
def update_group_mode(self):
"""
update group mode.
:param group_mode:
:return:
"""
# DispatchInfo.update_group_mode()
self.group_mode = 1
self.group_mode = DispatchInfo.get_group_mode(self.group_id)
def update_group_device(self):
"""
update group devices.
:return:
"""
# update group devices
# DispatchInfo.update_device_group_structure()
self.excavator = {}
self.unload_area = {}
self.dump = {}
self.truck_set = set()
self.excavator = DispatchInfo.get_excavator(self.group_id)
self.unload_area = DispatchInfo.get_unload_area(self.group_id)
self.dump = DispatchInfo.get_dump(self.group_id)
self.truck_set = DispatchInfo.get_truck_set(self.group_id)
def update_group_road_network(self):
"""
update group road network.
:return:
"""
# DispatchInfo.update_route_distance()
self.to_excavator_distance = None
self.to_unload_area_distance = None
self.park_to_excavator_distance = None
self.to_excavator_distance = DispatchInfo.get_to_excavator_distance(self.group_id)
self.to_unload_area_distance = DispatchInfo.get_to_unload_area_distance(self.group_id)
self.park_to_excavator_distance = DispatchInfo.get_park_to_excavator_distance(self.group_id)
def update_group_device_map(self):
"""
update group device map.
:return:
"""
# excavator_index = 0
self.excavator_uuid_index_dict = {}
self.unload_area_uuid_index_dict = {}
self.truck_uuid_index_dict = {}
self.dump_uuid_index_dict = {}
for i in range(len(self.excavator)):
self.excavator_uuid_index_dict[list(self.excavator)[i]] = i
for i in range(len(self.unload_area)):
self.unload_area_uuid_index_dict[list(self.unload_area)[i]] = i
for i in range(len(self.dump)):
self.dump_uuid_index_dict[list(self.dump)[i]] = i
for i in range(len(self.truck_set)):
self.truck_uuid_index_dict[list(self.truck_set)[i]] = i
self.excavator_uuid_index_dict = bidict(self.excavator_uuid_index_dict)
self.unload_area_uuid_index_dict = bidict(self.unload_area_uuid_index_dict)
self.truck_uuid_index_dict = bidict(self.truck_uuid_index_dict)
self.dump_uuid_index_dict = bidict(self.dump_uuid_index_dict)
# group_excavator_dict = {group_1: {excavator_1: load_area_1}, group_2: {excavator_2: load_area_2}}
def info_update(self):
"""
update group info.
:return:
"""
self.update_group_mode()
self.update_group_device()
self.update_group_device_map()
self.update_group_road_network()
def group_dispatch(self, solver: object):
"""
Receive a alg obj. and output dispatch plan for trucks in this group.
:param solver:
:return:
dispatch plan: Dict({truck_id: match_id})
"""
truck_dispatch = {}
self.truck_info_list = {}
assert issubclass(solver, AlgorithmBase)
s = solver(self, self.truck, self.pre_sch) # algorithm init
for i in list(self.truck_set):
truck_trip = self.truck.get_truck_current_trip()[self.truck.truck_uuid_to_index_dict[i]]
truck_task = self.truck.get_truck_current_task()[i]
truck_info = CurrentTruck(i, self.group_id, truck_trip, truck_task)
self.truck_info_list[i] = truck_info
# 全智能模式
if self.group_mode == 1:
if truck_task in [-2, 3, 4, 5]:
try:
next_excavator_value = s.solve(truck_info)
# next_excavator_value = s.solve(i, truck_task, truck_trip)
# min_index = next_excavator_list.index(min(next_excavator_list))
min_index = np.argmin(next_excavator_value)
next_excavator_id = self.excavator_uuid_index_dict.inverse[min_index]
if truck_task == -2:
next_unload_area_id = "Park"
else:
dump_id = get_value("dump_index_to_uuid_dict")[truck_trip[-1]]
next_unload_area_id = get_value("dump_uuid_to_unload_area_uuid_dict")[dump_id]
truck_dispatch[i] = [next_excavator_id, next_unload_area_id]
except Exception as es:
self.logger.error("重载车辆全智能模式-计算异常")
self.logger.error(es)
if truck_task in [0, 1, 2]:
try:
next_unload_area_value = s.solve(truck_info)
min_index = np.argmin(next_unload_area_value)
next_unload_area_id = self.unload_area_uuid_index_dict.inverse[min_index]
# next_excavator_id = self.excavator_uuid_index_dict.inverse[truck_trip[-1]]
next_excavator_id = get_value("excavator_index_to_uuid_dict")[truck_trip[-1]]
truck_dispatch[i] = [next_excavator_id, next_unload_area_id]
except Exception as es:
self.logger.error("空载车辆全智能模式-计算异常")
self.logger.error(es)
truck_dispatch[i] = [None, None]
# 空车智能模式
elif self.group_mode == 2:
if truck_task in [-2, 3, 4, 5]:
try:
next_excavator_value = s.solve(truck_info)
# min_index = next_excavator_list.index(min(next_excavator_list))
min_index = np.argmin(next_excavator_value)
next_excavator_id = self.excavator_uuid_index_dict.inverse[min_index]
if truck_task == -2:
next_unload_area_id = "Park"
else:
# next_unload_area_id = self.unload_area_uuid_index_dict.inverse[truck_trip[-1]]
dump_id = get_value("dump_index_to_uuid_dict")[truck_trip[-1]]
next_unload_area_id = get_value("dump_uuid_to_unload_area_uuid_dict")[dump_id]
truck_dispatch[i] = [next_excavator_id, next_unload_area_id]
except Exception as es:
self.logger.error("重载车辆空车智能模式-计算异常")
self.logger.error(es)
if truck_task in [0, 1, 2]:
try:
truck_dispatch[i] = DispatchInfo.get_truck_match(i)
except Exception as es:
self.logger.error("空载车辆空车智能模式-计算异常")
self.logger.error(es)
# 定铲派车
elif self.group_mode == 3:
try:
truck_dispatch[i] = DispatchInfo.get_truck_match(i)
except Exception as es:
self.logger.error("固定派车-计算异常")
self.logger.error(es)
# 分流配比模式
elif self.group_mode == 4:
next_exactor_id = DispatchInfo.get_truck_exactor(i) # 获取该卡车对应的exactor_id
self.logger.info(f"分流配比模式,对应的卡车:{i}")
self.logger.info(f"矿卡对应的铲车:{next_exactor_id}")
next_unload_area_id = None
if truck_task == -2:
next_unload_area_id = "Park"
# 空载模式下,计算下一次卸载区的位置,按照分流配比的模式进行计算
elif truck_task in [0, 1, 2]:
try:
next_unload_area_id = DistributionRatio(next_exactor_id).ratio_main()
except Exception as es:
self.logger.error("分流配比模式-->>空载车辆计算异常")
self.logger.error(es)
# 重载模式下,按照固定派车进行计算
elif truck_task in [3, 4, 5]:
try:
next_unload_area_id = DispatchInfo.get_truck_match(i)[1]
except Exception as es:
self.logger.error("分流配比模式-->>重载车辆计算异常")
self.logger.error(es)
truck_dispatch[i] = [next_exactor_id, next_unload_area_id]
# return dispatch plan
return truck_dispatch
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/6/9 18:22
# @Author : Opfer
# @Site :
# @File : schedule.py
# @Software: PyCharm
from data.dispatchInfo import DispatchInfo
# from core.group import Group
# from alg.algorithm import ExpectedTime
from settings import get_logger, session_mysql, redis5
from tables import Dispatch
from para_config import DeviceMap, get_value, global_period_para_update
from equipment import TruckInfo, ExcavatorInfo, DumpInfo
import json
import numpy as np
from datetime import datetime, timedelta
class PreSchedule:
""" class for the prediction of equipments' trip.
Description:
负责处理所有预测项的计算与更新
基于矿卡最近一次装卸载时间预测其抵达目的地时间
根据矿卡请求队列及抵达信息,计算设备最早可用时间
Attribute:
equipment class: truck, excavator, dump
schedule start time
equipment available time: truck, excavator, dump
"""
def __init__(self, truck, excavator, dump):
# 设备对象域
self.truck = truck
self.excavator = excavator
self.dump = dump
# 调度开始时间
self.start_time = datetime.now()
# 真实设备可用时间
self.truck_reach_dump = np.zeros(self.truck.get_truck_num())
self.truck_reach_excavator = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time = np.zeros(self.excavator.get_excavator_num())
self.dump_avl_time = np.zeros(self.dump.get_dump_num())
self.truck_avl_time = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time_dict = {}
self.dump_avl_time_dict = {}
self.truck_avl_time_dict = {}
self.logger = get_logger("zxt.pre_schedule")
def update_truck_reach_time(self):
"""
更新矿卡预计抵达目的地时间
:return:
excavator_avl_ls: (list) 驶往挖机的各矿卡抵达时间
dump_avl_ls: (list) 驶往卸点的各矿卡抵达时间
"""
try:
dynamic_excavator_num = self.excavator.get_excavator_num()
dumps = self.dump.get_dump_num()
trucks = self.truck.get_truck_num()
truck_current_task = self.truck.get_truck_current_task()
truck_current_trip = self.truck.get_truck_current_trip()
truck_reach_excavator = self.truck.get_truck_reach_excavator()
truck_reach_dump = self.truck.get_truck_reach_dump()
excavator_avl_ls = [[] for _ in range(dynamic_excavator_num)]
dump_avl_ls = [[] for _ in range(dumps)]
# self.logger.info("update_truck_reach_time-trucks")
# self.logger.info(trucks)
for i in range(trucks):
task = truck_current_task[self.truck.truck_index_to_uuid_dict[i]]
end_area_index = truck_current_trip[i][1]
# self.logger.info("update_truck_reach_time-truck_current_trip")
# self.logger.info(truck_current_trip)
if task in [0, 1]: # 卡车空载行驶或正在入场
reach_time = truck_reach_excavator[i]
excavator_avl_ls[end_area_index].append(
[reach_time, i, end_area_index]
)
elif task in [3, 4]: # 卡车重载行驶或正在入场
reach_time = truck_reach_dump[i]
dump_avl_ls[end_area_index].append([reach_time, i, end_area_index])
elif task == -2:
self.truck_avl_time[i] = (
datetime.now() - self.start_time
) / timedelta(hours=0, minutes=1, seconds=0)
except Exception as es:
self.logger.error("矿卡预计抵达时间计算异常")
self.logger.error(es)
return [], []
return excavator_avl_ls, dump_avl_ls
def update_excavator_avl_time(self, excavator_avl_ls):
"""
更新挖机预计可用时间
:param
excavator_avl_ls: (list) 驶往挖机的各矿卡抵达时间
:return:
excavator_avl_time: (array) 各挖机完成所有已分配矿卡装载的时间
"""
# 初始化挖机可用时间
self.excavator_avl_time = np.full(
get_value("dynamic_excavator_num"),
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0),
)
for excavator_id in get_value("dynamic_excavator_set"):
self.excavator_avl_time_dict[excavator_id] = (datetime.now() - self.start_time) \
/ timedelta(hours=0, minutes=1, seconds=0)
loading_time = self.excavator.get_loading_time()
loading_task_time = self.excavator.get_loading_task_time()
try:
now = float(
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0)
)
for reach_ls in excavator_avl_ls:
self.logger.info("update_excavator_avl_time-excavator_avl_ls")
self.logger.info(excavator_avl_ls)
if len(reach_ls) != 0:
reach_ls = np.array(reach_ls)
tmp = reach_ls[np.lexsort(reach_ls[:, ::-1].T)]
for i in range(len(tmp)):
try:
excavator_index = int(tmp[i][2])
excavator_id = self.excavator.excavator_index_to_uuid_dict[excavator_index]
except Exception as es:
self.logger.error("excavator_error_1")
self.logger.error(es)
try:
self.excavator_avl_time[excavator_index] = (
max(tmp[i][0], self.excavator_avl_time[excavator_index])
+ loading_task_time[excavator_index]
)
self.excavator_avl_time_dict[excavator_id] = self.excavator_avl_time[excavator_index]
except Exception as es:
self.logger.error("excavator_error_2")
self.logger.error(es)
try:
truck_index = int(tmp[i][1])
truck_id = self.truck.truck_index_to_uuid_dict[truck_index]
except Exception as es:
self.logger.error("excavator_error_3")
self.logger.error(es)
try:
self.truck_avl_time[truck_index] = self.excavator_avl_time[excavator_index]
self.truck_avl_time_dict[truck_id] = self.truck_avl_time[truck_index]
except Exception as es:
self.logger.error("excavator_error_4")
self.logger.error(es)
# # 若挖机可用时间严重偏离,进行修正
# if abs(self.excavator_avl_time[excavator_index] - now) > 60:
# self.truck_avl_time[int(tmp[i][1])] = now
# if abs(self.excavator_avl_time[excavator_index] - now) > 60:
# self.excavator_avl_time[excavator_index] = now
except Exception as es:
self.logger.error("挖机可用时间计算异常")
self.logger.error(es)
return self.excavator_avl_time_dict
def update_dump_avl_time(self, dump_avl_ls):
"""
更新卸载设备预计可用时间
:param
dump_avl_ls: (list) 驶往卸点的各矿卡抵达时间
:return:
dump_avl_time: (array) 各卸点完成所有已分配矿卡卸载的时间
"""
dynamic_dump_num = self.dump.get_dump_num()
# 初始化卸载设备可用时间
self.dump_avl_time = np.full(
dynamic_dump_num,
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0),
)
for dump_id in get_value("dynamic_dump_set"):
self.dump_avl_time_dict[dump_id] = (datetime.now() - self.start_time) \
/ timedelta(hours=0, minutes=1, seconds=0)
unloading_time = self.dump.get_unloading_time()
unloading_task_time = self.dump.get_unloading_task_time()
try:
now = float(
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0)
)
for reach_ls in dump_avl_ls:
if len(reach_ls) != 0:
reach_ls = np.array(reach_ls)
tmp = reach_ls[np.lexsort(reach_ls[:, ::-1].T)]
for i in range(len(tmp)):
dump_index = int(tmp[i][2])
dump_id = self.dump.dump_index_to_uuid_dict[dump_index]
self.dump_avl_time[dump_index] = (
max(tmp[i][0], self.dump_avl_time[dump_index])
+ unloading_task_time[dump_index]
)
self.dump_avl_time_dict[dump_id] = self.dump_avl_time[dump_index]
truck_index = int(tmp[i][1])
truck_id = self.truck.truck_index_to_uuid_dict[truck_index]
self.truck_avl_time[truck_index] = self.dump_avl_time[dump_index]
self.truck_avl_time_dict[truck_id] = self.truck_avl_time[truck_index]
# # 若卸载设备可用时间严重偏离,进行修正
# if abs(self.dump_avl_time[dump_index] - now) > 60:
# self.dump_avl_time[dump_index] = now
# if abs(self.truck_avl_time[int(tmp[i][1])] - now) > 60:
# self.truck_avl_time[int(tmp[i][1])] = now
except Exception as es:
self.logger.error("卸载设备可用时间计算异常")
self.logger.error(es)
return self.dump_avl_time_dict
def _reset(self):
"""
重置设备可用时间
:return:
"""
# 真实设备可用时间
self.truck_reach_dump = np.zeros(self.truck.get_truck_num())
self.truck_reach_excavator = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time = np.zeros(self.excavator.get_excavator_num())
self.dump_avl_time = np.zeros(self.dump.get_dump_num())
self.truck_avl_time = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time_dict = {}
self.dump_avl_time_dict = {}
self.truck_avl_time_dict = {}
def get_dump_avl_time(self):
"""
获取卸载点最早可用时间
:return:
dump_avl_time: (array) 各卸点完成所有已分配矿卡卸载的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
dump_avl_time = self.update_dump_avl_time(dump_avl_ls)
return dump_avl_time
def get_excavator_avl_time(self, excavator_id=None):
"""
获取挖机最早可用时间
:param excavator_id: 挖机编号uuid
:return:
excavator_avl_time: (array) 各挖机完成所有已分配矿卡装载的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
if excavator_id is not None:
return self.update_excavator_avl_time(excavator_avl_ls) \
[self.excavator.excavator_uuid_to_index_dict[excavator_id]]
else:
tmp = self.update_excavator_avl_time(excavator_avl_ls)
return self.update_excavator_avl_time(excavator_avl_ls)
def get_truck_avl_time(self, truck_id=None):
"""
获取矿卡最早可用时间
:param truck_id: 矿卡编号uuid
:return: truck_avl_time: (array) 各矿卡完成当前装载或卸载任务的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
self.update_excavator_avl_time(excavator_avl_ls)
self.update_dump_avl_time(dump_avl_ls)
if truck_id is not None:
return self.truck_avl_time[self.truck.truck_uuid_to_index_dict[truck_id]]
else:
return self.truck_avl_time
\ No newline at end of file
# -*- coding: utf-8 -*-
# @Time : 2022/5/30 14:45
# @Author : Opfer
# @Site :
# @File : dispatchInfo.py
# @Software: PyCharm
import numpy as np
from settings import *
import pandas as pd
from tables import DispatchMatch, DispatchEquipment
logger = get_logger("zxt.dispatchInfo")
class DispatchInfo:
"""
class for dispatch group info.
"""
# dispatch groups
group_set = set()
# device group structure
load_excavator_dict = {} # 装载区id-->>电铲编号的映射
excavator_load_dict = {} # 电铲编号->>装载区id的映射
# excavator <-> group id
group_excavator_dict = {} # team_id -> dict {[excavator_id, excavator_id], ...}
excavator_group_dict = {} # excavator_id -> team_id 问题:多个key值对应一个value值
# unload_area <-> group id
group_unload_area_dict = {} # team_id -> dict {unload_area_id, unload_area_id, ...}
unload_area_group_dict = {} # unload_area_id -> team_id
# dump <-> group id
group_dump_dict = {}
dump_group_dict = {}
# truck_id <-> team_id
group_truck_dict = {} # team_id -> dict # {group_id:[truck_id,truck_id],...}
truck_group_dict = {} # truck_id -> team_id
# group mode
group_mode = {} # 数据格式: {team_id:mode_code}
# route_distance(路网距离)
load_distance = {}
unload_distance = {}
# group_name <-> group_id
group_name = {}
# truck -> match(excavator_id, unload_area_id)
truck_match_dict = {}
# unload_area <-> dump id
dump_unload_area_dict = {}
unload_area_dump_dict = {}
# 获取电铲与卡车的双映射 -->> exactor_id <-> truck_id
exactor_truck_dict = {}
truck_exactor_dict = {}
# 获取电铲与卸载区的双映射 -->> exactor_id <-> unload_area_id
exactor_unload_dict = {}
unload_exactor_dict = {}
# 获取卸载区与rate之间的关系 -->> unload_area_id -> rate
unload_rate_dict = {}
@classmethod
def reset(cls):
"""
@date:2022/6/2 19:50
@author:maqc
@desc:实例化对象,可直接访问
"""
cls.group_set = set()
cls.load_excavator_dict = {}
cls.excavator_load_dict = {}
cls.group_excavator_dict = {}
cls.excavator_group_dict = {}
cls.group_unload_area_dict = {}
cls.unload_area_group_dict = {}
cls.group_dump_dict = {}
cls.dump_group_dict = {}
cls.group_truck_dict = {}
cls.truck_group_dict = {}
cls.group_mode = {}
cls.load_distance = {}
cls.unload_distance = {}
cls.truck_match_dict = {}
cls.dump_unload_area_dict = {}
cls.unload_area_dump_dict = {}
cls.exactor_truck_dict = {}
cls.truck_exactor_dict = {}
cls.exactor_unload_dict = {}
cls.unload_exactor_dict = {}
cls.unload_rate_dict = {}
# cls.group_unload_area_dict = {} # cls.group_unload_area_dict.keys() 相当于所有的team_id
# cls.unload_area_group_dict = {} # cls.unload_area_group_dict.keys() 相当于所有的卸载区 unload_area_id
# cls.group_excavator_dict = {}
# cls.excavator_group_dict = {}
# cls.load_excavator_dict = {} # cls.load_excavator_dict.keys() 相当于所有的装载区 load_area_id
# cls.excavator_load_dict = {}
# cls.group_truck_dict = {}
# cls.truck_group_dict = {}
# cls.group_mode = {}
# cls.load_distance = {} # to_load_diatance-->>空车模式
# cls.unload_distance = {} # to_unload_distance-->>重车模式
@classmethod
def update_device_group_structure(cls):
"""
@date:2022/6/2 19:49
@author:maqc
@desc:分组与卸载区、挖机、矿卡的映射和反映射
"""
logger = get_logger("zxt.update_device_group_structure")
# update excavator_id <-> load_area_id
try:
for item in session_mysql.query(DispatchSetting).all():
cls.load_excavator_dict[item.load_area_id] = item.exactor_id
cls.excavator_load_dict[item.exactor_id] = item.load_area_id
# aa = cls.load_excavator_dict
except Exception as es:
logger.error("挖机和装载区映射更新异常")
logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
# update dump_id <-> unload_area_id
try:
for item in session_mysql.query(DispatchSetting).all():
cls.unload_area_dump_dict[item.unload_area_id] = item.dump_id
cls.dump_unload_area_dict[item.dump_id] = item.unload_area_id
# aa = cls.load_excavator_dict
except Exception as es:
logger.error("卸载设备和卸载区映射更新异常")
logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
# update exactor_id <-> truck_id
try:
for item in session_mysql.query(DispatchSetting).all():
if item.exactor_id not in cls.exactor_truck_dict.keys():
cls.exactor_truck_dict[item.exactor_id] = [item.truck_id]
else:
if item.truck_id not in cls.exactor_truck_dict[item.exactor_id]:
cls.exactor_truck_dict[item.exactor_id].append(item.truck_id)
cls.truck_exactor_dict[item.truck_id] = item.exactor_id
except Exception as es:
logger.error("电铲和卡车的映射关系更新异常")
logger.error(es)
# update exactor_id <-> unload_area_id
try:
for item in session_mysql.query(DispatchSetting).all():
if item.exactor_id not in cls.exactor_unload_dict.keys():
cls.exactor_unload_dict[item.exactor_id] = [item.unload_area_id]
else:
if item.unload_area_id not in cls.exactor_unload_dict[item.exactor_id]:
cls.exactor_unload_dict[item.exactor_id].append(item.unload_area_id)
except Exception as es:
logger.error("电铲和卸载区的映射关系更新异常")
logger.error(es)
# update unload_area_id -> rate
try:
for item in session_mysql.query(DispatchSetting).all():
cls.unload_rate_dict[item.unload_area_id] = item.rate
except Exception as es:
logger.error("卸载区和比例值关系更新异常")
logger.error(es)
# update excavator_id <-> group_id && unload_area_id <-> group_id && truck_id <-> group_id
try:
for item in session_mysql.query(DispatchSetting).all():
# add excavator
if item.group_id not in cls.group_excavator_dict.keys():
cls.group_excavator_dict[item.group_id] = [item.exactor_id]
else:
if item.exactor_id not in cls.group_excavator_dict[item.group_id]:
cls.group_excavator_dict[item.group_id].append(item.exactor_id)
cls.excavator_group_dict[item.exactor_id] = item.group_id
# add unload_area
if item.group_id not in cls.group_unload_area_dict.keys():
cls.group_unload_area_dict[item.group_id] = [item.unload_area_id]
else:
if item.unload_area_id not in cls.group_unload_area_dict[item.group_id]:
cls.group_unload_area_dict[item.group_id].append(item.unload_area_id)
cls.unload_area_group_dict[item.unload_area_id] = item.group_id
# add dump
if item.dump_id not in cls.group_dump_dict.keys():
cls.group_dump_dict[item.group_id] = [item.dump_id]
else:
if item.dump_id not in cls.group_dump_dict[item.group_id]:
cls.group_dump_dict[item.group_id].append(item.dump_id)
cls.dump_group_dict[item.dump_id] = item.group_id
# add truck
if item.group_id not in cls.group_truck_dict.keys():
cls.group_truck_dict[item.group_id] = [item.truck_id]
else:
if item.truck_id not in cls.group_truck_dict[item.group_id]:
cls.group_truck_dict[item.group_id].append(item.truck_id)
cls.truck_group_dict[item.truck_id] = item.group_id
print("存在的分组")
print(cls.group_excavator_dict.keys())
except Exception as es:
logger.error("挖机/卸载区/矿卡与group_id映射更新异常")
logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
# update group set
try:
cls.group_set = set(cls.group_excavator_dict.keys())
except Exception as es:
logger.error(es)
# update truck_id <-> match_id(excavator_id, unload_area_id)
try:
trucks = cls.truck_group_dict.keys()
for i in trucks:
match_excavator = session_mysql.query(DispatchSetting).filter_by(truck_id=i).first().exactor_id
match_unload_area = session_mysql.query(DispatchSetting).filter_by(truck_id=i).first().unload_area_id
cls.truck_match_dict[i] = [match_excavator, match_unload_area]
except Exception as es:
logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
@classmethod
def update_group_mode(cls):
"""
@date:2022/6/2 19:49
@author:maqc
@desc:处理其它类型的数据
"""
# update group_id->mode_code
logger = get_logger("zxt.update_group_mode")
cls.group_mode = {}
try:
for item in session_mysql.query(DispatchGroup).all():
mode_id = item.mode_id
mode_code = session_mysql.query(DispatchMode).filter_by(id=mode_id).first().mode_code
# mode = session_mysql.query(DispatchMode).filter_by(group_code=).first()
cls.group_mode[item.id] = mode_code
except Exception as es:
logger.error("group_id->mode_code更新异常")
logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
@classmethod
def update_group_name(cls):
"""
@date:2022/6/13 20:30
@author:zxtc
@desc:处理 group name
"""
# update group_id->mode_name
logger = get_logger("zxt.update_group_name")
cls.group_name = {}
try:
for item in session_mysql.query(DispatchGroup).all():
name = item.group_name
cls.group_name[item.id] = name
except Exception as es:
logger.error("group_id->name更新异常")
logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
logger.info("group_name")
logger.info(cls.group_name)
@classmethod
# 距离-->>数据格式:矩阵-->>to_load_distance
def update_route_distance(cls):
"""
@date:2022/6/2 19:50
@author:maqc
@desc:更新路网距离,返回矩阵格式数据
"""
logger = get_logger("zxt.update_route_distance")
try:
groups = cls.group_excavator_dict.keys()
for item in groups:
try:
# 每个组的 excavator_id 及对应 load_area_id
excavator_ids = cls.group_excavator_dict[item]
load_areas = []
for excavator_id in excavator_ids:
load_areas.append(cls.excavator_load_dict[excavator_id])
# 每个组的unload_areas
unload_areas = cls.group_unload_area_dict[item]
except Exception as es:
logger.error("装卸载区统计异常")
logger.error(es)
try:
# unload->load distance
unload_load_distance = np.zeros((len(unload_areas), len(load_areas)))
for i in range(len(unload_areas)):
for j in range(len(load_areas)):
distance = int(session_postgre.query(WalkTime).filter_by(unload_area_id=unload_areas[i], load_area_id=load_areas[j]).first().to_load_distance)
unload_load_distance[i][j] = distance
cls.load_distance[item] = unload_load_distance
except Exception as es:
logger.error(f'{item} 分组装载路网异常')
cls.load_distance[item] = np.full((len(unload_areas), len(load_areas)), 10000)
logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
try:
# load->unload distance
load_unload_distance = np.zeros((len(load_areas), len(unload_areas)))
for i in range(len(load_areas)):
for j in range(len(unload_areas)):
distance = int(session_postgre.query(WalkTime).filter_by(load_area_id=load_areas[i], unload_area_id=unload_areas[j]).first().to_unload_distance)
load_unload_distance[i][j] = distance
cls.unload_distance[item] = load_unload_distance
except Exception as es:
logger.error(f'{item} 分组卸载路网异常')
cls.unload_distance[item] = np.full((len(load_areas), len(unload_areas)), 10000)
logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
except Exception as es:
logger.error("路网距离更新异常-调度部分和路网部分不一致")
logger.error(es)
@classmethod
def get_all_group(cls):
return set(cls.group_excavator_dict.keys())
@classmethod
def get_group_mode(cls, group_id):
return cls.group_mode[group_id]
@classmethod
def get_excavator(cls, group_id):
return set(cls.group_excavator_dict[group_id])
@classmethod
def get_unload_area(cls, group_id):
return set(cls.group_unload_area_dict[group_id])
@classmethod
def get_dump(cls, group_id):
return set(cls.group_dump_dict[group_id])
@classmethod
def get_truck_set(cls, group_id):
return set(cls.group_truck_dict[group_id])
@classmethod
def get_load_area(cls, excavator_id):
return cls.excavator_load_dict[excavator_id]
@classmethod
def get_to_excavator_distance(cls, group_id):
return cls.load_distance[group_id]
@classmethod
def get_to_unload_area_distance(cls, group_id):
return cls.unload_distance[group_id]
@classmethod
def get_truck_match(cls, truck_id):
return cls.truck_match_dict[truck_id]
@classmethod
def get_park_to_excavator_distance(cls, group_id):
excavators = cls.group_excavator_dict[group_id]
park_matrix = np.ones((1, len(excavators)))
try:
b = excavators
for i in range(len(excavators)):
load_area_id = cls.excavator_load_dict[excavators[i]]
try:
distance = session_postgre.query(WalkTimePark).filter_by(load_area_id=load_area_id).first().park_load_distance
park_matrix[0][i] = distance
except Exception as es:
logger.warning("查询不到距离,设置为100000000")
logger.warning(es)
park_matrix[0][i] = 100000000 # 设置为一个很大的数字
except Exception as es:
logger.error("park->load距离更新异常, 存在备停区不可达的装载区")
logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
return park_matrix
@classmethod
def get_truck_exactor(cls, truck_id):
return cls.truck_exactor_dict[truck_id]
@classmethod
def get_exactor_truck_nums(cls, exactor_id):
return len(cls.exactor_truck_dict[exactor_id])
@classmethod
def get_exactor_unload_match(cls, exactor_id):
return cls.exactor_unload_dict[exactor_id]
# #!E:\Pycharm Projects\Waytous
# # -*- coding: utf-8 -*-
# # @Time : 2022/5/30 14:45
# # @Author : Opfer
# # @Site :
# # @File : dispatchInfo.py
# # @Software: PyCharm
# from settings import *
#
# logger = get_logger("mqc.dispatchInfo")
#
#
# class DispatchInfo:
# """
# class for dispatch group info.
# """
#
# # dispatch groups
# group_set = set()
#
# # device group structure
# group_unload_area_dict = {} # team_id -> dict {unload_area_id, unload_area_id, ...}
# # {group_id:unload_area_id,...}
# group_excavator_dict = {} # team_id -> dict {[excavator_id, load_area_id], ...}
# # {group_id: [excavator_id, unload_area_id], ...}
# group_truck_dict = {} # team_id -> dict {truck_id, ...}
# # {group_id:[truck_id,truck_id],...}
#
# unload_area_group_dict = {} # unload_area_id -> team_id
# excavator_group_dict = {} # excavator_id -> team_id
# truck_group_dict = {} # truck_id -> team_id
#
# # group feature
# group_mode = {} # 四种模式:全智能、空车智能、定铲定铲和分流配比模式
# # {mode_name:mode_code}
#
# # route_distance(路网距离)
# load_excavator_distance = {} # 装载区-挖机(电铲)的距离 数据格式 -->> {load_area_id:[excavator_uuid, to_load_distance],}
# unload_excavator_distance = {} # 卸载区-挖机(电铲)的距离 数据格式 -->> {unload_area_id:[excavator_uuid, to_unload_distance],}
#
# @classmethod
# def renew_set(cls):
# """
# @date:2022/6/2 19:50
# @author:maqc
# @desc:实例化对象,可直接访问
# """
# cls.group_unload_area_dict = {}
# cls.unload_area_group_dict = {}
#
# cls.group_excavator_dict = {}
# cls.excavator_group_dict = {}
#
# cls.group_truck_dict = {}
# cls.truck_group_dict = {}
#
# cls.group_mode = {}
# cls.load_excavator_distance = {}
# cls.unload_excavator_distance = {}
#
# @classmethod
# def update_device_group_structure(cls):
# """
# @date:2022/6/2 19:49
# @author:maqc
# @desc:分组与卸载区、挖机、矿卡的映射和反映射
# """
# logger = get_logger("mqc.update_device_group_structure")
# try:
# # group_unload_area_dict = {} -->> {group_id:unload_area_id,...}
# # unload_area_group_dict = {} # unload_area_id -> team_id
# group_code_dict = {} # group_code-->>team_id的映射
# for valve in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():
# group_code_dict[valve.group_code] = valve.team_id
# if valve.team_id not in cls.group_unload_area_dict:
# cls.group_unload_area_dict[valve.team_id] = [valve.unload_area_id] # 注意:一个team_id可能对应多个unload_area_id
# else:
# cls.group_unload_area_dict[valve.team_id].append(valve.unload_area_id)
# cls.unload_area_group_dict[valve.unload_area_id] = valve.team_id # 一个unload_area_id只对应一个team_id
# # group_excavator_dict = {} -->> {group_id: [excavator_id, unload_area_id], ...} # 一个team_id对应一组excavator_id, unload_area_id
# # excavator_group_dict = {} -->> excavator_id -> team_id 一个excavator_id只对应一个team_id
# for item in session_mysql.query(DispatchMatch).filter_by(group_type=1).all():
# # cls.group_excavator_dict[item.team_id] = [item.excavator_id, item.unload_area_id]
# cls.group_excavator_dict[item.team_id] = item.excavator_id
# cls.excavator_group_dict[item.excavator_id] = item.team_id
# # group_truck_dict = {} -->> {group_id:[truck_id,truck_id],...}
# # truck_group_dict = {} -->> truck_id -> team_id
# for key in session_mysql.query(DispatchEquipment).filter_by(group_type=1).all():
# if key.group_code in group_code_dict:
# if key.group_code not in cls.group_truck_dict:
# cls.group_truck_dict[key.group_code] = [key.equipment_id]
# else:
# cls.group_truck_dict[key.group_code].append(key.equipment_id)
# cls.truck_group_dict[key.equipment_id] = group_code_dict[key.group_code]
# except Exception as es:
# logger.error("分组到卸载区的数据更新异常")
# logger.error(es)
#
# @classmethod
# def update_group_mode(cls):
# """
# @date:2022/6/2 19:49
# @author:maqc
# @desc:处理其它类型的数据
# """
# logger = get_logger("mqc.update_group_mode")
# try:
# for value in session_mysql.query(DispatchMode).all():
# cls.group_mode[value.mode_name] = value.mode_code
# except Exception as es:
# logger.error("派车模式数据更新异常")
# logger.error(es)
#
# @classmethod
# def dispatch_group_init(cls):
# """
# update basic paras (group_set, dict, num ...)
# :return:
# """
# pass
#
#
# @classmethod
# def get_group_road_info(cls,group_id, truck_info):
# if truck_info == 1:
# for i in group_excavator():
# pass
# for j in group_unload_area():
# pass
# if truck_info == 2:
# pass
# @classmethod
# # 距离-->>数据格式:矩阵-->>to_load_distance
# def update_route_distance(cls):
# """
# @date:2022/6/2 19:50
# @author:maqc
# @desc:更新路网距离,返回矩阵格式数据
# """
# load_excavator_dict = {} # 装载区id-->>电铲编号的映射
# logger = get_logger("mqc.update_route_distance")
# try:
# for value in session_postgre.query(DiggingWorkArea).all():
# load_excavator_dict[value.Id] = value.Exactorld
# for value in session_postgre.query(WalkTime).all():
# if value.load_area_id in load_excavator_dict:
# cls.load_excavator_distance[value.load_area_id] = [load_excavator_dict[value.load_area_id],
# value.to_load_distance]
# cls.unload_excavator_distance[value.unload_area_id] = [load_excavator_dict[value.load_area_id],
# value.to_unload_distance]
# except Exception as es:
# logger.error("路网数据更新异常")
# logger.error(es)
#
#
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/12/29 11:36
# @Author : Opfer
# @Site :
# @File : dispatcher.py
# @Software: PyCharm
from traffic_flow.traffic_flow_planner import *
from para_config import *
from group_control.group_control import Group
from path_plan.priority_control import PriorityController
from algorithm import ScheduleAlg
class CurrentTruck:
""" class for the information of current dispatching truck.
Description:
当前请求调度卡车信息
Attribute:
truck_id(uuid)
group_id(uuid)
trip(list)
task(int)
"""
def __init__(self, truck_id, group_id, trip, task):
self._truck_id = truck_id
self._group_id = group_id
self._trip = trip
self._task = task
def get_truck_id(self):
return self._truck_id
def get_trip(self):
return self._trip
def get_task(self):
return self._task
def get_group_id(self):
return self._group_id
class Dispatcher(WalkManage):
""" class for the truck dispatch.
Description:
计算根据矿卡状态计算最佳派车计划
将派车计划写入redis
Attribute:
equipment class: truck, excavator, dump
schedule start time
equipment available time: truck, excavator, dump
"""
def __init__(self, dump, excavator, truck, predict_schedule, request_mode=False):
# 运行模式
self.request_mode = request_mode
# 调度开始时间
self.start_time = datetime.now()
# 车流对象
# self.traffic_flow = Traffic_flow(dump, excavator, truck)
self.traffic_flow = None
# 分组控制对象
self.group = Group(dump, excavator, truck, self.traffic_flow)
# 行程预测对象
self.pre_sch = predict_schedule
# 设备对象
self.dump = dump
self.excavator = excavator
self.truck = truck
# # 路径规划对象
# self.path = PathPlanner(dump, excavator, dump)
# 调度结果输出器
self.submission = DispatchSubmission(dump, excavator, truck, self.group)
# 调度算法
self._schedule_alg = ScheduleAlg(dump, excavator, truck, self.group, self.pre_sch)
# 获取日志器
self.logger = get_logger("zxt.dispatcher")
def dispatcher_period_update(self):
"""
控制全局调度信息更新
"""
if not self.request_mode:
global_period_para_update()
# 更新卸载设备对象
self.dump.dump_para_period_update()
# 更新挖机对象
self.excavator.excavator_para_period_update()
# 更新矿卡对象
self.truck.truck_para_period_update(self.dump, self.excavator)
self.truck.state_period_update()
# # 更新实时车流
# self.traffic_flow.update_actual_traffic_flow()
# # 获取路网加权行驶成本
# self.cost_to_excavator, self.cost_to_dump, self.cost_park_to_excavator = self.path.walk_cost_cal()
# 调度分组更新
self.group.period_update()
def truck_schedule(self, truck_id):
"""
按照指定规则及算法, 为请调车辆分配派车计划
:param truck_id: (uuid) 请调车辆id
:return:
target: (int) 请调车辆目的地id
"""
# 规则读取
try:
rule3 = session_mysql.query(DispatchRule).filter_by(id=3).first().disabled
rule4 = session_mysql.query(DispatchRule).filter_by(id=4).first().disabled
except Exception as es:
self.logger.error(es)
self.logger.error("调度规则读取异常")
session_postgre.rollback()
session_mysql.rollback()
try:
# 读取优先级设置
excavator_priority_coefficient = self.excavator.excavator_priority_coefficient
excavator_material_priority = self.excavator.excavator_material_priority
except Exception as es:
self.logger.error("挖机优先级信息读取异常")
self.logger.error(es)
try:
# 矿卡序号
truck_index = self.truck.truck_uuid_to_index_dict[truck_id]
except Exception as es:
self.logger.error("矿卡基本信息读取异常")
self.logger.error(es)
try:
# 矿卡行程
trip = self.truck.get_truck_current_trip()[truck_index]
except Exception as es:
self.logger.error("矿卡行程读取异常")
self.logger.error(es)
try:
# 矿卡任务
task = self.truck.get_truck_current_task()[self.truck.truck_index_to_uuid_dict[truck_index]]
except Exception as es:
self.logger.error("矿卡任务读取异常")
self.logger.error(es)
try:
# 调度分组
group_id = self.group.dispatch_truck_group[truck_id]
except Exception as es:
self.logger.error("调度分组读取异常")
self.logger.error(es)
try:
# 记录当前调度车辆信息
current_truck = CurrentTruck(truck_id, group_id, trip, task)
except Exception as es:
self.logger.error("调度车辆对象构建异常")
self.logger.error(es)
if truck_id not in self.group.dispatch_truck_group:
self.logger.error("无该矿卡")
return -1
target = 0
# # 车流计算
# # 驶往卸载设备的实际车流
# actual_goto_dump_traffic_flow = self.traffic_flow.actual_goto_dump_traffic_flow
#
# # 驶往挖机的实际车流
# actual_goto_excavator_traffic_flow = self.traffic_flow.actual_goto_excavator_traffic_flow
#
# # 计算理想车流
# opt_goto_dump_traffic_flow, opt_goto_excavator_traffic_flow = traffic_flow_plan(self.truck)
truck_uuid_to_name_dict = get_value("truck_uuid_to_name_dict")
self.logger.info(f"========== 调度矿卡 {truck_id} {truck_index} {truck_uuid_to_name_dict[truck_id]} ==========")
if task == -2:
################################################ 矿卡启动 ###############################################
try:
self.logger.info(datetime.now())
self.logger.info("矿卡状态:矿卡启动或故障恢复")
self.logger.info("矿卡行程:无")
self.logger.info(f"涉及挖机:{list(self.excavator.excavator_uuid_to_index_dict.keys())}")
if truck_id in self.truck.truck_material_bind:
self.logger.info(f'物料类型 {self.truck.truck_material_bind[truck_id]}')
self.logger.info(f'挖机设备优先级 {excavator_priority_coefficient}')
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
# 1. 绑定调度
if truck_id in self.truck.truck_excavator_bind:
self.logger.info("绑定调度")
target = self.excavator.excavator_uuid_to_index_dict[self.truck.truck_excavator_bind[truck_id]]
# 2. 正常调度
elif rule3 and rule4:
self.logger.info("正常调度")
transport_value = self._schedule_alg.truck_schedule(current_truck, "expected")
self.logger.info(f'行驶成本-含拥堵度的路径长度 {transport_value}')
excavator_exclude_modify = self.group.group_excavator_exclude_modify[truck_id]
self.logger.info(f'挖机设备禁止因子 {excavator_exclude_modify}')
target = np.argmin(
transport_value
+ excavator_exclude_modify)
self.logger.info("truck_schedule-target")
self.logger.info(target)
target = self.excavator.excavator_uuid_to_index_dict[
self.group.group_excavator_index_to_uuid_dict[group_id][target]]
self.logger.info("truck_schedule-dict")
self.logger.info(self.excavator.excavator_uuid_to_index_dict)
self.logger.info(self.group.group_excavator_index_to_uuid_dict)
self.logger.info("truck_schedule-target")
self.logger.info(target)
self.logger.info(f'excavator_uuid_to_index_dict {self.excavator.excavator_uuid_to_index_dict}')
# 3. 启用饱和度调度
else:
self.logger.info("饱和度调度")
# saturation_value = self._schedule_alg.saturation_schedule(current_truck)
saturation_value = self._schedule_alg.truck_schedule(current_truck, "saturation")
self.logger.info(f'驶往挖机饱和度价值 {saturation_value}')
target = np.argmax(saturation_value)
target = self.excavator.excavator_uuid_to_index_dict[
self.group.group_excavator_index_to_uuid_dict[group_id][target]]
except Exception as es:
self.logger.error(f"矿卡{truck_id}调度指令生成异常")
self.logger.error(es)
self.logger.info(self.excavator.excavator_uuid_to_index_dict)
self.logger.info(self.group.group_excavator_uuid_to_index_dict)
excavator_uuid_to_name_dict = get_value("excavator_uuid_to_name_dict")
self.logger.info(f"目的地:{excavator_uuid_to_name_dict[self.excavator.excavator_index_to_uuid_dict[target]]}")
if task in [0, 1]: # 矿卡空载行驶或正在入场
################################################ 矿卡空载 ###############################################
try:
self.logger.info("矿卡状态:矿卡空载")
self.logger.info(f"涉及卸载设备:{list(self.dump.dump_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
# 日志记录部分
try:
self.logger.info(f'挖机id: {self.excavator.excavator_uuid_to_index_dict}')
self.logger.info(f'卸点id: {self.dump.dump_uuid_to_index_dict}')
self.logger.info(f'空载trip {trip}')
if truck_id in self.truck.truck_material_bind:
self.logger.info(f'物料类型 {self.truck.truck_material_bind[truck_id]}')
# self.logger.info(f'驶往卸点的运输成本 {self.cost_to_dump}')
self.logger.info("卸点物料修正")
self.logger.info(self.truck.dump_material_bind_modify)
except Exception as es:
self.logger.info("矿卡行程信息异常")
self.logger.info(es)
try:
# 1. 绑定调度
if truck_id in self.truck.truck_dump_bind:
self.logger.info("矿卡已绑定卸点")
unload_area_uuid_to_index_dict = get_value("unload_area_uuid_to_index_dict")
bind_unload_area_id = self.truck.truck_dump_bind[truck_id]
for key, value in self.dump.dump_index_to_unload_area_index_dict.items():
if value == unload_area_uuid_to_index_dict[bind_unload_area_id]:
target = key
break
# 2. 正常调度
elif rule3 and rule4:
# 卸载点处理能力及产量约束 and 电铲采装能力及产量约束 均未启用
transport_value = self._schedule_alg.truck_schedule(current_truck, "expected")
self.logger.info(f'行驶成本-含拥堵度的路径长度 {transport_value}')
dump_material_bind_modify = self.group.group_dump_material_bind_modify[truck_id]
self.logger.info(f'卸点物料禁止因子 {dump_material_bind_modify}')
target = np.argmin(transport_value.T + dump_material_bind_modify)
target = self.dump.dump_uuid_to_index_dict[
self.group.group_dump_index_to_uuid_dict[group_id][target]]
# 3. 饱和度调度
else:
# 卸载点处理能力及产量约束 or 电铲采装能力及产量约束 启用
self.logger.info("饱和度调度")
# saturation_value = self._schedule_alg.saturation_schedule(current_truck)
saturation_value = self._schedule_alg.truck_schedule(current_truck, "saturation")
self.logger.info(f'驶往卸点饱和度价值 {saturation_value}')
target = np.argmax(saturation_value)
target = self.dump.dump_uuid_to_index_dict[
self.group.group_dump_index_to_uuid_dict[group_id][target]]
except Exception as es:
self.logger.error(f"矿卡{truck_id}调度指令生成异常")
self.logger.error(es)
dump_uuid_to_name_dict = get_value("dump_uuid_to_name_dict")
self.logger.info(f"目的地:{dump_uuid_to_name_dict[self.dump.dump_index_to_uuid_dict[target]]}")
elif task in [3, 4]: # 卡车重载行驶或正在入场
################################################ 矿卡重载 ###############################################
try:
self.logger.info("矿卡状态:矿卡重载")
self.logger.info(f"涉及挖机设备:{list(self.excavator.excavator_uuid_to_index_dict.keys())}")
except Exception as es:
self.logger.error(f"矿卡{truck_id}状态不匹配")
self.logger.error(es)
try:
self.logger.info("挖机id:")
self.logger.info(self.excavator.excavator_uuid_to_index_dict)
self.logger.info("卸点id:")
self.logger.info(self.dump.dump_uuid_to_index_dict)
self.logger.info("重载trip")
self.logger.info(trip)
self.logger.info("物料类型")
if truck_id in self.truck.truck_material_bind:
self.logger.info(self.truck.truck_material_bind[truck_id])
# self.logger.info("驶往挖机的运输成本")
# self.logger.info(self.cost_to_excavator)
self.logger.info("挖机物料修正")
self.logger.info(self.truck.excavator_material_bind_modify)
self.logger.info("挖机优先级修正")
self.logger.info(self.excavator.excavator_priority_coefficient)
except Exception as es:
self.logger.info("矿卡行程信息异常")
self.logger.info(es)
# 计算目的地
try:
# 1. 绑定调度
if truck_id in self.truck.truck_excavator_bind:
target = self.excavator.excavator_uuid_to_index_dict[self.truck.truck_excavator_bind[truck_id]]
self.logger.info("矿卡已绑定挖机")
# self.logger.info("cost_to_excavator")
# self.logger.info(self.cost_to_excavator)
# 2 正常调度
elif rule3 and rule4:
self.logger.info("正常调度")
transport_value = self._schedule_alg.truck_schedule(current_truck, "expected")
self.logger.info(f'行驶成本-含拥堵度的路径长度 {transport_value}')
excavator_exclude_modify = self.group.group_excavator_exclude_modify[truck_id]
self.logger.info(f'挖机设备禁止因子 {excavator_exclude_modify}')
self.logger.info(transport_value)
target = np.argmin(
transport_value.T
+ excavator_exclude_modify)
target = self.excavator.excavator_uuid_to_index_dict[
self.group.group_excavator_index_to_uuid_dict[group_id][target]]
# 3. 饱和度调度
else:
self.logger.info("饱和度调度")
# saturation_value = self._schedule_alg.saturation_schedule(current_truck)
saturation_value = self._schedule_alg.truck_schedule(current_truck, "saturation")
self.logger.info(f'驶往卸点饱和度价值 {saturation_value}')
target = np.argmax(saturation_value)
target = self.excavator.excavator_uuid_to_index_dict[
self.group.group_excavator_index_to_uuid_dict[group_id][target]]
except Exception as es:
self.logger.error(f"矿卡{truck_id}调度指令生成异常")
self.logger.info(es)
excavator_uuid_to_name_dict = get_value("excavator_uuid_to_name_dict")
self.logger.info(f"目的地:{excavator_uuid_to_name_dict[DeviceMap.excavator_index_to_uuid_dict[target]]}")
self.logger.info("==========================================================")
print(target)
# except Exception as es:
# self.logger.error("truck_schedule,error")
# self.logger.error(es)
return target
def schedule_construct(self):
"""
读取调度所需信息, 依次为动态派车车辆请求派车计划, 并写入redis缓存
:return: None
"""
global truck
global excavator
global dump
# self.reset()
# try:
# 读取所需信息
dynamic_truck_num = get_value("dynamic_truck_num")
truck_current_trip = self.truck.get_truck_current_trip()
truck_current_task = self.truck.get_truck_current_task()
# 获取矿卡最早可用时间
truck_avl_time = self.pre_sch.get_truck_avl_time()
# 根据矿卡最早可用时间顺序进行规划
temp = copy.deepcopy(truck_avl_time) - self.truck.truck_priority
try:
# 没有启动的矿卡加上一个很大的值,降低其优先级
for i in range(dynamic_truck_num):
task = truck_current_task[self.truck.truck_index_to_uuid_dict[i]]
if task == -2:
temp[i] = temp[i] + M
except Exception as es:
self.logger.error("矿卡排序启动异常")
self.logger.error(es)
index = np.argsort(temp.reshape(1, -1))
index = index.flatten()
# 对于在线矿卡已经赋予新的派车计划,更新其最早可用时间,及相关设备时间参数
for truck_index in index:
try:
self.truck_request(self.truck.truck_index_to_uuid_dict[truck_index])
except Exception as es:
self.logger.error("")
self.logger.error(es)
# # submission将调度结果写入redis
# self.submission.submit_to_redis(Seq)
def truck_request(self, truck_id):
truck_index = self.truck.truck_uuid_to_index_dict[truck_id]
truck_current_trip = self.truck.get_truck_current_trip()
truck_dispatch_seq = [truck_current_trip[truck_index][1], -1]
target_eq_index = self.truck_schedule(self.truck.truck_index_to_uuid_dict[truck_index])
truck_dispatch_seq[1] = target_eq_index
self.submission.truck_dispatch_to_redis(truck_id, truck_dispatch_seq)
class DispatchSubmission:
""" class for the submission calculated dispatch.
Description:
将调度结果按照指定格式传递到云端机群
Attribute:
"""
def __init__(self, dump, excavator, truck, group):
self.logger = self.logger = get_logger("zxt.submission")
self.dump = dump
self.excavator = excavator
self.truck = truck
self.group = group
def submit_to_redis(self, Seq):
"""
将调度结果输出到redis
:param Seq: (List[int]) 调度结果列表
:return: None
"""
for i in range(len(Seq)):
try:
try:
truck_id = self.truck.truck_index_to_uuid_dict[i]
group_id = self.group.dispatch_truck_group[truck_id]
record = {"truckId": self.truck.truck_index_to_uuid_dict[i]}
task = self.truck.get_truck_current_task()[self.truck.truck_index_to_uuid_dict[i]]
except Exception as es:
self.logger.error("调度结果写入异常-读取矿卡信息异常(uuid, group id, task)")
self.logger.error(es)
if task in [0, 1, 2]: # 卡车空载或在装载区出场前, 可变更卸载目的地
try:
item = (
session_mysql.query(Dispatch)
.filter_by(dump_id=DeviceMap.dump_index_to_uuid_dict[Seq[i][1]],
exactor_id=DeviceMap.excavator_index_to_uuid_dict[Seq[i][0]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0, ).first())
if item is None:
raise Exception("调度计划表与实时监控不匹配")
except Exception as es:
self.logger.error(es)
item = (
session_mysql.query(Dispatch)
.filter_by(truck_id=truck_id,
# group_id=group_id,
isauto=1, isdeleted=0, ).first())
try:
record["exactorId"] = item.exactor_id
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["dispatchId"] = item.id
record["isdeleted"] = False
record["creator"] = item.creator
record["createtime"] = item.createtime.strftime(
"%b %d, %Y %I:%M:%S %p")
redis5.set(self.truck.truck_index_to_uuid_dict[i], str(json.dumps(record)))
except Exception as es:
self.logger.error("调度结果写入异常-矿卡空载")
elif task in [3, 4, 5]: # 卡车重载或在卸载区出场前, 可变更装载目的地
try:
item = (
session_mysql.query(Dispatch)
.filter_by(exactor_id=DeviceMap.excavator_index_to_uuid_dict[Seq[i][1]],
dump_id=DeviceMap.dump_index_to_uuid_dict[Seq[i][0]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0, ).first())
if item is None:
raise Exception("调度计划表与实时监控不匹配")
except Exception as es:
self.logger.error(es)
item = (
session_mysql.query(Dispatch)
.filter_by(truck_id=truck_id,
# group_id=group_id,
isauto=1, isdeleted=0, ).first())
try:
record["exactorId"] = self.excavator.excavator_index_to_uuid_dict[Seq[i][1]]
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["dispatchId"] = item.id
record["isdeleted"] = False
record["creator"] = item.creator
record["createtime"] = item.createtime.strftime(
"%b %d, %Y %I:%M:%S %p")
redis5.set(self.truck.truck_index_to_uuid_dict[i], str(json.dumps(record)))
except Exception as es:
self.logger.error("调度结果写入异常-矿卡重载")
elif task == -2:
try:
try:
item = (
session_mysql.query(Dispatch)
.filter_by(exactor_id=DeviceMap.excavator_index_to_uuid_dict[Seq[i][1]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0).first())
if item is None:
raise Exception("调度计划表与实时监控不匹配")
self.logger.info(Seq)
self.logger.info(Seq[i][1])
self.logger.info(DeviceMap.excavator_index_to_uuid_dict[Seq[i][1]])
self.logger.info("item")
print(item.id, item.truck_id, item.exactor_id, item.dump_id)
except Exception as es:
self.logger.error(es)
item = (
session_mysql.query(Dispatch)
.filter_by(truck_id=truck_id,
# group_id=group_id,
isauto=1, isdeleted=0).first())
try:
record["exactorId"] = item.exactor_id
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["dispatchId"] = item.id
record["isdeleted"] = False
record["creator"] = item.creator
record["createtime"] = item.createtime.strftime(
"%b %d, %Y %I:%M:%S %p")
redis5.set(self.truck.truck_index_to_uuid_dict[i], str(json.dumps(record)))
except Exception as es:
self.logger.error("调度结果写入异常-矿卡故障或备停区-redis写入异常")
self.logger.error(es)
except Exception as es:
self.logger.error("调度结果写入异常-矿卡故障或备停区")
self.logger.error(es)
else:
pass
except Exception as es:
self.logger.error("调度结果写入异常")
self.logger.error(f"调度结果:{Seq}")
self.logger.error(es)
for i in range(get_value("dynamic_truck_num")):
print("dispatch_setting:")
print(redis5.get(self.truck.truck_index_to_uuid_dict[i]))
# except Exception as es:
# self.logger.error("更新不及时-1")
# self.logger.error(es)
def truck_dispatch_to_redis(self, truck_id, dispatch_seq):
"""
将truck_id对应矿卡派车计划写入redis
:param truck_id: (uuid) 矿卡uuid
:param dispatch_seq: (List[int]) 矿卡派车计划
:return: None
"""
try:
try:
group_id = self.group.dispatch_truck_group[truck_id]
record = {"truckId": truck_id}
task = self.truck.get_truck_current_task()[truck_id]
except Exception as es:
self.logger.error("调度结果写入异常-读取矿卡信息异常(uuid, group id, task)")
self.logger.error(es)
if task in [0, 1, 2]: # 卡车空载或在装载区出场前, 可变更卸载目的地
try:
item = (
session_mysql.query(Dispatch)
.filter_by(dump_id=DeviceMap.dump_index_to_uuid_dict[dispatch_seq[1]],
exactor_id=DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[0]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0, ).first())
if item is None:
raise Exception("调度计划表与实时监控不匹配")
except Exception as es:
self.logger.error(es)
item = (
session_mysql.query(Dispatch)
.filter_by(truck_id=truck_id,
# group_id=group_id,
isauto=1, isdeleted=0, ).first())
try:
record["exactorId"] = item.exactor_id
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["dispatchId"] = item.id
record["isdeleted"] = False
record["creator"] = item.creator
record["createtime"] = item.createtime.strftime(
"%b %d, %Y %I:%M:%S %p")
redis5.set(truck_id, str(json.dumps(record)))
except Exception as es:
self.logger.error("调度结果写入异常-矿卡空载")
elif task in [3, 4, 5]: # 卡车重载或在卸载区出场前, 可变更装载目的地
try:
item = (
session_mysql.query(Dispatch)
.filter_by(exactor_id=DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[1]],
dump_id=DeviceMap.dump_index_to_uuid_dict[dispatch_seq[0]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0, ).first())
if item is None:
raise Exception("调度计划表与实时监控不匹配")
except Exception as es:
self.logger.error(es)
item = (
session_mysql.query(Dispatch)
.filter_by(truck_id=truck_id,
# group_id=group_id,
isauto=1, isdeleted=0, ).first())
try:
record["exactorId"] = self.excavator.excavator_index_to_uuid_dict[dispatch_seq[1]]
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["dispatchId"] = item.id
record["isdeleted"] = False
record["creator"] = item.creator
record["createtime"] = item.createtime.strftime(
"%b %d, %Y %I:%M:%S %p")
redis5.set(truck_id, str(json.dumps(record)))
except Exception as es:
self.logger.error("调度结果写入异常-矿卡重载")
elif task == -2:
try:
try:
item = (
session_mysql.query(Dispatch)
.filter_by(exactor_id=DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[1]],
truck_id=truck_id,
group_id=group_id,
isauto=1, isdeleted=0).first())
if item is None:
raise Exception("调度计划表与实时监控不匹配")
self.logger.info(dispatch_seq)
self.logger.info(dispatch_seq[1])
self.logger.info(DeviceMap.excavator_index_to_uuid_dict[dispatch_seq[1]])
self.logger.info("item")
print(item.id, item.truck_id, item.exactor_id, item.dump_id)
except Exception as es:
self.logger.error(es)
item = (
session_mysql.query(Dispatch)
.filter_by(truck_id=truck_id,
# group_id=group_id,
isauto=1, isdeleted=0).first())
try:
record["exactorId"] = item.exactor_id
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["dispatchId"] = item.id
record["isdeleted"] = False
record["creator"] = item.creator
record["createtime"] = item.createtime.strftime(
"%b %d, %Y %I:%M:%S %p")
redis5.set(truck_id, str(json.dumps(record)))
except Exception as es:
self.logger.error("调度结果写入异常-矿卡故障或备停区-redis写入异常")
self.logger.error(es)
except Exception as es:
self.logger.error("调度结果写入异常-矿卡故障或备停区")
self.logger.error(es)
else:
pass
except Exception as es:
self.logger.error("调度结果写入异常")
self.logger.error(f"调度结果:{dispatch_seq}")
self.logger.error(es)
class PreSchedule:
""" class for the prediction of equipments' trip.
Description:
负责处理所有预测项的计算与更新
基于矿卡最近一次装卸载时间预测其抵达目的地时间
根据矿卡请求队列及抵达信息,计算设备最早可用时间
Attribute:
equipment class: truck, excavator, dump
schedule start time
equipment available time: truck, excavator, dump
"""
def __init__(self, truck, excavator, dump):
# 设备对象域
self.truck = truck
self.excavator = excavator
self.dump = dump
# 调度开始时间
self.start_time = datetime.now()
# 真实设备可用时间
self.truck_reach_dump = np.zeros(self.truck.get_truck_num())
self.truck_reach_excavator = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time = np.zeros(self.excavator.get_excavator_num())
self.dump_avl_time = np.zeros(self.dump.get_dump_num())
# 卡车完成装载及卸载时间(矿卡可用时间)
self.truck_avl_time = np.zeros(self.truck.get_truck_num())
self.logger = get_logger("zxt.pre_schedule")
def update_truck_reach_time(self):
"""
更新矿卡预计抵达目的地时间
:return:
excavator_avl_ls: (list) 驶往挖机的各矿卡抵达时间
dump_avl_ls: (list) 驶往卸点的各矿卡抵达时间
"""
try:
dynamic_excavator_num = self.excavator.get_excavator_num()
dumps = self.dump.get_dump_num()
trucks = self.truck.get_truck_num()
truck_current_task = self.truck.get_truck_current_task()
truck_current_trip = self.truck.get_truck_current_trip()
truck_reach_excavator = self.truck.get_truck_reach_excavator()
truck_reach_dump = self.truck.get_truck_reach_dump()
excavator_avl_ls = [[] for _ in range(dynamic_excavator_num)]
dump_avl_ls = [[] for _ in range(dumps)]
# self.logger.info("update_truck_reach_time-trucks")
# self.logger.info(trucks)
for i in range(trucks):
task = truck_current_task[self.truck.truck_index_to_uuid_dict[i]]
end_area_index = truck_current_trip[i][1]
# self.logger.info("update_truck_reach_time-truck_current_trip")
# self.logger.info(truck_current_trip)
if task in [0, 1]: # 卡车空载行驶或正在入场
reach_time = truck_reach_excavator[i]
excavator_avl_ls[end_area_index].append(
[reach_time, i, end_area_index]
)
elif task in [3, 4]: # 卡车重载行驶或正在入场
reach_time = truck_reach_dump[i]
dump_avl_ls[end_area_index].append([reach_time, i, end_area_index])
elif task == -2:
self.truck_avl_time[i] = (
datetime.now() - self.start_time
) / timedelta(hours=0, minutes=1, seconds=0)
except Exception as es:
self.logger.error("矿卡预计抵达时间计算异常")
self.logger.error(es)
return [], []
return excavator_avl_ls, dump_avl_ls
def update_excavator_avl_time(self, excavator_avl_ls):
"""
更新挖机预计可用时间
:param
excavator_avl_ls: (list) 驶往挖机的各矿卡抵达时间
:return:
excavator_avl_time: (array) 各挖机完成所有已分配矿卡装载的时间
"""
# 初始化挖机可用时间
self.excavator_avl_time = np.full(
get_value("dynamic_excavator_num"),
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0),
)
loading_time = self.excavator.get_loading_time()
loading_task_time = self.excavator.get_loading_task_time()
try:
now = float(
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0)
)
for reach_ls in excavator_avl_ls:
self.logger.info("update_excavator_avl_time-excavator_avl_ls")
self.logger.info(excavator_avl_ls)
if len(reach_ls) != 0:
reach_ls = np.array(reach_ls)
tmp = reach_ls[np.lexsort(reach_ls[:, ::-1].T)]
for i in range(len(tmp)):
excavator_index = int(tmp[i][2])
self.excavator_avl_time[excavator_index] = (
max(tmp[i][0], self.excavator_avl_time[excavator_index])
+ loading_task_time[excavator_index]
)
self.truck_avl_time[
int(tmp[i][1])
] = self.excavator_avl_time[excavator_index]
# # 若挖机可用时间严重偏离,进行修正
# if abs(self.excavator_avl_time[excavator_index] - now) > 60:
# self.truck_avl_time[int(tmp[i][1])] = now
# if abs(self.excavator_avl_time[excavator_index] - now) > 60:
# self.excavator_avl_time[excavator_index] = now
except Exception as es:
self.logger.error("挖机可用时间计算异常")
self.logger.error(es)
return self.excavator_avl_time
def update_dump_avl_time(self, dump_avl_ls):
"""
更新卸载设备预计可用时间
:param
dump_avl_ls: (list) 驶往卸点的各矿卡抵达时间
:return:
dump_avl_time: (array) 各卸点完成所有已分配矿卡卸载的时间
"""
dynamic_dump_num = self.dump.get_dump_num()
# 初始化卸载设备可用时间
self.dump_avl_time = np.full(
dynamic_dump_num,
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0),
)
unloading_time = self.dump.get_unloading_time()
unloading_task_time = self.dump.get_unloading_task_time()
try:
now = float(
(datetime.now() - self.start_time)
/ timedelta(hours=0, minutes=1, seconds=0)
)
for reach_ls in dump_avl_ls:
if len(reach_ls) != 0:
reach_ls = np.array(reach_ls)
tmp = reach_ls[np.lexsort(reach_ls[:, ::-1].T)]
for i in range(len(tmp)):
dump_index = int(tmp[i][2])
self.dump_avl_time[dump_index] = (
max(tmp[i][0], self.dump_avl_time[dump_index])
+ unloading_task_time[dump_index]
)
self.truck_avl_time[
int(tmp[i][1])
] = self.dump_avl_time[dump_index]
# # 若卸载设备可用时间严重偏离,进行修正
# if abs(self.dump_avl_time[dump_index] - now) > 60:
# self.dump_avl_time[dump_index] = now
# if abs(self.truck_avl_time[int(tmp[i][1])] - now) > 60:
# self.truck_avl_time[int(tmp[i][1])] = now
except Exception as es:
self.logger.error("卸载设备可用时间计算异常")
self.logger.error(es)
return self.dump_avl_time
def _reset(self):
"""
重置设备可用时间
:return:
"""
# 真实设备可用时间
self.truck_reach_dump = np.zeros(self.truck.get_truck_num())
self.truck_reach_excavator = np.zeros(self.truck.get_truck_num())
self.excavator_avl_time = np.zeros(self.excavator.get_excavator_num())
self.dump_avl_time = np.zeros(self.dump.get_dump_num())
# 卡车完成装载及卸载时间(矿卡可用时间)
self.truck_avl_time = np.zeros(self.truck.get_truck_num())
def get_dump_avl_time(self):
"""
获取卸载点最早可用时间
:return:
dump_avl_time: (array) 各卸点完成所有已分配矿卡卸载的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
dump_avl_time = self.update_dump_avl_time(dump_avl_ls)
return dump_avl_time
def get_excavator_avl_time(self, excavator_id=None):
"""
获取挖机最早可用时间
:param excavator_id: 挖机编号uuid
:return:
excavator_avl_time: (array) 各挖机完成所有已分配矿卡装载的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
if excavator_id is not None:
return self.update_excavator_avl_time(excavator_avl_ls) \
[self.excavator.excavator_uuid_to_index_dict[excavator_id]]
else:
return self.update_excavator_avl_time(excavator_avl_ls)
def get_truck_avl_time(self, truck_id=None):
"""
获取矿卡最早可用时间
:param truck_id: 矿卡编号uuid
:return: truck_avl_time: (array) 各矿卡完成当前装载或卸载任务的时间
"""
self._reset()
excavator_avl_ls, dump_avl_ls = self.update_truck_reach_time()
self.update_excavator_avl_time(excavator_avl_ls)
self.update_dump_avl_time(dump_avl_ls)
if truck_id is not None:
return self.truck_avl_time[self.truck.truck_uuid_to_index_dict[truck_id]]
else:
return self.truck_avl_time
......@@ -5,3 +5,7 @@
# @Site :
# @File : __init__.py
# @Software: PyCharm
from .excavator import ExcavatorInfo
from .dump import DumpInfo
from .truck import TruckInfo
......@@ -84,7 +84,7 @@ class DumpInfo(WalkManage):
# except Exception as es:
# self.logger.error(f"卸载设备 {dump_id} 卸载时间信息缺失, 已设为默认值(1min)")
# self.logger.error(es)
self.unloading_time[self.dump_uuid_to_index_dict[dump_id]] = 2.00
self.unloading_time[self.dump_uuid_to_index_dict[dump_id]] = 10.00
# print("average_unload_time: ", self.unloading_time[self.dump_uuid_to_index_dict[dump_id]])
# 更新卸载设备出入时间
......@@ -111,15 +111,16 @@ class DumpInfo(WalkManage):
# except Exception as es:
# self.logger.error(f"卸载设备 {dump_id} 出入场时间信息缺失, 已设为默认值(1min)")
# self.logger.error(es)
self.entrance_time[self.dump_uuid_to_index_dict[dump_id]] = 0.50
self.exit_time[self.dump_uuid_to_index_dict[dump_id]] = 0.50
self.entrance_time[self.dump_uuid_to_index_dict[dump_id]] = 0.75
self.exit_time[self.dump_uuid_to_index_dict[dump_id]] = 0.75
def update_dump_material(self):
self.dump_material = {}
for dump_id in get_value("dynamic_dump_set"):
try:
unload_area_id = session_mysql.query(Dispatch).filter_by(dump_id=dump_id, isauto=1, isdeleted=0).first().unload_area_id
dump_material_id = session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first().Material
# unload_area_id = session_mysql.query(DispatchSetting).filter_by(dump_id=dump_id, isauto=1, isdeleted=0).first().unload_area_id
unload_area_id = session_mysql.query(DispatchSetting).filter_by(dump_id=dump_id, isdeleted=0).first().unload_area_id
dump_material_id = list(session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first().Materials)
self.dump_material[dump_id] = dump_material_id
except Exception as es:
self.logger.error("卸点物料更新异常")
......
......@@ -82,7 +82,7 @@ class ExcavatorInfo(WalkManage):
self.logger.info(self.loading_time)
self.logger.info("excavator_uuid_to_index_dict")
self.logger.info(self.excavator_uuid_to_index_dict)
self.loading_time[self.excavator_uuid_to_index_dict[excavator_id]] = 1.00
self.loading_time[self.excavator_uuid_to_index_dict[excavator_id]] = 10.00
# 更新挖机设备出入时间
def update_excavator_entrance_exit_time(self):
......@@ -111,8 +111,8 @@ class ExcavatorInfo(WalkManage):
# self.logger.error(es)
self.entrance_time[
self.excavator_uuid_to_index_dict[excavator_id]
] = 0.50
self.exit_time[self.excavator_uuid_to_index_dict[excavator_id]] = 0.50
] = 0.75
self.exit_time[self.excavator_uuid_to_index_dict[excavator_id]] = 0.75
# 读取出入场时间
def get_loading_task_time(self):
......@@ -131,7 +131,8 @@ class ExcavatorInfo(WalkManage):
self.logger.info(self.dynamic_excavator_set)
for excavator_id in self.dynamic_excavator_set:
try:
load_area_id = session_mysql.query(Dispatch).filter_by(exactor_id=excavator_id, isdeleted=0, isauto=1).first().load_area_id
# load_area_id = session_mysql.query(DispatchSetting).filter_by(exactor_id=excavator_id, isdeleted=0, isauto=1).first().load_area_id
load_area_id = session_mysql.query(DispatchSetting).filter_by(exactor_id=excavator_id, isdeleted=0).first().load_area_id
excavator_material_id = session_postgre.query(DiggingWorkArea).filter_by(Id=load_area_id).first().Material
self.excavator_material[excavator_id] = excavator_material_id
except Exception as es:
......
......@@ -135,6 +135,8 @@ class TruckInfo(WalkManage):
key_value_dict = redis2.hgetall(item) # reids str可以自动转为bytes
device_type = int(key_value_dict[str_to_byte("type")])
if device_type == 1:
bb = self.dynamic_truck_set
cc = truck_name_to_uuid_dict
if truck_name_to_uuid_dict[item] in self.dynamic_truck_set:
currentTask = int(key_value_dict[str_to_byte("currentTask")])
self.truck_current_task[
......@@ -259,6 +261,7 @@ class TruckInfo(WalkManage):
# 初始化矿卡行程, -1代表备停区
self.truck_current_trip = np.full((self.dynamic_truck_num, 2), -1)
ab = self.dynamic_truck_num
for i in range(self.dynamic_truck_num):
try:
session_mysql.commit()
......@@ -270,24 +273,36 @@ class TruckInfo(WalkManage):
.filter_by(truck_id=truck_id, isdeleted=0)
.first()
)
if task in empty_task_set + heavy_task_set and item is None:
# item = (
# session_mysql.query(DispatchSetting)
# .filter_by(truck_id=truck_id, isdeleted=0)
# .first()
# )
point = empty_task_set
point2 = heavy_task_set
if task in (empty_task_set + heavy_task_set) and item is None:
raise Exception(f"矿卡 {truck_id} 配对关系异常")
except Exception as es:
self.logger.error("配对关系异常")
self.logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
continue
try:
# try:
load_area_uuid_to_index_dict = get_value("load_area_uuid_to_index_dict")
unload_area_uuid_to_index_dict = get_value("unload_area_uuid_to_index_dict")
aa = task
tt = truck_id
# 若矿卡状态为空运
if task in [0, 1, 2]: # 矿卡空载或仍未出装载区
# last_unload_time = self.relative_last_unload_time[
# self.truck_index_to_uuid_dict[i]
# ]
bb = self.relative_last_unload_time
last_unload_time = self.relative_last_unload_time[
self.truck_index_to_uuid_dict[i]
truck_id
]
if item.dump_id in DeviceMap.dump_uuid_to_unload_area_uuid_dict:
start_area_id = self.dump_uuid_to_unload_area_uuid_dict[item.dump_id]
start_area_index = unload_area_uuid_to_index_dict[start_area_id]
......@@ -347,6 +362,13 @@ class TruckInfo(WalkManage):
self.truck_current_trip[i] = [start_eq_index, end_eq_index]
self.logger.info("walk_time_to_unload_area")
self.logger.info(walk_time_to_unload_area)
self.logger.info("end_area_index")
self.logger.info(end_area_index)
self.logger.info("start_area_index")
self.logger.info(start_area_index)
self.cur_truck_reach_dump[i] = (
last_load_time
+ walk_time_to_unload_area[end_area_index][start_area_index]
......@@ -364,9 +386,9 @@ class TruckInfo(WalkManage):
# end_eqp_index = excavator.excavator_uuid_to_index_dict[item.exactor_id]
# self.excavator_hold_truck_num[end_eqp_index] = self.excavator_hold_truck_num[end_eqp_index] + 1
pass
except Exception as es:
self.logger.error("矿卡行程读取异常")
self.logger.error(es)
# except Exception as es:
# self.logger.error("矿卡行程读取异常")
# self.logger.error(es)
# print("self.dump_hold_truck_num")
# print(self.dump_hold_truck_num)
......@@ -375,8 +397,8 @@ class TruckInfo(WalkManage):
# print(self.excavator_hold_truck_num)
self.truck_current_trip.flatten()
print("当前矿卡行程:")
print(self.truck_current_trip)
self.logger.info("当前矿卡行程:")
self.logger.info(self.truck_current_trip)
def update_eqp_hold_truck(self):
......@@ -384,12 +406,20 @@ class TruckInfo(WalkManage):
try:
session_mysql.commit()
truck_id = self.truck_index_to_uuid_dict[i]
aa = self.truck_index_to_uuid_dict
bb = self.truck_current_task
task = self.truck_current_task[self.truck_index_to_uuid_dict[i]]
# item = (
# session_mysql.query(EquipmentPair)
# .filter_by(truck_id=truck_id, isdeleted=0)
# .first()
# )
item = (
session_mysql.query(EquipmentPair)
session_mysql.query(DispatchSetting)
.filter_by(truck_id=truck_id, isdeleted=0)
.first()
)
if task in empty_task_set + heavy_task_set and item is None: # 矿卡处于正常工作状态, 但查询不到派车计划
raise Exception(f"矿卡 {truck_id} 配对关系异常")
except Exception as es:
......@@ -571,7 +601,6 @@ class TruckInfo(WalkManage):
def update_truck_material(self):
try:
self.truck_material_bind = {}
self.update_truck_excavator_bind()
self.update_truck_dump_area_bind()
......@@ -580,11 +609,10 @@ class TruckInfo(WalkManage):
self.dump_material_bind_modify = np.full((self.dynamic_truck_num, get_value("dynamic_dump_num")), 0)
for truck_id in self.dynamic_truck_set:
if truck_id in self.truck_dump_bind:
unload_area_id = self.truck_dump_bind[truck_id]
try:
dump_material_id = session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first().Material
dump_material_id = session_postgre.query(DumpArea).filter_by(Id=unload_area_id).first().Materials
except Exception as es:
session_postgre.rollback()
session_mysql.rollback()
......@@ -674,6 +702,22 @@ class TruckInfo(WalkManage):
self.dynamic_truck_num = get_value("dynamic_truck_num")
# 更新矿卡集合
self.dynamic_truck_set = get_value("dynamic_truck_set")
# 矿卡抵达卸载设备时间
self.cur_truck_reach_dump = np.zeros(self.dynamic_truck_num)
# 矿卡抵达挖机时间
self.cur_truck_reach_excavator = np.zeros(self.dynamic_truck_num)
# 矿卡最后装载/卸载时间
self.last_load_time = {}
self.last_unload_time = {}
# 相对矿卡最后装载/卸载时间
self.relative_last_load_time = {}
self.relative_last_unload_time = {}
# 矿卡当前任务
self.truck_current_task = {}
# 矿卡当前行程(第一列为出发地序号, 第二列为目的地序号)
self.truck_current_trip = np.full((self.dynamic_truck_num, 2), -1)
# 矿卡不可用列表
self.truck_disable_list = []
# 矿卡挖机绑定关系
self.truck_excavator_bind = {}
# 矿卡卸点绑定关系
......
aaaaaa
......@@ -357,22 +357,19 @@ class WalkManage(DeviceMap):
# 计算设备路网距离及行走时间
try:
n = dynamic_dump_num
m = dynamic_excavator_num
for i in range(dynamic_dump_num):
for j in range(dynamic_excavator_num):
cls.distance_to_excavator[i][j] = cls.distance_to_load_area[
cls.dump_index_to_unload_area_index_dict[i]
][cls.excavator_index_to_load_area_index_dict[j]]
cls.walk_time_to_excavator[i][j] = cls.walk_time_to_load_area[
cls.dump_index_to_unload_area_index_dict[i]
][cls.excavator_index_to_load_area_index_dict[j]]
cls.distance_to_dump[i][j] = cls.distance_to_unload_area[
cls.dump_index_to_unload_area_index_dict[i]
][cls.excavator_index_to_load_area_index_dict[j]]
cls.walk_time_to_dump[i][j] = cls.walk_time_to_unload_area[
cls.dump_index_to_unload_area_index_dict[i]
][cls.excavator_index_to_load_area_index_dict[j]]
cls.distance_to_excavator[i][j] = cls.distance_to_load_area[cls.dump_index_to_unload_area_index_dict[i]][cls.excavator_index_to_load_area_index_dict[j]]
cls.walk_time_to_excavator[i][j] = cls.walk_time_to_load_area[cls.dump_index_to_unload_area_index_dict[i]][cls.excavator_index_to_load_area_index_dict[j]]
cls.distance_to_dump[i][j] = cls.distance_to_unload_area[cls.dump_index_to_unload_area_index_dict[i]][cls.excavator_index_to_load_area_index_dict[j]]
cls.walk_time_to_dump[i][j] = cls.walk_time_to_unload_area[cls.dump_index_to_unload_area_index_dict[i]][cls.excavator_index_to_load_area_index_dict[j]]
except Exception as es:
logger.error("设备路网信息异常异常")
logger.error("设备路网信息异常")
logger.error(es)
try:
......@@ -421,7 +418,6 @@ def get_global_para_from_cache(cache):
global_dict = cache.get("global_dict")
if global_dict is None:
print("here2")
global_period_para_update()
cache.set("global_dict", global_dict, timeout=5 * 60)
......@@ -520,6 +516,16 @@ def global_period_para_update():
global_dict["distance_park_to_excavator"] = WalkManage.distance_park_to_excavator
global_dict["distance_to_dump"] = WalkManage.distance_to_dump
global_dict["dump_uuid_to_index_dict"] = WalkManage.dump_uuid_to_index_dict
global_dict["dump_index_to_uuid_dict"] = WalkManage.dump_index_to_uuid_dict
global_dict["excavator_uuid_to_index_dict"] = WalkManage.excavator_uuid_to_index_dict
global_dict["excavator_index_to_uuid_dict"] = WalkManage.excavator_index_to_uuid_dict
global_dict["dump_uuid_to_unload_area_uuid_dict"] = WalkManage.dump_uuid_to_unload_area_uuid_dict
global_dict["excavator_uuid_to_load_area_uuid_dict"] = WalkManage.excavator_uuid_to_load_area_uuid_dict
# logger.info("walk_manage_para")
# logger.info("distance_to_excavator")
# logger.info(walk_manage.distance_to_excavator)
......
......@@ -112,7 +112,7 @@ class PriorityController:
for dump_id in get_value("dynamic_dump_set"):
for excavator_id in get_value("dynamic_excavator_set"):
try:
item = session_mysql.query(Dispatch).filter_by(dump_id=dump_id, exactor_id=excavator_id, isauto=1,
item = session_mysql.query(DispatchSetting).filter_by(dump_id=dump_id, exactor_id=excavator_id, isauto=1,
isdeleted=0).first()
except Exception as es:
session_postgre.rollback()
......
......@@ -14,7 +14,49 @@ from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
import sched
import time
from dispatcher import Dispatcher, PreSchedule
from core.dispatcher import Dispatcher
from core.schedule import PreSchedule
from data.dispatchInfo import DispatchInfo
def direct2redis():
"""
直接读取数据库写入redis
:return: None
"""
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
try:
truck_disp = {}
for item in session_mysql.query(DispatchSetting).all():
if item.truck_id not in truck_disp:
record = {"truckId": item.truck_id}
record["id"] = item.id
record["exactorId"] = item.exactor_id
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["groupId"] = item.group_id
record["isdeleted"] = False
record["isTemp"] = False
record["haulFlag"] = -1
record["groupName"] = item.group_id
logger.info("调度结果")
logger.info(record)
redis5.set(item.truck_id, str(json.dumps(record)))
except Exception as es:
logger.error(es)
session_postgre.rollback()
session_mysql.rollback()
def process(dispatcher):
......@@ -24,18 +66,21 @@ def process(dispatcher):
:return: None
"""
# # 直接读取数据库写入redis
# direct2redis()
try:
# 更新周期参数
logger.info("#####################################周期更新开始#####################################")
global_period_para_update()
if get_value("dynamic_dump_num") * get_value("dynamic_excavator_num") == 0:
raise Exception("无动态派车计划可用")
return
if get_value("dynamic_truck_num") == 0:
raise Exception("无动态派车可用矿卡")
return
# if get_value("dynamic_dump_num") * get_value("dynamic_excavator_num") == 0:
# raise Exception("无动态派车计划可用")
# return
# if get_value("dynamic_truck_num") == 0:
# raise Exception("无动态派车可用矿卡")
# return
# 清空数据库缓存
session_mysql.commit()
......@@ -45,18 +90,80 @@ def process(dispatcher):
session_postgre.commit()
session_postgre.flush()
# 周期更新
dispatcher.dispatcher_period_update()
# 调度计算
dispatcher.schedule_construct()
global_period_para_update()
# 更新调度信息
DispatchInfo.reset()
DispatchInfo.update_device_group_structure()
DispatchInfo.update_route_distance()
DispatchInfo.update_group_mode()
DispatchInfo.update_group_name()
# logger.info
# group_set = set()
#
# # device group structure
# load_excavator_dict = {} # 装载区id-->>电铲编号的映射
# excavator_load_dict = {} # 电铲编号->>装载区id的映射
#
# group_excavator_dict = {} # team_id -> dict {[excavator_id, excavator_id], ...}
# excavator_group_dict = {} # excavator_id -> team_id 问题:多个key值对应一个value值
#
# group_dump_dict = {} # team_id -> dict {unload_area_id, unload_area_id, ...}
# dump_group_dict = {} # unload_area_id -> team_id
#
# group_truck_dict = {} # team_id -> dict # {group_id:[truck_id,truck_id],...}
# truck_group_dict = {} # truck_id -> team_id
#
# # group feature
# group_mode = {} # 数据格式: {team_id:mode_code}
#
# # route_distance(路网距离)
# load_distance = {}
# unload_distance = {}
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)
# logger.info("load_excavator_dict")
# logger.info(DispatchInfo.load_excavator_dict)
# logger.info("excavator_load_dict")
# logger.info(DispatchInfo.excavator_load_dict)
# logger.info(DispatchInfo.excavator_group_dict)
# logger.info(DispatchInfo.dump_group_dict)
# logger.info(DispatchInfo.truck_group_dict)
# 调度生成
dispatcher.period_update()
dispatcher.group_generate()
dispatcher.group_info_update()
dispatcher.group_dispatch()
logger.info("#####################################周期更新结束#####################################")
except Exception as es:
logger.error("最外层异常捕获")
logger.error(es)
direct2redis()
def perform(inc, dispatcher):
......@@ -103,7 +210,7 @@ if __name__ == "__main__":
pre_sch = PreSchedule(truck, excavator, dump)
# 实例化矿卡调度器
dispatcher = Dispatcher(dump, excavator, truck, pre_sch, False)
dispatcher = Dispatcher(truck, dump, excavator, pre_sch, False)
logger.info(" ")
logger.info("调度系统启动")
......
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2021/7/21 16:45
# @Author : Opfer
# @Site :
# @File : realtime_dispatch.py
# @Software: PyCharm
# 实时调度模块
from para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
import sched
import time
from core.dispatcher import Dispatcher
from core.schedule import PreSchedule
from data.dispatchInfo import DispatchInfo
def direct2redis():
"""
直接读取数据库写入redis
:return: None
"""
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
truck_disp = {}
for item in session_mysql.query(DispatchSetting).all():
if item.truck_id not in truck_disp:
record = {"truckId": item.truck_id}
record["id"] = item.id
record["exactorId"] = item.exactor_id
record["dumpId"] = item.dump_id
record["loadAreaId"] = item.load_area_id
record["unloadAreaId"] = item.unload_area_id
record["groupId"] = item.group_id
record["isdeleted"] = False
record["isTemp"] = False
record["haulFlag"] = -1
record["groupName"] = item.group_id
logger.info("调度结果")
logger.info(record)
redis5.set(item.truck_id, str(json.dumps(record)))
def process(dispatcher):
"""
周期调度进程
:param dispatcher: (Dispatch Class) 矿卡调度类对象
:return: None
"""
# try:
# 更新周期参数
logger.info("#####################################周期更新开始#####################################")
global_period_para_update()
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
global_period_para_update()
# 更新调度信息
DispatchInfo.reset()
DispatchInfo.update_device_group_structure()
DispatchInfo.update_route_distance()
DispatchInfo.update_group_mode()
DispatchInfo.update_group_name()
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)
# logger.info("load_excavator_dict")
# logger.info(DispatchInfo.load_excavator_dict)
# logger.info("excavator_load_dict")
# logger.info(DispatchInfo.excavator_load_dict)
# logger.info(DispatchInfo.excavator_group_dict)
# logger.info(DispatchInfo.dump_group_dict)
# logger.info(DispatchInfo.truck_group_dict)
# 调度生成
dispatcher.period_update()
dispatcher.group_generate()
dispatcher.group_info_update()
dispatcher.group_dispatch()
logger.info("#####################################周期更新结束#####################################")
# except Exception as es:
# logger.error("最外层异常捕获")
# logger.error(es)
def perform(inc, dispatcher):
"""
控制程序循环执行
:param inc: (int) 循环周期, 单位, 秒
:param dispatcher: (Dispatch Class) 矿卡调度类对象
:return: None
"""
scheduler.enter(inc, 0, perform, (inc, dispatcher))
process(dispatcher)
def main(inc, dispatcher):
"""
程序循环入口函数
:param inc: (int) 循环周期, 单位, 秒
:param dispatcher: (Dispatch Class) 矿卡调度类对象
:return: None
"""
scheduler.enter(0, 0, perform, (inc, dispatcher))
scheduler.run()
if __name__ == "__main__":
# 初始化日志
set_log()
# 获取日志器
logger = get_logger("zxt.main")
# 全局参数更新
global_period_para_update()
# 实例化设备对象
dump = DumpInfo()
excavator = ExcavatorInfo()
truck = TruckInfo(dump, excavator)
# 实例化程序调度器
scheduler = sched.scheduler(time.time, time.sleep)
# 实例化调度预测器
pre_sch = PreSchedule(truck, excavator, dump)
# 实例化矿卡调度器
dispatcher = Dispatcher(truck, dump, excavator, pre_sch, False)
logger.info(" ")
logger.info("调度系统启动")
main(30, dispatcher)
......@@ -67,7 +67,7 @@ def set_log():
# timefilehandler = logging.handlers.TimedRotatingFileHandler(log_path + "/dispatch.log", when='M', interval=1, backupCount=60)
filehandler = logging.handlers.RotatingFileHandler(log_path + "/dispatch.log", maxBytes=3*1024*1024, backupCount=10, encoding="utf-8")
filehandler = logging.handlers.RotatingFileHandler(log_path + "/dispatch.log", maxBytes=30*1024*1024, backupCount=10, encoding="utf-8")
# filehandler = logging.handlers.RotatingFileHandler("./Logs/dispatch.log", maxBytes=3 * 1024 * 1024, backupCount=10, encoding="utf-8")
# 设置后缀名称,跟strftime的格式一样
filehandler.suffix = "%Y-%m-%d_%H-%M.log"
......@@ -94,59 +94,6 @@ pool2 = ConnectionPool(host=redis_config["host"], db=2, port=6379, password=redi
redis2 = StrictRedis(connection_pool=pool2)
# 数据库连接设置
########################################################################################################################
# 创建对象的基类:
Base = declarative_base()
sql_str = str("mysql+mysqlconnector://" + mysql_config["user"] + ":%s@" + mysql_config["host"] + \
":" + mysql_config["port"] + "/" + mysql_config["database"])
postgre_str = str("postgresql://" + postgre_config["user"] + ":%s@" + postgre_config["host"] + \
":" + postgre_config["port"] + "/" + postgre_config["database"])
try:
engine_mysql = create_engine(
# "mysql+mysqlconnector://root:%s@192.168.28.111:3306/waytous"
# % quote("Huituo@123")
# "mysql+mysqlconnector://" + mysql_config["user"] + ":" + mysql_config["password"] + "@" + mysql_config[
# "host"] + ":" + mysql_config["port"] + "/" + mysql_config["database"]
sql_str % quote(mysql_config["password"])
)
engine_postgre = create_engine(
# "postgresql://postgres:%s@192.168.28.111:5432/shenbao_2021520"
# % quote("Huituo@123")
# "postgresql://" + postgre_config["user"] + ":" + postgre_config["password"] + "@" + postgre_config[
# "host"] + ":" + postgre_config["port"] + "/" + postgre_config["database"]
postgre_str % quote(postgre_config["password"])
)
# 创建DBsession_mysql类型:
DBsession_mysql = sessionmaker(bind=engine_mysql)
DBsession_mysql = scoped_session(DBsession_mysql)
DBsession_postgre = sessionmaker(bind=engine_postgre)
DBsession_postgre = scoped_session(DBsession_postgre)
# 创建session_mysql对象:
session_mysql = DBsession_mysql()
session_mysql.expire_on_commit = False
session_postgre = DBsession_postgre()
session_postgre.expire_on_commit = False
except Exception as es:
logger.error("数据库连接失败")
logger.error(es)
def str_to_byte(item):
return bytes(item, encoding='utf8')
......
......@@ -152,7 +152,8 @@ def update_deveices_map(unload_area_uuid_to_index_dict, load_area_uuid_to_index_
excavator_num = 0
dump_num = 0
for item in (
session_mysql.query(Dispatch).filter_by(isdeleted=0, isauto=1).all()
# session_mysql.query(DispatchSetting).filter_by(isdeleted=0, isauto=1).all()
session_mysql.query(DispatchSetting).filter_by(isdeleted=0).all()
):
# excavator_id <-> excavator_index
# dump_id <-> dump_index
......@@ -227,7 +228,6 @@ def update_truck_uuid_index_map(dynamic_truck_set):
"truck_index_to_uuid_dict": truck_index_to_uuid_dict,
}
def update_total_truck():
# 矿卡集合
truck_list = []
......@@ -238,13 +238,11 @@ def update_total_truck():
.filter_by(device_type=1, isdeleted=0)
.all()
)
# for item in query:
# json_value = json.loads(redis2.get(item.equipment_id))
# is_online = json_value.get('isOnline')
# if is_online:
# truck_list.append(item.id)
for item in query:
truck_list.append(item.id)
......@@ -262,13 +260,27 @@ def update_total_truck():
def update_dynamic_truck():
dynamic_truck_list = []
# try:
# query = np.array(
# session_mysql.query(Dispatch).filter_by(isauto=1, isdeleted=0).all()
# )
#
# for item in query:
# if item.truck_id is not None:
# dynamic_truck_list.append(item.truck_id)
#
# except Exception as es:
# logger.error(es)
# logger.error("动态调度矿卡读取异常")
# session_postgre.rollback()
# session_mysql.rollback()
try:
query = np.array(
session_mysql.query(Dispatch).filter_by(isauto=1, isdeleted=0).all()
session_mysql.query(DispatchSetting).filter_by(isdeleted=0).all()
)
for item in query:
if item.truck_id is not None:
# if item.truck_id is not None and item.truck_id not in dynamic_truck_list:
dynamic_truck_list.append(item.truck_id)
except Exception as es:
......@@ -286,7 +298,7 @@ def update_fixdisp_truck():
try:
query = np.array(
session_mysql.query(Dispatch).filter_by(isauto=0, isdeleted=0).all()
session_mysql.query(DispatchSetting).filter_by(isauto=0, isdeleted=0).all()
)
for item in query:
......@@ -308,8 +320,8 @@ def update_fixdisp_truck():
for item in query:
fixed_truck_list.append(item.id)
if len(fixed_truck_list) < 1:
raise Exception("无固定派车计划可用-固定派车矿卡集合读取异常")
# if len(fixed_truck_list) < 1:
# raise Exception("无固定派车计划可用-固定派车矿卡集合读取异常")
except Exception as es:
logger.info("派车计划读取")
logger.error(es)
......@@ -322,9 +334,8 @@ def update_autodisp_excavator():
# 用于动态派车的挖机集合
dynamic_excavator_list = []
try:
for item in (
session_mysql.query(Dispatch).filter_by(isdeleted=0, isauto=1).all()
):
for item in (session_mysql.query(DispatchSetting).filter_by().all()):
if item.exactor_id not in dynamic_excavator_list:
dynamic_excavator_list.append(item.exactor_id)
if len(dynamic_excavator_list) < 1:
raise Exception("无动态派车计划可用-动态派车挖机/卸载设备集合读取异常")
......@@ -340,9 +351,8 @@ def update_autodisp_dump():
# 用于动态调度的卸载点集合
dynamic_dump_list = []
try:
for item in (
session_mysql.query(Dispatch).filter_by(isdeleted=0, isauto=1).all()
):
for item in (session_mysql.query(DispatchSetting).filter_by().all()):
if item.dump_id not in dynamic_dump_list:
dynamic_dump_list.append(item.dump_id)
if len(dynamic_dump_list) < 1:
raise Exception("无动态派车计划可用-动态派车挖机/卸载设备集合读取异常")
......@@ -386,305 +396,3 @@ def update_park_area():
session_postgre.rollback()
session_mysql.rollback()
return park_area_list
# def build_work_area_uuid_index_map():
# # load_area_id <-> load_area_index
# # unload_area_id <-> unload_area_index
# load_area_uuid_to_index_dict = {}
# unload_area_uuid_to_index_dict = {}
# load_area_index_to_uuid_dict = {}
# unload_area_index_to_uuid_dict = {}
#
# unload_area_num = 0
# load_area_num = 0
#
# try:
# for item in session_postgre.query(WalkTime).all():
# load_area = str(item.load_area_id)
# unload_area = str(item.unload_area_id)
# if load_area not in load_area_uuid_to_index_dict:
# load_area_uuid_to_index_dict[load_area] = load_area_num
# load_area_index_to_uuid_dict[load_area_num] = load_area
# load_area_num = load_area_num + 1
# if unload_area not in unload_area_uuid_to_index_dict:
# unload_area_uuid_to_index_dict[unload_area] = unload_area_num
# unload_area_index_to_uuid_dict[unload_area_num] = unload_area
# unload_area_num = unload_area_num + 1
# if unload_area_num < 1 or load_area_num < 1:
# raise Exception("无路网信息")
# except Exception as es:
# logger.error("路网读取")
# logger.error(es)
# return (
# load_area_uuid_to_index_dict,
# unload_area_uuid_to_index_dict,
# load_area_index_to_uuid_dict,
# unload_area_index_to_uuid_dict,
# )
#
#
# def build_park_uuid_index_map():
# # park_id <-> park_index
# park_uuid_to_index_dict = {}
# park_index_to_uuid_dict = {}
#
# park_num = 0
#
# try:
# for item in session_postgre.query(WalkTimePark).all():
# park = str(item.park_area_id)
# if park not in park_uuid_to_index_dict:
# park_uuid_to_index_dict[park] = park_num
# park_index_to_uuid_dict[park_num] = park
# park_num = park_num + 1
# if park_num < 1:
# raise Exception("无备停区路网信息")
# except Exception as es:
# logger.info("备停区路网读取")
# logger.error(es)
#
# return park_uuid_to_index_dict, park_index_to_uuid_dict
#
#
# def build_truck_uuid_name_map():
# # truck_id <-> truck_name
# truck_uuid_to_name_dict = {}
# truck_name_to_uuid_dict = {}
#
# try:
# for item in session_mysql.query(Equipment).filter_by(device_type=1).all():
# truck_id = item.id
# truck_name = item.equipment_id
#
# truck_name_to_uuid_dict[truck_name] = truck_id
# truck_uuid_to_name_dict[truck_id] = truck_name
# if len(truck_uuid_to_name_dict) < 1 or len(truck_name_to_uuid_dict) < 1:
# raise Exception("无矿卡设备可用-矿卡设备映射异常")
# except Exception as es:
# logger.warning(es)
# return truck_uuid_to_name_dict, truck_name_to_uuid_dict
#
#
# def update_deveices_map(unload_area_uuid_to_index_dict, load_area_uuid_to_index_dict):
# excavator_uuid_to_index_dict = {} # 用于将Excavator表中的area_id映射到index
# dump_uuid_to_index_dict = {} # 用于将Dump表中的area_id映射到index
# excavator_index_to_uuid_dict = {} # 用于将index映射到Excavator表中的area_id
# dump_index_to_uuid_dict = {} # 用于将index映射到Dump表中的area_id
#
# dump_uuid_to_unload_area_uuid_dict = {}
# excavator_uuid_to_load_area_uuid_dict = {}
# excavator_index_to_load_area_index_dict = {}
# dump_index_to_unload_area_index_dict = {}
#
# try:
# excavator_num = 0
# dump_num = 0
# for item in (
# session_mysql.query(Dispatch).filter_by(isdeleted=0, isauto=1).all()
# ):
# # excavator_id <-> excavator_index
# # dump_id <-> dump_index
# # excavator_id <-> load_area_id
# # dump_id <-> unload_area_id
# # excavator_index <-> load_area_index
# # dump_index <-> unload_area_index
# excavator_id = item.exactor_id
# load_area_id = item.load_area_id
# unload_area_id = item.unload_area_id
# dump_id = item.dump_id
# if dump_id not in dump_uuid_to_unload_area_uuid_dict:
# dump_uuid_to_index_dict[dump_id] = dump_num
# dump_index_to_uuid_dict[dump_num] = dump_id
# dump_uuid_to_unload_area_uuid_dict[dump_id] = unload_area_id
# dump_index_to_unload_area_index_dict[
# dump_uuid_to_index_dict[dump_id]
# ] = unload_area_uuid_to_index_dict[unload_area_id]
# dump_num = dump_num + 1
# if excavator_id not in excavator_uuid_to_index_dict:
# excavator_uuid_to_index_dict[excavator_id] = excavator_num
# excavator_index_to_uuid_dict[excavator_num] = excavator_id
# excavator_uuid_to_load_area_uuid_dict[excavator_id] = load_area_id
# excavator_index_to_load_area_index_dict[
# excavator_uuid_to_index_dict[excavator_id]
# ] = load_area_uuid_to_index_dict[load_area_id]
# excavator_num = excavator_num + 1
# if excavator_num < 1 or dump_num < 1:
# raise Exception("无动态派车计划可用-动态派车挖机/卸载设备映射失败")
# except Exception as es:
# logger.error("卸载区信息异常")
# logger.error(es)
#
# logger.info("excavator_index_to_load_area_index_dict")
# logger.info(excavator_index_to_load_area_index_dict)
#
# logger.info("load_area_uuid_to_index_dict")
# logger.info(load_area_uuid_to_index_dict)
# logger.info("static_excavator_uuid_to_index_dict")
# logger.info(excavator_uuid_to_index_dict)
#
# return {
# "excavator_uuid_to_index_dict": excavator_uuid_to_index_dict,
# "dump_uuid_to_index_dict": dump_uuid_to_index_dict,
# "excavator_index_to_uuid_dict": excavator_index_to_uuid_dict,
# "dump_index_to_uuid_dict": dump_index_to_uuid_dict,
# "dump_uuid_to_unload_area_uuid_dict": dump_uuid_to_unload_area_uuid_dict,
# "excavator_uuid_to_load_area_uuid_dict": excavator_uuid_to_load_area_uuid_dict,
# "excavator_index_to_load_area_index_dict": excavator_index_to_load_area_index_dict,
# "dump_index_to_unload_area_index_dict": dump_index_to_unload_area_index_dict,
# }
#
#
# def update_truck_uuid_index_map(dynamic_truck_set):
# truck_uuid_to_index_dict = {}
# truck_index_to_uuid_dict = {}
#
# # truck_id <-> truck_index
# truck_num = 0
# for truck_id in dynamic_truck_set:
# truck_uuid_to_index_dict[truck_id] = truck_num
# truck_index_to_uuid_dict[truck_num] = truck_id
# truck_num = truck_num + 1
#
# logger.info("static_data_process.py-truck_uuid_to_index_dict")
# logger.info(truck_uuid_to_index_dict)
#
# return {
# "truck_uuid_to_index_dict": truck_uuid_to_index_dict,
# "truck_index_to_uuid_dict": truck_index_to_uuid_dict,
# }
#
#
# def update_total_truck():
# # 矿卡集合
# truck_list = []
#
# try:
# query = np.array(
# session_mysql.query(Equipment)
# .filter_by(device_type=1, isdeleted=0)
# .all()
# )
#
# # for item in query:
# # json_value = json.loads(redis2.get(item.equipment_id))
# # is_online = json_value.get('isOnline')
# # if is_online:
# # truck_list.append(item.id)
#
# for item in query:
# truck_list.append(item.id)
#
# if len(truck_list) < 1:
# raise Exception("无矿卡设备可用-矿卡集合读取异常")
# except Exception as es:
# logger.info("矿卡读取")
# logger.error(es)
#
# return truck_list
#
#
# def update_dynamic_truck():
# dynamic_truck_list = []
#
# try:
# query = np.array(
# session_mysql.query(Dispatch).filter_by(isauto=1, isdeleted=0).all()
# )
#
# for item in query:
# if item.truck_id is not None:
# dynamic_truck_list.append(item.truck_id)
#
# except Exception as es:
# logger.error(es)
# logger.error("动态调度矿卡读取异常")
#
# return set(dynamic_truck_list)
#
#
# def update_fixdisp_truck():
# # 固定派车矿卡集合
# fixed_truck_list = []
#
# try:
# query = np.array(
# session_mysql.query(Dispatch).filter_by(isauto=0, isdeleted=0).all()
# )
#
# for item in query:
# fixed_truck_list.append(item.truck_id)
#
# rule5 = session_mysql.query(DispatchRule).filter_by(id=5).first().disabled
#
# if not rule5:
# query = np.array(
# session_mysql.query(Equipment)
# .filter_by(device_type=1, isdeleted=0, disabled=1)
# .all()
# )
#
# for item in query:
# fixed_truck_list.append(item.id)
#
# if len(fixed_truck_list) < 1:
# raise Exception("无固定派车计划可用-固定派车矿卡集合读取异常")
# except Exception as es:
# logger.info("派车计划读取")
# logger.error(es)
# return set(fixed_truck_list)
#
#
# def update_autodisp_excavator():
# # 用于动态派车的挖机集合
# dynamic_excavator_list = []
# try:
# for item in (
# session_mysql.query(Dispatch).filter_by(isdeleted=0, isauto=1).all()
# ):
# dynamic_excavator_list.append(item.exactor_id)
# if len(dynamic_excavator_list) < 1:
# raise Exception("无动态派车计划可用-动态派车挖机/卸载设备集合读取异常")
# except Exception as es:
# logger.warning(es)
#
# return set(dynamic_excavator_list)
#
#
# def update_autodisp_dump():
# # 用于动态调度的卸载点集合
# dynamic_dump_list = []
# try:
# for item in (
# session_mysql.query(Dispatch).filter_by(isdeleted=0, isauto=1).all()
# ):
# dynamic_dump_list.append(item.dump_id)
# if len(dynamic_dump_list) < 1:
# raise Exception("无动态派车计划可用-动态派车挖机/卸载设备集合读取异常")
# except Exception as es:
# logger.warning(es)
#
# print("here1")
# print(set(dynamic_dump_list))
# return set(dynamic_dump_list)
#
#
# def update_load_area():
# load_area_list = []
# for walk_time in session_postgre.query(WalkTime).all():
# load_area_list.append(walk_time.load_area_id)
#
# return load_area_list
#
#
# def update_unload_area():
# unload_area_list = []
# for walk_time in session_postgre.query(WalkTime).all():
# unload_area_list.append(walk_time.unload_area_id)
# return unload_area_list
#
#
# def update_park_area():
# park_area_list = []
# for walk_time_park in session_postgre.query(WalkTimePark).all():
# park_area_list.append(walk_time_park.park_area_id)
# return park_area_list
......@@ -9,15 +9,16 @@
# 存储数据库表结构
from settings import *
from sqlalchemy import Column, create_engine
from sqlalchemy import VARCHAR, DateTime, Float, Integer, BOOLEAN
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base
from urllib.parse import quote
import json
import json, os
json_file = "config.json"
relative_path = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件夹的绝对路径
json_file = os.path.join(relative_path, "config.json")
# json_file = "config.json"
with open(json_file) as f:
mysql_config = json.load(f)["mysql"]
......@@ -58,7 +59,6 @@ with open(json_file) as f:
#
# session_postgre.expire_on_commit = False
# 创建对象的基类:
Base = declarative_base()
......@@ -68,8 +68,8 @@ sql_str = str("mysql+mysqlconnector://" + mysql_config["user"] + ":%s@" + mysql_
postgre_str = str("postgresql://" + postgre_config["user"] + ":%s@" + postgre_config["host"] + \
":" + postgre_config["port"] + "/" + postgre_config["database"])
try:
engine_mysql = create_engine(
# try:
engine_mysql = create_engine(
# "mysql+mysqlconnector://root:%s@192.168.28.111:3306/waytous"
# % quote("Huituo@123")
......@@ -77,9 +77,9 @@ try:
# "host"] + ":" + mysql_config["port"] + "/" + mysql_config["database"]
sql_str % quote(mysql_config["password"])
)
)
engine_postgre = create_engine(
engine_postgre = create_engine(
# "postgresql://postgres:%s@192.168.28.111:5432/shenbao_2021520"
# % quote("Huituo@123")
......@@ -87,29 +87,29 @@ try:
# "host"] + ":" + postgre_config["port"] + "/" + postgre_config["database"]
postgre_str % quote(postgre_config["password"])
)
)
# 创建DBsession_mysql类型:
DBsession_mysql = sessionmaker(bind=engine_mysql)
# 创建DBsession_mysql类型:
DBsession_mysql = sessionmaker(bind=engine_mysql)
DBsession_mysql = scoped_session(DBsession_mysql)
DBsession_mysql = scoped_session(DBsession_mysql)
DBsession_postgre = sessionmaker(bind=engine_postgre)
DBsession_postgre = sessionmaker(bind=engine_postgre)
DBsession_postgre = scoped_session(DBsession_postgre)
DBsession_postgre = scoped_session(DBsession_postgre)
# 创建session_mysql对象:
session_mysql = DBsession_mysql()
# 创建session_mysql对象:
session_mysql = DBsession_mysql()
session_mysql.expire_on_commit = False
session_mysql.expire_on_commit = False
session_postgre = DBsession_postgre()
session_postgre = DBsession_postgre()
session_postgre.expire_on_commit = False
except Exception as es:
# logger.error("数据库连接失败")
# logger.error(es)
pass
session_postgre.expire_on_commit = False
# except Exception as es:
# # logger.error("数据库连接失败")
# # logger.error(es)
# pass
# 定义对象:
......@@ -207,6 +207,7 @@ class WalkTime(Base):
# self.walktime_load = walktime_load
# self.walktime_unload = walktime_unload
# class Truck(Base):
# __tablename__ = 'truck_status'
#
......@@ -262,7 +263,8 @@ class EquipmentPair(Base):
isdeleted = Column(BOOLEAN)
createtime = Column(DateTime)
def __init__(self, id, truck_id, exactor_id, dump_id, load_area_id, unload_area_id, dispatch_id, isdeleted, createtime):
def __init__(self, id, truck_id, exactor_id, dump_id, load_area_id, unload_area_id, dispatch_id, isdeleted,
createtime):
self.id = id
self.truck_id = truck_id
self.exactor_id = exactor_id
......@@ -273,15 +275,6 @@ class EquipmentPair(Base):
self.isdeleted = isdeleted
self.createtime = createtime
# class Lane(Base):
# # 表的名字
# __tablename__ = 'Geo_Node'
# Id = Column(VARCHAR(36), primary_key=True)
# LaneIds = Column(VARCHAR(100))
#
# def __init__(self, Id, LaneIds):
# self.Id = Id
# self.LaneIds = LaneIds
class Lane(Base):
# 表的名字
......@@ -295,6 +288,7 @@ class Lane(Base):
self.Length = Length
self.MaxSpeed = MaxSpeed
class Dispatch(Base):
# 表的名字:
__tablename__ = 'sys_dispatch_setting'
......@@ -317,11 +311,12 @@ class Dispatch(Base):
deletor = Column(VARCHAR(36))
deletetime = Column(DateTime)
def __init__(self, id, load_area_id, exactor_id, unload_area_id, dump_id, isauto, truck_id, group_id, remark, proportion_id,
def __init__(self, id, load_area_id, exactor_id, unload_area_id, dump_id, isauto, truck_id, group_id, remark,
proportion_id,
isdeleted, creator, createtime, updator, updatetime, deletor, deletetime):
self.id = id
self.load_area_id = load_area_id
self.excavator_id = exactor_id
self.exactor_id = exactor_id
self.unload_area_id = unload_area_id
self.dump_id = dump_id
self.isauto = isauto
......@@ -337,6 +332,47 @@ class Dispatch(Base):
self.deletor = deletor
self.deletetime = deletetime
class DispatchSetting(Base):
__tablename__ = 'sys_dispatch_setting_v'
id = Column(VARCHAR(36), primary_key=True)
mode_name = Column(VARCHAR(36))
mode_code = Column(VARCHAR(36))
group_name = Column(VARCHAR(36))
group_id = Column(VARCHAR(36))
group_code = Column(VARCHAR(36))
group_type = Column(Integer)
load_area_id = Column(VARCHAR(36))
exactor_id = Column(VARCHAR(36))
unload_area_id = Column(VARCHAR(36))
dump_id = Column(VARCHAR(36))
isauto = Column(BOOLEAN)
truck_id = Column(VARCHAR(36))
team_id = Column(VARCHAR(36))
isdeleted = Column(BOOLEAN)
rate = Column(Integer)
proportion_id = Column(VARCHAR(36))
def __init__(self, id, mode_name, mode_code, group_name, group_id, group_code, group_type, load_area_id, exactor_id,
unload_area_id, dump_id, isauto, truck_id, remark, proportion_id, rate):
self.id = id
self.mode_name = mode_name
self.mode_code = mode_code
self.group_name = group_name
self.group_id = group_id
self.group_code = group_code
self.group_type = group_type
self.load_area_id = load_area_id
self.exactor_id = exactor_id
self.unload_area_id = unload_area_id
self.dump_id = dump_id
self.isauto = isauto
self.truck_id = truck_id
self.proportion_id = proportion_id
self.remark = remark
self.rate = rate
class WalkTimePark(Base):
__tablename__ = 'park_load_distance'
......@@ -355,6 +391,15 @@ class WalkTimePark(Base):
self.park_load_distance = park_load_distance
self.park_load_lanes = park_load_lanes
# class DispatchSetting(Base):
# __tablename__ = 'sys_dispatch_setting_v'
# id = Column(VARCHAR(36), primary_key=True)
#
# def __init__(self, id):
# self.id = id
class Equipment(Base):
__tablename__ = 'sys_equipment'
......@@ -384,6 +429,7 @@ class Equipment(Base):
self.only_allowed = only_allowed
self.priority = priority
class EquipmentSpec(Base):
__tablename__ = 'sys_equipment_spec'
......@@ -402,6 +448,7 @@ class EquipmentSpec(Base):
self.width = width
self.max_speed = max_speed
class LoadInfo(Base):
__tablename__ = 'sys_loadinfo'
......@@ -414,6 +461,7 @@ class LoadInfo(Base):
self.dump_id = dump_id
self.load_weght = load_weight
class JobRecord(Base):
__tablename__ = 'statistic_job_record'
......@@ -430,6 +478,7 @@ class JobRecord(Base):
self.end_time = end_time
self.work_type = work_type
class WorkRecord(Base):
__tablename__ = 'statistic_work_record'
......@@ -440,7 +489,8 @@ class WorkRecord(Base):
load_exit_time = Column(DateTime)
load_exit_count = Column(Integer)
def __init__(self, equipment_id, work_day, load_entrance_time, load_entrance_count, load_exit_time, load_exit_count):
def __init__(self, equipment_id, work_day, load_entrance_time, load_entrance_count, load_exit_time,
load_exit_count):
self.equipment_id = equipment_id
self.work_day = work_day
self.load_entrance_time = load_entrance_time
......@@ -456,16 +506,24 @@ class DumpArea(Base):
BindList = Column(VARCHAR(1000))
UnloadAbililty = Column(Float)
Disabled = Column(Integer)
Material = Column(VARCHAR(36))
Materials = Column(VARCHAR(36))
Priority = Column(Integer)
DumpEquipmentId = Column(VARCHAR(36))
EntranceNodeId = Column(VARCHAR(50))
ExitNodeId = Column(VARCHAR(50))
Name = Column(VARCHAR(36))
def __init__(self, Id, BindList, UnloadAbililty, Disabled, Material, Priority):
def __init__(self, Id, BindList, UnloadAbililty, Disabled, Materials, Priority, DumpEquipmentId, EntranceNodeId,ExitNodeId, Name):
self.Id = Id
self.BindList = BindList
self.UnloadAbililty = UnloadAbililty
self.Disabled = Disabled
self.Material = Material
self.Materials = Materials
self.Priority = Priority
self.DumpEquipmentId = DumpEquipmentId
self.EntranceNodeId = EntranceNodeId
self.ExitNodeId = ExitNodeId
self.Name = Name
class DiggingWorkArea(Base):
......@@ -473,10 +531,18 @@ class DiggingWorkArea(Base):
Id = Column(VARCHAR(50), primary_key=True)
Material = Column(VARCHAR(36))
ExactorId = Column(VARCHAR(36))
ExactorUuid = Column(VARCHAR(50))
EntranceNodeId = Column(VARCHAR(50))
ExitNodeId = Column(VARCHAR(50))
def __init__(self, Id, Material):
def __init__(self, Id, Material, ExactorId, ExactorUuid, EntranceNodeId, ExitNodeId):
self.Id = Id
self.Material = Material
self.ExactorId = ExactorId
self.ExactorUuid = ExactorUuid
self.EntranceNodeId = EntranceNodeId
self.ExitNodeId = ExitNodeId
class DispatchRule(Base):
......@@ -501,3 +567,76 @@ class Material(Base):
self.id = id
self.name = name
class DispatchMode(Base):
__tablename__ = 'sys_dispatch_mode'
id = Column(VARCHAR(36), primary_key=True)
mode_name = Column(VARCHAR(30))
mode_desc = Column(VARCHAR(50))
mode_code = Column(Integer)
def __init__(self, id, mode_name, mode_desc, mode_code):
self.id = id
self.mode_name = mode_name
self.mode_desc = mode_desc
self.mode_code = mode_code
class DispatchGroup(Base):
__tablename__ = 'sys_dispatch_group'
id = Column(VARCHAR(36), primary_key=True)
group_type = Column(Integer)
group_code = Column(VARCHAR(36))
mode_id = Column(VARCHAR(36))
mode_code = Column(Integer)
group_name = Column(VARCHAR(36))
def __init__(self, id, group_type, group_code, mode_id, mode_code, group_name):
self.id = id
self.group_type = group_type
self.group_code = group_code
self.mode_id = mode_id
self.mode_code = mode_code
self.group_name = group_name
class DispatchMatch(Base):
__tablename__ = 'sys_dispatch_match'
id = Column(VARCHAR(36), primary_key=True)
group_type = Column(Integer)
group_code = Column(VARCHAR(36))
match_code = Column(VARCHAR(36))
team_id = Column(VARCHAR(36))
load_area_id = Column(VARCHAR(36))
dump_id = Column(VARCHAR(36))
exactor_id = Column(VARCHAR(36))
unload_area_id = Column(VARCHAR(36))
def __init__(self, id, group_type, group_code, match_code, team_id, load_area_id, dump_id, exactor_id, unload_area_id):
self.id = id
self.group_type = group_type
self.group_code = group_code
self.match_code = match_code
self.team_id = team_id
self.load_area_id = load_area_id
self.dump_id = dump_id
self.exactor_id = exactor_id
self.unload_area_id = unload_area_id
class DispatchEquipment(Base):
__tablename__ = 'sys_dispatch_equipment'
id = Column(VARCHAR(36), primary_key=True)
group_type = Column(Integer)
group_code = Column(VARCHAR(36))
match_code = Column(VARCHAR(36))
isdeleted = Column(Integer)
equipment_id = Column(VARCHAR(36))
def __init__(self, id, group_type, group_code, match_code, isdeleted, equipment_id):
self.id = id
self.group_type = group_type
self.group_code = group_code
self.match_code = match_code
self.isdeleted = isdeleted
self.equipment_id = equipment_id
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