#ifndef __DISPATCH_COMMAND_HH__ #define __DISPATCH_COMMAND_HH__ #include "../tool/singleton.h" #include "../tool/thread_condition.h" #include "../error_code/error_code.h" #include "../dispatch/database_controller.h" #include "../message/message.pb.h" #include "../tool/common_data.h" #include #include #include //调度指令模块, 主要是与数据库的表 command_queue 同步, 然后按照一定的策略 class Dispatch_command { public: #define PARK_TIME_FLAG 101 //存车时间标记, 用于记录时差 #define PICK_TIME_FLAG 102 //取车时间标记, 用于记录时差120 #ifdef CHUTIAN_PROJECT_PROJECT #define SORT_LOSS_RATIO 1 //排序时, 排序编号间和楼层距离的比例, 默认1:1 #endif//CHUTIAN_PROJECT_PROJECT #ifdef SHANGGUJIE_PROJECT_PROJECT #define SORT_LOSS_RATIO 0//厦门车库暂时不允许插队, 按时间顺序 #endif//SHANGGUJIE_PROJECT_PROJECT //调度指令模块 的状态 enum Dispatch_command_status { E_DISPATCH_COMMAND_UNKNOW = 0, //未知 E_DISPATCH_COMMAND_READY = 1, //准备,待机 E_DISPATCH_COMMAND_BUSY = 2, //工作正忙 E_DISPATCH_COMMAND_DISCONNECT = 3, //断连 E_DISPATCH_COMMAND_FAULT = 100, //故障 }; //调度指令, 格式和数据库的 command_queue 保持一致 struct Dispatch_command_info { std::string m_car_number; //车牌号 std::string m_primary_key; //唯一码 int m_unit; //单元号, int m_terminal_id; //终端号, int m_queue_id; //排序的id, int m_type; //指令类型, 0无效, 1存车, 2取车, int m_statu; //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常 int m_import_id; //入口id, 1~6 int m_export_id; //出口id, 1~6 float m_height; //车高 std::string m_space_info_string; //车位信息的DebugString, 默认没有, 存车要根据感测信息的车高去申请车位, 取车根据车牌号找车位 parkspace_info m_space_info_msg; //车位信息的proto格式 std::string m_measure_info_string; //感测信息的DebugString, 里面自带车高, 小1.5 中1.7 大1.9, measure_info m_measure_info_msg; //感测信息的proto格式 std::string m_car_number_info_string; //车牌信息,包含图片 plate_number_info m_car_number_info_msg; //车牌信息,包含图片 int m_useless_distance; //空跑的路程, }; //调度车位信息, 格式和数据库的 space 保持一致 struct Dispatch_space_info { int m_id; //车位id int m_serial_id; //排序id int m_table_id; //标签id int m_unit; //单元号, int m_floor; //车位楼层 int m_room_id; //层内id float m_height; //车位高度, 小1.55 中1.75 大2.2, std::string m_primary_key; //key std::string m_car_number; //车牌号 int m_statu; //车位状态, 0可用, 1故障 std::string m_space_info_string; //车位信息的DebugString, 默认没有, 存车要根据感测信息的车高去申请车位, 取车根据车牌号找车位 parkspace_info m_space_info_msg; //车位信息的proto格式 std::string m_measure_info_string; //感测信息的DebugString, 里面自带车高, 小1.5 中1.7 大1.9, measure_info m_measure_info_msg; //感测信息的proto格式 }; //调度车辆信息, 格式和数据库的 vehicle 保持一致 struct Dispatch_vehicle_info { std::string m_car_number; //车牌号 std::string m_primary_key; //唯一码 std::string m_actually_measure_info; //感测信息的DebugString, 里面自带车高, 小1.5 中1.7 大1.9, measure_info m_actually_measure_info_msg; //感测信息的proto格式 }; public: Dispatch_command(); Dispatch_command(const Dispatch_command& other)= default; Dispatch_command& operator =(const Dispatch_command& other)= default; ~Dispatch_command(); public://API functions #ifdef SHANGGUJIE_PROJECT_PROJECT //存车指令入队, 检查节点直接通过rabbitmq发送给调度, 调度接受后数据库指令入队, Error_manager insert_park_command(park_table park_command); //存车指令入队, 检查节点直接通过rabbitmq发送给调度, 调度接受后数据库指令入队, Error_manager insert_park_command(park_table park_command, Dispatch_command::Dispatch_space_info dispatch_space_info); //取车指令入队, 检查节点直接通过rabbitmq发送给调度, 调度接受后数据库指令入队, Error_manager insert_pick_command(pick_table pick_command); //取车指令入队, 检查节点直接通过rabbitmq发送给调度, 调度接受后数据库指令入队, Error_manager insert_pick_command(pick_table pick_command, Dispatch_command::Dispatch_space_info dispatch_space_info); #endif//SHANGGUJIE_PROJECT_PROJECT //检查指令队列, 优先恢复未完成的指令,其次在执行新的指令 //调度开始前, 向数据库发送请求的相关操作, 输入 穿梭机所在的楼层, 调度id 0~2, 空闲出口id, 如果不是0,就表示有空闲的出口 Error_manager dispatch_request_to_sql(int plc_floor, int dispatch_id, int outlet_ready); //调度完成后, 向数据库发送答复的相关操作 Error_manager dispatch_response_to_sql(Error_manager error); //调度 , 向数据库 重新分配车位, Error_manager dispatch_reallocate_to_sql(Common_data::Car_type reallocate_car_type, int outlet_ready); //检查出口是否空闲, 检查指令队列的取车完成的出口id是否存在, 不存在就是空闲,返回成功 Error_manager check_export_id_is_ready(int export_id); //检查出口取车是否完成, 指定的出口有取车完成指令就返回成功, 否则报错. Error_manager check_pickup_is_finish(int unit_id, int export_id); //检查入口存车是否开始, 指定的入口有存车开始指令就返回成功, 否则报错. Error_manager check_park_is_start(int import_id); //获取指定入口的 存车流程的 唯一码, Error_manager get_primary_key_for_store(int import_id, std::string & primary_key ); //删除 指令队列, 根据出口编号 Error_manager delete_command_queue_for_export_id(int unit_id, int export_id); //添加plc数据储存 Error_manager insert_plc_data(std::string plc_data, float hearbeat); //查询 取车的车位 取车指令 根据车牌号 查询对应的车位 Error_manager query_dispatch_space_for_car_number(std::string car_number, parkspace_info & parkspace_info); //查询 取车的车位 取车指令 根据车牌号 查询对应的车位 Error_manager query_dispatch_space_for_primary_key(std::string primary_key, std::string &car_number, parkspace_info & parkspace_info, measure_info & measure_info); //查询 取车的车辆感测信息 取车指令 根据key 查询感测信息 Error_manager query_dispatch_vehicle_for_primary_key(std::string primary_key, measure_info & measure_info); public://get or set member variable protected://member functions public: //获取调度指令, 与数据库同步 command_queue, statu指令状态, 0:排队等待, 1正在运行, 2:已经完成 Error_manager query_all_dispatch_command(int statu); //对调度指令进行排序, 选出最优解, 比较存车和取车 Error_manager sort_dispatch_command_for_total(); //对调度指令进行排序, 选出最优解, 只比较存车 Error_manager sort_dispatch_command_for_park(); //获取 指定车高 指定单元 的车位信息,用于车位分配, 找不到就会报错, Error_manager query_specify_height_unit_parkspace_info(int unit, float height, float wheel_base, Dispatch_space_info & dispatch_space_info); //获取 指定车高 指定单元 的空闲车位数量, Error_manager query_specify_height_unit_parkspace_info(int unit, float height, float wheel_base, int & dispatch_space_count); //查询空闲车位最优解, 存车指令 根据调度指令最优解 获取 空闲车位最优解 Error_manager query_dispatch_space_optimal(int unit, float height, float wheel_base, Common_data::Car_type & car_type, Dispatch_space_info & dispatch_space_info); //查询空闲车位最优解, 存车指令 根据调度指令最优解 获取 空闲车位最优解 Error_manager query_dispatch_space_optimal_ex(Common_data::Car_type reallocate_car_type, Dispatch_space_info & dispatch_space_info); //查询 取车的车位 取车指令 根据车牌号 查询对应的车位 Error_manager query_dispatch_space_for_car_number(); //查询 取车的车辆感测信息 取车指令 根据key 查询感测信息 // Error_manager query_dispatch_vehicle_for_primary_key(); //更新 车位状态, 根据车位ID 修改车牌号即可, Error_manager update_parkspace_write_car_number(); //更新 车位状态, 存车排队预约车位 Error_manager update_parkspace_write_car_number(park_table park_command, Dispatch_command::Dispatch_space_info dispatch_space_info); //更新 车位状态, 找到车牌号, 写NULL Error_manager update_parkspace_clear_car_number(); //更新 车位状态, 找到车牌号, 写NULL by id Error_manager update_parkspace_clear_car_number_by_id(int space_id, int statu); //更新车牌图片信息, Error_manager update_parkspace_write_car_number_info(); //删除车牌图片信息, Error_manager update_parkspace_clear_car_number_info(); //更新 指令队列, 根据车牌号 修改状态即可, //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常 Error_manager update_command_queue_for_statu(int statu); //更新 指令队列, 根据车牌号 修改状态即可, //指令状态, 0排队中, 1正在工作, 2已完成, 3故障异常 // Error_manager update_command_queue_for_statu(int statu, std::string error_description); //把整个单元的排队指令改为故障 Error_manager update_command_queue_from_wait_to_fault_for_unit(int unit_id); //删除 指令队列, 根据车牌号 删除指令 Error_manager delete_command_queue_for_car_number(); //制作存车表单 Error_manager create_park_table(); //制作取车表单 Error_manager create_pick_table(int outlet_ready); //增加 车辆表, 存车指令 完成后添加车辆信息 Error_manager select_vehicle_for_car_number(); //增加 车辆表, 存车指令 完成后添加车辆信息 Error_manager insert_vehicle_for_car_number(); //增加 车辆表, 存车指令 完成后添加车辆信息, park_statu停车状态, 0:不存在, 1:存车中, 2:取车中, 3:在楼上存车 Error_manager updata_vehicle_for_car_number(int park_statu); //删除 车辆表, 取车指令 完成后删除车辆信息 Error_manager delete_vehicle_for_car_number(); //检查记录表是否提前创建。没有创建就返回成功 Error_manager check_record_for_no_primary_key(std::string primary_key); //增加 记录表, 存车指令 完成后添加存车记录 Error_manager insert_record_for_park_start(); //更新 记录表, 存车指令 完成后只更新存车开始时间 Error_manager updata_record_for_park_start(); //增加 记录表, 存车指令 完成后添加存车记录 Error_manager insert_record_for_park_start(park_table park_command, Dispatch_command::Dispatch_space_info dispatch_space_info); //增加 记录表, 存车指令 完成后添加存车记录 Error_manager updata_record_for_park_end(); //更新 记录表, 取车指令 完成后更新取车记录 Error_manager updata_record_for_pick_start(); //更新 记录表, 取车指令 完成后更新取车记录 Error_manager updata_record_for_pick_end(); //更新 记录表, 取车指令 完成后更新取车记录, 撤销指令, 没有取车时间差 Error_manager updata_record_for_pick_end_ex(); //计算汽车在车库的存车时间, 从存车开始到取车结束, 返回 parking_time, 单位秒. Error_manager get_parking_time(std::string primary_key, int & parking_time ); public: //获取出入口id 1~2为入口, 3~4为出口, //输入terminal_id 1~19, 输入 action_mode 1:存车, 2:取车 int get_passway_id(int terminal_id, int action_mode); protected://member variable public: Dispatch_command_status m_dispatch_command_status; //调度指令模块 的状态 std::mutex m_lock; // 锁. int m_dispatch_id; //调度id, 0-2 int m_unit; //单元号 int m_device_floor; //穿梭机所在的楼层, 存车完在对应的车位楼层, 取车完在1楼 int m_outlet_ready; //取车空闲出口id, 0表示没有出口, 1~6表示空闲出口 std::map m_dispatch_command_map; //调度指令map, 数据库的所有信息 std::string m_car_number_optimal; //调度指令最优解 Dispatch_space_info m_dispatch_space_info[100]; //调度车位最优解, 可以多次重新分配 int m_dispatch_space_info_count; //调度车位最优解, 如果重新分配,这个count就是最新使用的下标 // int m_wait_park_count = 0; //排队存车的数量 // int m_wait_pick_count = 0; //排队取车的数量 // Dispatch_vehicle_info m_dispatch_vehicle_info; //调度车位最优解 // Dispatch_space_info m_dispatch_space_info_reallocate[100]; //调度车位最优解, 重新分配的车位 Common_data::Dispatch_process_type m_dispatch_process_type ; //调度流程类型 park_table m_park_table_msg; //停车表单 pick_table m_pick_table_msg; //取车表单 Common_data::Car_type m_car_type; //车的大小 private: }; #endif // __DISPATCH_COMMAND_HH__