#ifndef module_traffic_light_manager_h #define module_traffic_light_manager_h #include #include #include "module_traffic_light.h" #include "module_traffic_light_rule.h" #include "db_api/CDBCommon.h" #include "geo_hash.h" #include "log.h" #include "websocket/sio/sio_client.h" #include "common_tool.h" #include "crc.h" #include "protocol.h" #include "websocket/wsTimerThread.h" // 红绿灯管理 struct traffic_light_manager{ private: ~traffic_light_manager() { stop(); } public: static traffic_light_manager* instance(); // 从数据库加载数据 void init_light_from_db(int lid = 0); void init_light_group_from_db(int gid = 0); void init_light_group_path(); void init_map(int id = 0); // 初始化回调信息 void init(const int& lgc); // 开启 void start(); // 关闭 void stop(); // 运行 void run(); // 信息处理 void put(const light_message& msg); // 重新加载红绿灯信息 void handle_reload(const int& gid, const int& lid); int reload_light(const int& lid); int reload_group(const int& gid); // 手动控制红绿灯信息 void manual_ctrl(sio::message::ptr const& data); void set_manual(light_message& msg); void cancel_manual(light_message& msg); void handle_manual(const int& gid, const int& ld, const std::string& name, const int& lc); // 卡数据 void handle_position(pos_data& p); traffic_light_ptr get(const int& id) { return find_light(id); } //查找红绿灯 traffic_light_ptr find_light(const int k) { hashmap_light::iterator it = m_unmap_lights.find(k); if(it != m_unmap_lights.end()) { return it->second; } return nullptr; } // 查找红绿灯组 traffic_light_group_ptr find_group(const int k) { hashmap_group::iterator it = m_unmap_groups.find(k); if(it != m_unmap_groups.end()) { return it->second; } return nullptr; } std::vector find_stream_groups(traffic_light_group_ptr, const move_stream& stream); // 更新红绿灯数据 void update_light(const int& key, traffic_light_ptr ptl); // 更新红绿灯组数据 void update_group(const int& key, traffic_light_group_ptr ptlg); // 查找附近的车 std::vector find_nearby_vehicle(const point& p,const int& dist, const uint64_t& card_id) { return m_geo_list.find_near(p.x, p.y, dist, card_id); } pos_data* get_position(const uint64_t& cid) { std::map::iterator it = m_map_card.find(cid); if(it == m_map_card.end()) { log_error("[traffic_light] 找不到卡,card_id=%lld", cid); return nullptr; } return &(it->second); } void update(int x, int y, uint64_t cid) { m_geo_list.update(x, y, cid); } void vtlg_insert(const uint64_t& cid, traffic_light_group_ptr& group) { std::lock_guard lg(m_vtlg_mutex); auto it = m_vehicle_traffic_groups.find(cid); if(it == m_vehicle_traffic_groups.end()){ m_vehicle_traffic_groups.insert(std::make_pair(cid, std::list())); it = m_vehicle_traffic_groups.find(cid); } if(it->second.size() >= m_light_group_ctrl_num){ auto itg = it->second.front(); itg->reset(); it->second.pop_front(); } it->second.push_back(group); } void vtlg_erase(const uint64_t& cid, traffic_light_group_ptr& group) { std::lock_guard lg(m_vtlg_mutex); auto it = m_vehicle_traffic_groups.find(cid); if(it != m_vehicle_traffic_groups.end()){ for(auto it_g = it->second.begin(); it_g != it->second.end();++it_g){ if((*it_g)->m_group_id == group->m_group_id){ group->reset(); it->second.erase(it_g); break; } } } } bool vtlg_exist(const uint64_t& cid, const int& gid) { auto it = m_vehicle_traffic_groups.find(cid); if(it == m_vehicle_traffic_groups.end()){ return false; } for(auto it_g = it->second.begin(); it_g != it->second.end();++it_g){ if((*it_g)->m_group_id == gid){ return true; } } return false; } bool vtlg_exist(const int& gid) { bool ret = false; for(auto it : m_vehicle_traffic_groups) { if(vtlg_exist(it.first, gid)){ ret = true; break; } } return ret; } int vtlg_size(const uint64_t& cid) { auto it = m_vehicle_traffic_groups.find(cid); if(it == m_vehicle_traffic_groups.end()){ return 0; } return it->second.size(); } bool send_light_data(const int& light_id, const int& dev_type, const int& shape, const int cmd_type = 0){ std::vector msg; uint16_t cmd = THIRD_PARTY_CHAR_LIGHT_SETUP_STATE; if(1 == cmd_type){ cmd = THIRD_PARTY_CHAR_LIGHT_REQ_STATE; } tool_other::memcpy_int(msg, cmd); tool_other::memcpy_int(msg, light_id); // 设备类型 msg.push_back(dev_type); msg.push_back(static_cast(shape)); int16_t len = msg.size() + 2; int16_t crc = do_crc_1(msg, 0); auto it = msg.begin(); msg.insert(it, len&0xff); it = msg.begin(); msg.insert(it, (len>>8)&0xff); tool_other::memcpy_int(msg, crc); auto light_ptr = get(light_id); log_info("[light_info] ctrl light, light_id=%d, message's length=%d, light_ptr exist=%s", light_id, msg.size(), (light_ptr==nullptr)?"empty":"yes"); std::vector m = msg; output_message(std::move(m), light_id); if(light_ptr && light_ptr->m_clt){ light_ptr->m_clt->send(std::move(msg)); } return true; } /* * @brief 采集收到红绿灯心跳数据,将心跳数据发送给红绿灯设备 * * @param * const char* data 发送给红绿灯设备的心跳数据 * const int len 心跳数据长度 * const int light_id 红绿灯灯号 * * @return * false 发送失败 * true 发送成功 * @note * @warning * @bug * */ bool send_heart_data(const char* data, const int len, const int light_id) { auto light_ptr = get(light_id); if(light_ptr == nullptr){ log_error("[light_info] 未找到%d红绿灯", light_id); return false; } std::vector m; for(int i = 0;i < len; i++){ m.push_back(data[i]); } //m.insert(m.begin(), std::begin(data), std::end(data)); if(light_ptr->m_clt){ std::vector md = m; output_message(std::move(md), light_id); light_ptr->m_clt->send(std::move(m)); } return true; } /* * @brief * 输出红绿灯的16进制数据 * @param * std::vector&& msg 红绿灯数据 * int light_id 灯号 * @return * 无 * @note * @warning * @bug * */ void output_message(std::vector&& msg, int light_id) { std::string s("红绿灯控制的数据帧,灯号="); s.append(std::to_string(light_id)); s.append(":"); char a[4] = {0}; for(std::vector::size_type i = 0;i < msg.size(); ++i){ sprintf(a, "%02X ", static_cast(msg[i])); s.append(std::string(a)); } log_info("%s", s.c_str()); } void output_upstreamidx() { std::string msg = "红绿灯上行排序顺序(灯组id, 排序索引):"; for(auto it : m_map_groups){ char buf[20] = {0}; sprintf(buf, "(%d,%d)", it.second->m_group_id, it.first); msg.append(std::string(buf)); } log_info("%s", msg.c_str()); } int remove_light(const int& id); int remove_light_group(const int& id); void set_scale(const double& scale) { m_map_scale = scale; } double get_scale() { return m_map_scale; } std::string get_light_state(); bool on_path(const std::vector& vtp, const point& p); void visit_light_status(); private: bool m_stop; double m_map_scale = 0.0; unsigned int m_light_group_ctrl_num{0}; // 控制红绿灯组数 std::list m_list_data; std::mutex m_mutex; std::mutex m_vtlg_mutex; std::condition_variable m_condition; std::unique_ptr m_thread_light; std::unique_ptr m_crossing_rule; // 路口规则 std::unique_ptr m_avoidance_rule; // 避让规则 geo_list m_geo_list; hashmap_light m_unmap_lights; hashmap_group m_unmap_groups; map_group m_map_groups; std::map m_map_card; std::map> m_map_path; std::map> m_vehicle_traffic_groups; sys::jsonBuilder m_jsBuilder;//json构造器类 }; #endif