#include "module_traffic_light_manager.h" #include "db_api/CDBSingletonDefine.h" #include traffic_light_manager* traffic_light_manager::instance() { static traffic_light_manager tlm; return &tlm; } void traffic_light_manager::init_light_from_db(int lid) { std::string sql = "select light_id, lights_group_id, ip, x, y ,z, reader_id, state, port, physics_light_id, physics_light_direction, special_flag from dat_light"; if(0 == lid){ sql += ";"; }else{ sql += " where light_id = " + std::to_string(lid); sql += ";"; } std::string err = ""; YADB::CDBResultSet res; sDBConnPool.Query(sql.c_str(), res, err); int count = res.GetRecordCount(err); if(count < 1){ log_error("增加或修改失败,error:%s", sql.c_str()); return; } while(res.GetNextRecod(err)){ int light_id = 0; res.GetField("light_id", light_id, err); int group_id = 0; res.GetField("lights_group_id", group_id, err); std::string ip = ""; res.GetField("ip", ip, err); double x = 0.0, y = 0.0, z = 0.0; res.GetField("x", x, err); res.GetField("y", y, err); res.GetField("z", z, err); int site_id = 0, state = 0, port = 0, phy_light_id = 0, phy_direction = 0, special = 0; res.GetField("reader_id", site_id, err); res.GetField("state", state, err); res.GetField("port", port, err); res.GetField("physics_light_id", phy_light_id, err); res.GetField("physics_light_direction", phy_direction, err); res.GetField("special_flag", special, err); traffic_light_ptr pl = find_light(light_id); if(nullptr == pl){ pl = std::make_shared(x, y, z, light_id, group_id, ip, state, port, phy_light_id, phy_direction, special); m_unmap_lights.insert(std::make_pair(light_id, pl)); }else{ pl->update(x, y , z, light_id, group_id, ip, state, port, phy_light_id, phy_direction, special); } // 将红绿灯分配到对应组中 auto it_group = m_unmap_groups.find(pl->m_group_id); if(it_group != m_unmap_groups.end()) { it_group->second->m_vt_lights.push_back(pl); } } logn_info(2, "sql:%s",sql.c_str()); } void traffic_light_manager::init_light_group_from_db(int gid) { std::string sql = "select lights_group_id, x, y, z, scope, map_id, area_id, manual_control_time, light_auto_interval from dat_lights_group"; if(gid > 0){ sql += " where lights_group_id = " + std::to_string(gid); } sql += ";"; std::string err = ""; YADB::CDBResultSet res; sDBConnPool.Query(sql.c_str(), res, err); int count = res.GetRecordCount(err); if(count < 1){ log_error("增加或修改失败,数据库中找不到:sql=%s", sql.c_str()); return; } while(res.GetNextRecod(err)){ int group_id = 0; res.GetField("lights_group_id", group_id, err); double x = 0.0, y = 0.0, z = 0.0, scope = 0.0; res.GetField("x", x, err); res.GetField("y", y, err); res.GetField("z", z, err); res.GetField("scope", scope, err); int map_id = 0, area_id = 0; res.GetField("map_id", map_id, err); res.GetField("area_id", area_id, err); int ai = 0; res.GetField("light_auto_interval", ai, err); traffic_light_group_ptr pg = find_group(group_id); if(nullptr == pg){ pg = std::make_shared(x, y, z, group_id, scope, ai, map_id, area_id); m_unmap_groups.insert(std::make_pair(group_id, pg)); }else{ pg->update(x, y, z, group_id, scope, ai, map_id, area_id); } } logn_info(2, "sql:%s",sql.c_str()); } void traffic_light_manager::init(const traffic_send_callback& tcb) { // 1.先获得红绿灯组数据 init_light_group_from_db(); // 2.再获得红绿灯数据 init_light_from_db(); for(hashmap_light::iterator it_light = m_unmap_lights.begin(); it_light != m_unmap_lights.end(); ++it_light){ if(it_light->second->m_group_id >0){ hashmap_group::iterator it_group = m_unmap_groups.find(it_light->second->m_group_id); if(it_group != m_unmap_groups.end()){ it_group->second->insert(it_light->second); } } } set_send_callback(tcb); } void traffic_light_manager::start() { log_info("[traffic_light] start traffic light service, light_group's size=%d", m_unmap_groups.size()); m_stop = false; m_crossing_rule = std::unique_ptr(new crossing_rule); if(nullptr == m_crossing_rule){ log_info("[traffic_light] create crossing rule failed"); return; }else{ for(auto it = m_unmap_groups.begin(); it != m_unmap_groups.end(); ++it) { m_crossing_rule->put(it->second); } } m_avoidance_rule = std::unique_ptr(new avoidance_rule); if(nullptr == m_avoidance_rule){ log_info("[traffic_light] create avoidance rule failed"); return; }else{ for(auto it = m_unmap_groups.begin(); it != m_unmap_groups.end(); ++it) { log_info("[traffic_light] insert light group into area, area_id=%d", it->second->m_area_id); m_avoidance_rule->put(it->second); } } log_info("[traffic_light] rule's map size, crossing=%d, avoidance=%d", m_crossing_rule->size(), m_avoidance_rule->size()); m_thread_light.reset(new std::thread(std::bind(&traffic_light_manager::run, this))); } void traffic_light_manager::stop() { log_info("[traffic_light] stop traffic light service"); m_stop = true; m_thread_light->join(); } void traffic_light_manager::put(const light_message& msg) { std::unique_lock lock(m_mutex); m_list_data.push_back(msg); lock.unlock(); m_condition.notify_all(); } void traffic_light_manager::run() { while(!m_stop){ std::list tmp_data; tmp_data.clear(); //log_info("[traffic_light] working... m_stop=%d", m_stop); { std::unique_lock lock(m_mutex); while(m_list_data.empty()){ m_condition.wait(lock); } if(m_list_data.size() > 0){ m_list_data.swap(tmp_data); } lock.unlock(); } for(std::list::iterator it = tmp_data.begin(); it != tmp_data.end(); ++it){ switch(it->m_cmd){ case cmd_reload: log_info("[traffic_light] cmd=%d, gid=%d, lid=%d",it->m_cmd, it->m_group_id, it->m_light_id); handle_reload(it->m_group_id, it->m_light_id); break; case cmd_manual_ctrl: log_info("[traffic_light] cmd=%d, gid=%d, lid=%d, name=%s, lc=%d", it->m_cmd, it->m_group_id, it->m_light_id, it->m_ctrl_name.c_str(), it->m_light_status); handle_manual(it->m_group_id,it->m_light_id, it->m_ctrl_name, it->m_light_status); break; case cmd_card_data: log_info("[traffic_light] cmd=%d, cid=%d, ctype=%d, bigger=%d, aid=%d, speed=%.2f", it->m_cmd, it->m_pos.m_card_id, it->m_pos.m_type, it->m_pos.m_bigger, it->m_pos.m_area_id, it->m_pos.m_speed); handle_position(it->m_pos); break; default: log_warn("[traffic_light] message cmd error, cmd=%d", it->m_cmd); break; } } //log_info("[traffic_light] working thread one loop, m_stop=%d", m_stop); } log_info("[traffic_light] working thread is exit. m_stop=%d", m_stop); } void traffic_light_manager::handle_reload(const int& gid, const int& lid) { if(lid > 0){ init_light_from_db(lid); } if(gid > 0){ init_light_group_from_db(gid); } } int traffic_light_manager::reload_light(const int& lid) { init_light_from_db(lid); return 0; } int traffic_light_manager::reload_group(const int& gid) { init_light_group_from_db(gid); return 0; } void traffic_light_manager::handle_manual(const int& gid, const int& ld, const std::string& name, const int& lc) { traffic_light_group_ptr pg = find_group(gid); if(nullptr != pg){ pg->set_manual_ctrl(name, ld, lc); } } void traffic_light_manager::handle_position(pos_data& p) { if(p.m_type == 3 || p.m_type == 1){ std::map::iterator it = m_map_card.find(p.m_card_id); if(it != m_map_card.end()){ m_map_card.erase(it); } }else if(p.m_type == 2){ //log_info("[traffic_light] call handle rule"); update(p.x, p.y, p.m_card_id); m_map_card[p.m_card_id] = p; // 路口规则 if(nullptr != m_crossing_rule){ // maybe error //m_crossing_rule->handle_rule(p); } if(!p.m_bigger && nullptr != m_avoidance_rule){ m_avoidance_rule->handle_rule(p); } } }