浏览代码

add traffic light module

zhuyf 4 年之前
父节点
当前提交
ca30419e0f

+ 3 - 1
card.cpp

@@ -20,7 +20,9 @@
 #include "ya_setting.h"
 
 extern config_file config;
-int three_rates_flag=0;
+int three_rates_flag    = 0;
+int traffic_light_flag  = 0;
+
 static void request(uint64_t id,uint32_t hash_id,uint16_t dis)
 {
      task * t  = task::alloc<message_change_card_display>();

+ 2 - 0
card.h

@@ -5,6 +5,8 @@
 #include "card_base.h"
 #include "write-copy.h"
 extern int three_rates_flag;
+extern int traffic_light_flag;
+
 struct card_list_visit:visitor<std::shared_ptr<card_location_base>>
 {
 	bool visit(std::shared_ptr<card_location_base> c);

+ 31 - 23
card_base.cpp

@@ -20,6 +20,8 @@
 #include "area.h"
 #include "loc_point.h"
 #include "loc_message.h"
+#include "module_service/module_traffic_light_manager.h"
+
 extern config_file config;
 card_location_base::card_location_base(const std::string&type,uint32_t id,uint16_t dis,int16_t t,int32_t deptid,int32_t level_id,uint32_t cid)
 	:card(id,dis,t,deptid,level_id,cid)
@@ -118,23 +120,7 @@ void card_location_base::on_location(const std::vector<point>&vp,const std::vect
     log_info("[business] card_location_base::on_location");
     loc_point pt = m_sel_tool->select_solution(vp, lm);
     pt.y = -pt.y;
-    /*if(it != lm.cend()){
-        switch((*it).m_loc_type){
-            case LDT_TOF:
-    	        pt = m_sel_tool->select_solution(vp,lm);
-	            pt.y = -pt.y;
-                break;
-            case LDT_TDOA:
-                break;
-            case LDT_PDOA:
-                pt.x = vp[0].x;
-                pt.y = vp[0].y;
-                pt.m_useless = true;
-                log_info("[pdoa] position's size = %d, x=%.2f, y=%.2f", vp.size(), pt.x, pt.y);
-                break;
-        }
-    }*/
-
+    
 	auto site_ptr = get_area_tool()->m_site;
 	int sid = 0;
 	if(site_ptr)
@@ -301,12 +287,19 @@ void  card_location_base::clear()
     //m_ct;				//ct
     m_time=0;			//时间戳
 }
+
 void card_location_base::put_three_rates(card_pos & cp)
 {
-    if(!three_rates_flag)return;
-	cp.rec_time=m_time;cp.type=m_type;cp.id=m_id;
-	cp.identifier_id=m_cid;cp.running_stat=m_stat;cp.final_v=m_speed;
-	cp.dpt_id = m_deptid;
+    if(!three_rates_flag)
+        return;
+	
+    cp.rec_time     = m_time;
+    cp.type         = m_type;
+    cp.id           = m_id;
+	cp.identifier_id= m_cid;
+    cp.running_stat = m_stat;
+    cp.final_v      = m_speed;
+	cp.dpt_id       = m_deptid;
 	std::shared_ptr<area_tool> _areatool = get_area_tool();
 	if(nullptr != _areatool && nullptr != _areatool->m_site)
 	{
@@ -319,6 +312,23 @@ void card_location_base::put_three_rates(card_pos & cp)
 	three_rates::get_instance()->put(cp);
 }
 
+void card_location_base::put_traffic_light(card_pos& cp)
+{
+    if(!traffic_light_flag){
+        return;
+    }
+    light_message lm;
+
+    lm.m_cmd = cmd_card_data;
+    lm.m_pos.x = cp.x;
+    lm.m_pos.y = cp.y;
+    lm.m_pos.z = cp.z;
+    lm.m_pos.m_card_id = m_id;
+    //lm.m_pos.m_bigger = 0;
+    lm.m_pos.m_speed = m_speed;
+    traffic_light_manager::instance()->put(lm);
+}
+
 bool card_location_base::is_person() const
 {
     return tool_other::is_person(m_type);
@@ -348,5 +358,3 @@ std::shared_ptr<card_location_base> card_location_base::make_car(const std::stri
 {
 	return std::make_shared<car>(type,cardid,needdisplay,t, deptid, categoryid, type_id,level_id,cid);
 }
-
-

+ 1 - 0
card_base.h

@@ -131,6 +131,7 @@ struct card_location_base:card,std::enable_shared_from_this<card_location_base>
 	void del_card_pos();
 	int	 get_stat();
 	void put_three_rates(card_pos &);
+    void put_traffic_light(card_pos& cp);
     void set_event_flag(EVENT_TYPE et,std::uint8_t f=1){m_event[et]=f;}
     bool get_event_flag(EVENT_TYPE et){return m_event[et];}
 

+ 16 - 3
card_car.cpp

@@ -52,17 +52,30 @@ int car::get_vehicle_type_id()
 void car::handle_three_rates(const point &pt)
 {
 	card_pos cp;
-	m_biz_stat=get_stat();
+	m_biz_stat = get_stat();
 	cp.biz_stat = m_biz_stat;
-	cp.x=pt.x;cp.y=pt.y;cp.z=pt.z;	
+	cp.x = pt.x;
+    cp.y = pt.y;
+    cp.z = pt.z;	
 	//const auto lm = m_area_tool->getLandmark();
 //	cp.enter_time = std::get<0>(lm)*1000;
 //	cp.area_id = std::get<3>(lm);
 	cp.map_id = m_area_tool->get_mapid();
-	cp.vibration=m_acc;
+	cp.vibration = m_acc;
 	put_three_rates(cp);
 }
 
+void car::handle_traffic_light(const point& p)
+{
+    card_pos cp;
+    cp.x = p.x;
+    cp.y = p.y;
+    cp.z = p.z;
+    cp.map_id = m_area_tool->get_mapid();
+    cp.vibration = m_acc;
+    put_traffic_light(cp);
+}
+
 void car::on_timer()
 {
     if(!empty())

+ 1 - 0
card_car.h

@@ -43,6 +43,7 @@ public:
 	virtual void get_card(bool);
 private:
 	void handle_three_rates(const point &pt);
+    void handle_traffic_light(const point& pt);
 	void on_timer();
 	void make_package();
 	loc_point getSmoothPoint();

+ 1 - 1
card_person.cpp

@@ -158,7 +158,7 @@ void person::on_timer()
 			m_upmine_flag=0;
 		}
         
-        log_info("[person] person is not attendance");
+        //log_info("[person] person is not attendance");
 		return;
 	}
 

+ 22 - 2
main.cpp

@@ -22,6 +22,7 @@
 #include "forbid_staff_down_mine.h"
 #include "bulletin_broad_show.h"
 #include "sync_time/sync_manager.h"
+#include "module_service/module_traffic_light_manager.h"
 
 config_file config;
 void handlereader(uint32_t readerid,bool duration,uint32_t t)
@@ -37,11 +38,17 @@ void Handle_ThreeRates_Event_Callback(const int evType, const int evId, uint64_t
     event_tool::instance()->handle_event((OBJECT_TYPE)evType,(EVENT_TYPE)evId,id,limitVal,curVal,bFalg);
 }
 
+void handle_traffic_light(int light_id, int type, int shape)
+{
+    // 查找信号灯socket,发送形状指令
+}
+
 struct Init_Setting
 {
     void init()
     {
-        three_rates_flag=config.get("service.three_rates_flag",0);
+        three_rates_flag=config.get("service.three_rates_flag", 0);
+        traffic_light_flag = config.get("service.traffic_light_flag", 0);
         YADB::_DB_POOL_SETTING_ DBSetting;
         DBSetting.Host = config.get("db.host","127.0.0.1");
         DBSetting.User = config.get("db.user","root");
@@ -65,7 +72,8 @@ struct Init_Setting
         std_info("json_interval:%d,[%s]",send_interval,url.c_str());
         std::vector<std::string> url_list;
         url_list.push_back(url);
-        if(!url_2.empty())url_list.push_back(url_2);
+        if(!url_2.empty())
+            url_list.push_back(url_2);
         if(!wsClientMgr_init(url_list, send_interval))
         {
             std_info("连接webServer[%s] 失败,采集服务器无法启动!",url.c_str());
@@ -104,6 +112,10 @@ struct Init_Setting
 		    init_three_rates(dp);
         }
 
+        if(traffic_light_flag){
+            init_traffic_light();
+        }
+
         init_ant_sync();
 
         log_info("Init_Setting::init  Success. \n" );
@@ -120,6 +132,14 @@ struct Init_Setting
         std_info("加载三率模块成功");
 	}
 
+    void init_traffic_light()
+    {
+        log_info("init traffic_light ...................");
+        traffic_light_manager::instance()->init(handle_traffic_light);
+        traffic_light_manager::instance()->start();
+        std_info("成功加载信号灯模块");
+    }
+
     bool _mysql_init(YADB::_DB_POOL_SETTING_ &dps)
     {
         std::string szError = "";

+ 11 - 0
message.h

@@ -166,6 +166,17 @@ struct message_pdoa_locinfo: public message_locinfo{
     void load(zistream& is);
 };
 
+struct message_light: task{
+    uint32_t m_light_id;
+    uint8_t  m_type;
+    uint16_t m_stamp;
+    uint8_t  m_status;
+
+    message_light(): m_light_id(0), m_type(0), m_stamp(0), m_status(0)
+    {}
+};
+
+
 #endif
 
 

+ 120 - 0
module_service/module_traffic_light.cpp

@@ -0,0 +1,120 @@
+#include <algorithm>
+#include "module_traffic_light.h"
+#include "module_traffic_light_manager.h"
+
+void traffic_light_group::reset()
+{
+    m_time_stamp = 0;
+    m_ctrl_name = "";
+    m_card_id = 0;
+    set_status(false);
+    set_priority(priority_init);
+
+    for(auto it = m_vt_lights.begin();it != m_vt_lights.end(); ++it){
+        auto tl = traffic_light_manager::instance()->find_light((*it)->m_phy_light_id);
+        if(tl != nullptr){
+            tl->set_state();
+        }
+    }
+}
+
+void traffic_light_group::insert(traffic_light_ptr ptl)
+{
+   ptl->m_direct_distance = this->dist_direct(*ptl);
+   line tmp(*this, *ptl);
+   ptl->m_line_group = tmp;
+   m_vt_lights.push_back(ptl);
+   if(1 == ptl->m_special){
+       m_special = 1;
+   }
+}
+
+void traffic_light_group::set_light(const int& ld, const int& lc, const int& lcr)
+{
+    for(auto it = m_vt_lights.begin(); it != m_vt_lights.end(); ++it){
+        auto ptl = traffic_light_manager::instance()->find_light((*it)->m_light_id);
+            if(ptl != nullptr){
+                if(ptl->m_light_id == ld){
+                    ptl->set_state(lc);
+                    send_cmd_light(ptl);
+                }else{
+                    ptl->set_state(lcr);
+                    send_cmd_light(ptl);
+                }
+                break;
+            }
+    }
+}
+
+bool traffic_light_group::is_different(const int& ld, const int& lc, const int& lcr)
+{
+    bool ret = false;
+
+    get_turn();
+    if(get_priority() <= priority_avoidance)
+    {
+        for(auto it = m_vt_lights.begin(); it != m_vt_lights.end(); ++it)
+        {
+            if((*it)->m_light_id == ld)
+            {
+                if((*it)->m_state != lc)
+                {
+                    ret = true;
+                    break;
+                }
+            }else{
+                if((*it)->m_state != lcr)
+                {
+                    ret = true;
+                    break;
+                }
+            }
+        }
+    }
+    if(ret){
+        set_avoidance(ld, lc, lcr);
+    }
+
+    release_turn();
+
+    return ret;
+}
+
+void traffic_light_group::send_cmd_light(traffic_light_ptr& ptl)
+{
+    if(nullptr != ptl){
+        // 控制码
+        int shape = 0;
+        if(red == ptl->m_state){
+            shape = red_circle_solid;
+        }else if(green == ptl->m_state){
+            shape = green_down;
+        }else{
+            shape = green_spark;
+        }
+
+        traffic_light_manager::instance()->send_light_ctrl(ptl->m_light_id, DT_LIGHT, shape);
+    }
+}
+
+void traffic_light_group::set_manual_ctrl(const std::string& name, const int& ld, const int& lc)
+{
+    get_turn();
+    m_ctrl_name = name;
+    m_time_stamp = time(NULL);
+    set_priority(priority_manual_ctrl);
+    m_card_id = 0;
+    auto ptl = std::find_if(m_vt_lights.begin(), m_vt_lights.end(),[=](traffic_light_ptr lp){
+            if(lp->m_light_id == ld)
+            {
+                return true;
+            }else{
+                return false;
+            }
+            });
+    if(ptl != m_vt_lights.end()){
+        (*ptl)->set_state(lc);
+    }
+
+    release_turn();
+}

+ 153 - 0
module_service/module_traffic_light.h

@@ -0,0 +1,153 @@
+#ifndef module_traffic_light_h
+#define module_traffic_light_h
+#include <memory>
+#include <ctime>
+#include <atomic>
+#include <vector>
+#include <list>
+#include "module_traffic_light_common.h"
+#include "line.h"
+
+// 红绿灯
+struct traffic_light: point{
+    int m_light_id;             // 红绿灯id
+    int m_group_id;             // 所属红绿灯组
+    std::string m_ip;           // 红绿灯IP
+    int m_site_id;              // 控制分站id
+    int m_state;                // 红绿灯状态,1-初始值,2-红灯,3-绿灯,4-闪烁
+    int m_port;                 // 分站控制红绿灯的路数
+    int m_phy_light_id;         // 物理灯号,红绿灯正反面共享此灯号
+    int m_phy_direction;        // 物理灯朝向,1-正面,0-反面
+    uint64_t m_rec_time;        // 红绿灯接收时间
+    int m_special;              // 检查非巷道区域,0-正常,1-特殊
+    double m_direct_distance;   // 红绿灯到灯组坐标的距离
+    line m_line_group;        // 红绿灯与灯组坐标的连线
+
+    traffic_light(): m_light_id(0), m_group_id(0), m_ip(""), m_state(0), m_port(0), m_phy_light_id(0), m_phy_direction(0), m_rec_time(0), m_special(0), m_direct_distance(0.0)
+    {}
+
+    void set_state(int value = green)
+    {
+        m_state = value;
+    }
+};
+
+using traffic_light_ptr = std::shared_ptr<traffic_light>;
+class traffic_light_group;
+using traffic_light_group_ptr = std::shared_ptr<traffic_light_group>;
+
+//红绿灯组
+struct traffic_light_group: point{
+    int m_group_id;                 // 所属红绿灯组ID
+    double m_scope;                 // 控制半径
+    uint16_t m_manual_time;         // 人工控制默认时间
+    uint16_t m_auto_interval;       // 断网情况下,自动控制间隔
+    uint64_t m_card_id;             // 如果优先级是1,表示小车id;优先级是2,表示打车id
+    int m_map_id;                   // 地图ID
+    int m_area_id;                  // 区域ID
+    time_t m_time_stamp;            // 控制时长,单位秒
+    time_t m_ctrl_time;             // 控制时间
+    bool m_special;                 // 是否含有特殊红绿灯组
+    int m_green_light_id;           // 灯组被控制后变绿灯的灯ID
+    std::string m_ctrl_name;        // 控制用户
+    std::atomic<int> m_priority;    // 优先级,0-初始值,1-路口控制,2-避让控制;3-手动控制
+    std::atomic<bool> m_used;       // 是否使用
+    std::atomic_flag m_owner_flag;  // 控制权
+    std::vector<traffic_light_ptr> m_vt_lights;   // 组下红绿灯
+
+    traffic_light_group(): point(0,0), m_group_id(0), m_scope(0.0), m_manual_time(0), m_auto_interval(0), m_card_id(0), m_map_id(0), m_area_id(0), m_time_stamp(0), m_ctrl_time(0),m_special(false), m_green_light_id(0), m_ctrl_name(""), m_priority(priority_init), m_used(false)
+    {
+        m_vt_lights.clear();   
+    }
+
+    // 给红绿灯下发指令设置其颜色
+    void send_cmd_light(traffic_light_ptr& ptl);
+
+    void set_crossing(const uint64_t& cid, const int& p)
+    {
+        m_card_id = cid;
+        set_priority(p);
+    }
+
+    // 设置避让
+    void set_avoidance(const int& ld, const int& lc, const int& lcr)
+    {
+        m_card_id = 0;
+        m_time_stamp = 0;
+        set_priority(priority_avoidance);
+        set_light(ld, lc, lcr);
+    }
+
+    // 设置优先权
+    void set_priority(const int& p)
+    {
+        m_priority.store(p);   
+    }
+
+    // 获取优先权
+    int get_priority()
+    {
+        return m_priority.load();
+    }
+
+    // 设置状态
+    void set_status(bool s)
+    {
+        m_used.store(s);
+    }
+
+    // 得到状态
+    bool get_status()
+    {
+        return m_used.load();
+    }
+
+    // 控制超时检查
+    bool is_time_out()
+    {
+        if(m_time_stamp >= m_ctrl_time){
+            return true;
+        }
+
+        return false;
+    }
+
+    void get_turn()
+    {
+        while(m_owner_flag.test_and_set(std::memory_order_acquire))
+        {}
+    }
+
+    void release_turn()
+    {
+        m_owner_flag.clear(std::memory_order_release);
+    }
+
+    // 重置
+    void reset();
+
+    //设置灯组内红绿灯颜色,满足条件的设置为指定灯形状,不满足条件3个面的设为其他相同的灯形状
+    void set_light(const int& lid, const int& lc, const int& lcr);
+    
+    // 增加红绿灯到灯组
+    void insert(traffic_light_ptr ptl);
+
+    //获取两个灯之间的距离
+    bool is_different(const int& ld, const int& lc, const int& lcr);
+
+    // 手动控制
+    void set_manual_ctrl(const std::string& name, const int& ld, const int& lc);
+
+    uint64_t get_green_light_id();
+};
+
+struct traffic_light_data{
+    bool m_bigger_flag; //大车标识
+    std::list<traffic_light_ptr> m_traffic_group;
+
+    traffic_light_data(): m_bigger_flag(false){
+        m_traffic_group.clear();
+    }
+};
+
+#endif

+ 90 - 0
module_service/module_traffic_light_common.h

@@ -0,0 +1,90 @@
+#ifndef module_traffic_light_common_h
+#define module_traffic_light_common_h
+#include <string>
+#include <list>
+#include "point.h"
+
+enum device_type{
+    DT_BIG_READER = 1,      // 大分站
+    DT_SMALL_READER = 2,    // 小分站
+    DT_CARD_READER = 3,     // 读卡分站
+    DT_CTRL_READER = 4,     // 通信分站
+    DT_LIGHT = 5,           // 红绿灯
+    DT_SPEAKER = 6,         // 告警器
+    DT_TURNOUT = 7,         // 道岔
+    DT_LED = 8,             // 显示屏
+};
+
+// 灯的颜色和形状表
+enum light_shape{
+    init_shape          = 0,
+    red_circle_solid    = 1,    // 红色实心圆
+    red_circle          = 2,    // 红色空心圆
+    red_cross           = 3,    // 红色叉型
+    green_up            = 4,    // 绿色上箭头
+    green_down          = 5,    // 绿色下箭头
+    green_left          = 6,    // 绿色左箭头
+    green_right         = 7,    // 绿色右箭头
+    red_spark           = 8,    // 红色闪烁
+    green_spark         = 9,    // 绿色闪烁
+    green_all_on        = 10,   // 绿色全亮
+    green_all_off       = 11,   // 绿色全灭
+    red_all_on          = 12,   // 红色全亮
+    red_all_off         = 13    // 红色全灭
+};
+
+//优先级
+enum priority{
+    priority_init = 0,      // 初始值
+    priority_crossing,      // 路口控制
+    priority_avoidance,     // 避让控制
+    priority_manual_ctrl,   // 手动控制
+};
+
+//web对应的
+enum light_color{
+    init = 1,   // 初始值
+    red,        // 红灯
+    green,      // 绿灯
+    spark       // 闪烁
+};
+
+enum light_cmd{
+    cmd_reload      = 0,    // 重新加载红绿灯信息
+    cmd_manual_ctrl,     // 手动控制红绿灯信息
+    cmd_card_data,          // 卡数据
+};
+
+struct pos_data: point{
+    uint64_t m_card_id;     // 卡id
+    uint8_t  m_type;        // 1-add,2-del,3-update
+    bool m_bigger;          // 大小车标记
+    int32_t m_area_id;      // 区域id
+    double m_speed;         // 速度
+    std::list<int> m_light_group;   // 红绿灯id
+
+    pos_data(): m_card_id(0), m_type(0), m_bigger(false), m_area_id(0), m_speed(0.0)
+    {
+        m_light_group.clear();
+    }
+};
+
+struct light_message{
+    uint16_t m_cmd;             // 命令
+    int m_group_id;             // 信号灯组id
+    int m_light_id;             // 信号灯id
+    int m_light_status;         // 信号灯形状
+    std::string m_ctrl_name;    // 控制用户
+    pos_data m_pos;             // 卡数据
+
+    light_message(): m_cmd(0), m_group_id(0), m_light_id(0), m_light_status(0), m_ctrl_name("")
+    {}
+
+    light_message(const uint16_t cmd, const int gid, const int lid, const int ls, const std::string name, const pos_data& p): m_cmd(cmd), m_group_id(gid), m_light_id(lid), m_light_status(ls), m_ctrl_name(name), m_pos(p)
+    {}
+};
+
+const double g_max_scope = 100.0;
+const double g_mid_vehicle_length_group = 30.0;
+
+#endif

+ 234 - 0
module_service/module_traffic_light_manager.cpp

@@ -0,0 +1,234 @@
+#include "module_traffic_light_manager.h"
+#include "db_api/CDBSingletonDefine.h"
+#include <db_api/CDBResultSet.h>
+
+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)){
+        traffic_light_ptr pl = std::make_shared<traffic_light>();
+        if(nullptr == pl){
+            return;
+        }
+
+        res.GetField("light_id", pl->m_light_id, err);
+        res.GetField("lights_group_id", pl->m_group_id, err);
+        res.GetField("ip", pl->m_ip, err);
+        res.GetField("x", pl->x, err);
+        res.GetField("y", pl->y, err);
+        res.GetField("z", pl->z, err);
+        res.GetField("reader_id", pl->m_site_id, err);
+        res.GetField("state", pl->m_state, err);
+        res.GetField("port", pl->m_port, err);
+        res.GetField("physics_light_id", pl->m_phy_light_id, err);
+        res.GetField("physics_light_direction", pl->m_phy_direction, err);
+        res.GetField("special_flag", pl->m_special, err);
+        m_unmap_lights[pl->m_light_id] = 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)){
+        traffic_light_group_ptr pg = std::make_shared<traffic_light_group>();
+        if(nullptr == pg){
+            return;
+        }
+
+        res.GetField("lights_group_id", pg->m_group_id, err);
+        res.GetField("x", pg->x, err);
+        res.GetField("y", pg->y, err);
+        res.GetField("z", pg->z, err);
+        res.GetField("scope", pg->m_scope, err);
+        res.GetField("map_id", pg->m_map_id, err);
+        res.GetField("area_id", pg->m_area_id, err);
+        int ai = 0;
+        res.GetField("light_auto_interval", ai, err);
+        pg->m_auto_interval = ai;
+        m_unmap_groups[pg->m_group_id] = pg;
+    }
+    
+    logn_info(2, "sql:%s",sql.c_str());
+}
+
+void traffic_light_manager::init(const traffic_send_callback& tcb)
+{
+    init_light_from_db();
+    init_light_group_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");
+    m_stop = false;
+    m_crossing_rule = std::unique_ptr<crossing_rule>(new crossing_rule);
+    if(nullptr == m_crossing_rule){
+        log_info("[traffic_light] create crossing rule failed");
+        return;
+    }
+
+    m_avoidance_rule = std::unique_ptr<avoidance_rule>(new avoidance_rule);
+    if(nullptr == m_avoidance_rule){
+        log_info("[traffic_light] create avoidance rule failed");
+        return;
+    }
+
+    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<std::mutex> lock(m_mutex);
+    m_list_data.push_back(msg);
+    m_condition.notify_one();
+}
+
+void traffic_light_manager::run()
+{
+    while(!m_stop){
+        std::list<light_message> tmp_data;
+        tmp_data.clear();
+
+        {
+            std::unique_lock<std::mutex> lock(m_mutex);
+            while(m_list_data.empty()){
+                m_condition.wait(lock);
+            }
+
+            if(m_list_data.size() > 0){
+                m_list_data.swap(tmp_data);
+            }
+        }
+
+        for(std::list<light_message>::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, bigger=%d, aid=%d, speed=%.2f", it->m_cmd, it->m_pos.m_card_id, 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;
+            }
+        
+        }
+    }
+}
+
+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 == 2){
+        std::map<uint64_t, pos_data>::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 == 3 || p.m_type == 1){
+        m_geo_list.update(p.x, p.y, p.m_card_id);
+        m_map_card[p.m_card_id] = p;
+        // 路口规则
+        if(nullptr != m_crossing_rule){
+            m_crossing_rule->handle_rule(p);
+        }
+
+        if(!p.m_bigger && nullptr != m_avoidance_rule){
+            m_avoidance_rule->handle_rule(p);
+        }
+    }
+}

+ 136 - 0
module_service/module_traffic_light_manager.h

@@ -0,0 +1,136 @@
+#ifndef module_traffic_light_manager_h
+#define module_traffic_light_manager_h
+#include <thread>
+#include <functional>
+#include "module_traffic_light.h"
+#include "module_traffic_light_rule.h"
+#include "db_api/CDBCommon.h"
+#include "geo_hash.h"
+#include "log.h"
+
+using traffic_send_callback = std::function<void(int, int, int)>;
+
+struct traffic_light_callback{
+    traffic_send_callback m_traffic_send;
+
+    traffic_light_callback()
+    {
+        m_traffic_send = nullptr;
+    }
+
+    void set_callback(const traffic_send_callback& cb)
+    {
+        m_traffic_send = std::move(cb);
+    }
+};
+
+// 红绿灯管理
+struct traffic_light_manager{
+    static traffic_light_manager* instance();
+
+    // 从数据库加载数据
+    void init_light_from_db(int lid = 0);
+    void init_light_group_from_db(int gid = 0);
+
+    // 初始化回调信息
+    void init(const traffic_send_callback& cb);
+
+    // 开启
+    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 handle_manual(const int& gid, const int& ld, const std::string& name, const int& lc);
+
+    // 卡数据
+    void handle_position(pos_data& p);
+
+    //查找红绿灯
+    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;
+    }
+
+    // 更新红绿灯数据
+    void update_light(const int& key, traffic_light_ptr ptl);
+
+    // 更新红绿灯组数据
+    void update_group(const int& key, traffic_light_group_ptr ptlg);
+
+    // 查找附近的车
+    std::vector<uint64_t> 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<uint64_t, pos_data>::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);
+    }
+
+    bool send_light_ctrl(const int& light_id, const int& type, const int& shape){
+        if(light_id > 0 && m_send_callback){
+            m_send_callback(light_id, type, shape);
+        }
+
+        return true;
+    }
+
+    void set_send_callback(const traffic_send_callback& cb)
+    {
+        m_send_callback = std::move(cb);   
+    }
+
+    private:
+    bool m_stop;
+    std::list<light_message> m_list_data;
+    std::mutex m_mutex;
+    std::condition_variable m_condition;
+    std::unique_ptr<std::thread> m_thread_light;
+
+    std::unique_ptr<crossing_rule> m_crossing_rule; // 路口规则
+    std::unique_ptr<avoidance_rule> m_avoidance_rule;   // 避让规则
+
+    traffic_send_callback m_send_callback;
+    geo_list m_geo_list;
+    hashmap_light m_unmap_lights;
+    hashmap_group m_unmap_groups;
+    std::map<uint64_t, pos_data> m_map_card;
+};
+
+#endif

+ 659 - 0
module_service/module_traffic_light_rule.cpp

@@ -0,0 +1,659 @@
+#include <cfloat>
+#include "module_traffic_light_rule.h"
+#include "module_traffic_light_manager.h"
+
+bool rule::sort_vehicle(const uint64_t lhs, const uint64_t rhs, const traffic_light_group_ptr& g)
+{
+    pos_data* v1 = traffic_light_manager::instance()->get_position(lhs);
+    pos_data* v2 = traffic_light_manager::instance()->get_position(rhs);
+    double d1 = DBL_MAX, d2 = DBL_MAX;
+    if(nullptr != v2){
+        d2 = g->dist(v2->x, v2->y);
+    }
+    if(nullptr != v1){
+        d1 = g->dist(v1->x, v1->y);
+    }
+
+    return d1 < d2;
+}
+
+traffic_light_ptr rule::find_nearby_light(const point& p, traffic_light_group_ptr g)
+{
+    traffic_light_ptr pl = nullptr;
+    double max = DBL_MAX;
+    //查找最近的红绿灯
+    for(auto it = g->m_vt_lights.begin(); it != g->m_vt_lights.end(); ++it)
+    {
+        traffic_light_ptr tmp = traffic_light_manager::instance()->find_light((*it)->m_light_id);
+        double dt = tmp->dist(p.x, p.y);
+        if(dt < max){
+            max = dt;
+            pl = tmp;
+        }
+    }
+
+    return pl;
+}
+
+void crossing_rule::change_state(const uint64_t vid, traffic_light_group_ptr g)
+{
+    pos_data* cp = traffic_light_manager::instance()->get_position(vid);
+    if(nullptr != cp){
+        // 查找离车辆最近的红绿灯
+        traffic_light_ptr pl = find_nearby_light(point(cp->x, cp->y), g);
+        // 设置来车方向为绿灯,其他方向为红灯
+        if(nullptr != pl){
+            log_info("[traffic_light] card_id=%lld, light_id=%d", vid, pl->m_light_id);
+            g->set_light(pl->m_light_id, green, red);
+        }
+    }
+}
+
+// 获得车辆是否大车的标记
+bool crossing_rule::get_vehicle_state(const uint64_t& vid)
+{
+    bool s = false;
+
+    pos_data* v = traffic_light_manager::instance()->get_position(vid);
+    if(nullptr != v){
+        s = v->m_bigger;
+    }
+
+    return s;
+}
+
+bool crossing_rule::find_light(const uint64_t& vid, traffic_light_group_ptr g, bool a)
+{
+    pos_data* cp = traffic_light_manager::instance()->get_position(vid);
+    if(nullptr != cp){
+        line l;
+        traffic_light_ptr pl = find_nearby_light(point(cp->x, cp->y), g);
+        if(nullptr == pl){
+            return false;
+        }
+
+        if(!a){
+            if(1 == pl->m_special){
+                // 判断是否在线上
+                if(pl->m_line_group.contain(cp->x, cp->y, 0.5)){
+                    // 判断行车方向
+                    double d = cp->m_speed * pl->m_direct_distance;
+                    if(d < 0){
+                        return true;
+                    }
+                }
+            }
+        }else{
+            // 判断是否在线上
+            if(pl->m_line_group.contain(cp->x, cp->y, 1.0)){
+                double d = cp->m_speed * pl->m_direct_distance;
+                if(d < 0){
+                    return true;
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+bool crossing_rule::handle_manual_ctrl(traffic_light_group_ptr g)
+{
+    if(g->is_time_out()){
+        g->reset();
+        return true;
+    }
+
+    return false;
+}
+
+bool crossing_rule::handle_crossing(traffic_light_group_ptr g)
+{
+    // 查找一定范围的车辆
+    std::vector<uint64_t> vtl = traffic_light_manager::instance()->find_nearby_vehicle(point(static_cast<int>(g->x), static_cast<int>(g->y)), g->m_scope, 0);
+    if(vtl.empty()){
+        if(g->m_card_id > 0 && g->m_priority == priority_crossing)
+        {
+            // 释放红绿灯组
+            g->reset();
+            return true;
+        }
+
+        return false;
+    }
+
+    // 是否已经有车记录
+    if(g->m_card_id > 0)
+    {
+        auto it = std::find(vtl.begin(), vtl.end(), g->m_card_id);
+        if(it != vtl.end()){
+            return false;
+        }
+    }
+
+    std::sort(vtl.begin(), vtl.end(), [&](const uint64_t& lhs, const uint64_t& rhs){
+            return sort_vehicle(lhs, rhs, g);
+            });
+
+    // 设置优先级以及卡id
+    g->set_crossing(vtl[0], priority_crossing);
+    // 修改红绿灯组状态
+    change_state(vtl[0], g);
+
+    return true;
+}
+
+bool crossing_rule::handle_avoidance(traffic_light_group_ptr g)
+{
+    // 查看是否是大车,true表示特殊红绿灯,需要检测大车避让规则
+    bool flag = false;
+
+    do{
+        auto vt = traffic_light_manager::instance()->find_nearby_vehicle(point(static_cast<int>(g->x), static_cast<int>(g->y)), g->m_scope, 0);
+
+        // 筛选大车
+        if(vt.empty()){
+            flag = true;
+            break;
+        }
+        vt.erase(std::remove_if(vt.begin(), vt.end(), [&](const uint64_t& vid){
+            return get_vehicle_state(vid);
+                    }),
+                vt.end());
+
+        if(vt.empty()){
+            flag = true;
+            break;
+        }
+
+        // 查看离最近的点是否为特殊点,判断位置是否在直线上,判断方向
+        vt.erase(std::remove_if(vt.begin(), vt.end(), [&](const uint64_t& vid){
+            return find_light(vid, g);
+                    }),
+                vt.end());
+        if(vt.empty()){
+            flag = true;
+            break;
+        }
+
+        // 特殊规则保留id且优先级2,避让规则置空id,优先级2
+        if(priority_avoidance == g->get_priority()){
+            if(0 == g->m_card_id){
+                break;
+            }else{
+                auto it = std::find(vt.begin(), vt.end(), g->m_card_id);
+                if(it != vt.end()){
+                    break;
+                }
+            }
+        }
+
+        // 排序,找到离之最近的大车
+        std::sort(vt.begin(), vt.end(), [&](const uint64_t& vid, const uint64_t& cid){
+                return sort_vehicle(vid, cid, g);
+                });
+
+        change_state(vt[0], g);
+        g->set_crossing(vt[0], priority_avoidance);
+
+        return true;
+    }while(false);
+
+    if(flag){
+        // 找不到之前的车辆,则初始化
+        if(priority_avoidance == g->get_priority() && g->m_card_id > 0){
+            g->reset();
+        }else{
+            flag = false;
+        }
+    }
+
+    return flag;
+}
+
+vt_traffic_group crossing_rule::handle_rule(pos_data& p)
+{
+    vt_traffic_group llist;
+    for(auto it = m_vt_group.begin(); it != m_vt_group.end(); ++it){
+        // 获取控制权
+        (*it)->get_turn();
+        int priority = (*it)->get_priority();
+        bool flag = false;
+        do{
+            if(priority_manual_ctrl == priority){
+                 flag = handle_manual_ctrl(*it);
+                 if(flag){
+                    break;
+                 }
+            }
+
+            if(priority <= priority_avoidance && (*it)->m_special){
+                flag = handle_avoidance(*it);
+                if(flag){
+                    break;
+                }
+            }
+
+            if(priority <= priority_crossing){
+                flag = handle_crossing(*it);
+                if(flag){
+                    break;
+                }
+            }
+        }while(false);
+ 
+        (*it)->release_turn();
+        if(flag){
+            llist.push_back(*it);
+        }
+    }
+
+    return std::move(llist);
+}
+
+vt_traffic_group avoidance_rule::find_group(const pos_data& p)
+{
+    return find_group(point(p.x, p.y), p.m_area_id, p.m_speed, p);
+}
+
+vt_traffic_group avoidance_rule::find_group(const point& po , int area_id, double  speed, const pos_data& pd)
+{
+    vt_traffic_group llist;
+
+    if(0 == pd.m_card_id || 0 == pd.m_type){
+        std::move(llist);
+    }
+
+    // 获取车辆所在地图区域内的所有红绿灯组
+    vt_traffic_group vg = m_map_area_group[area_id];
+
+    double dist = 0.0;
+    for(std::size_t i = 0; i < vg.size(); ++i){
+        traffic_light_group_ptr pg = vg[i];
+        if(nullptr == pg){
+            continue;
+        }
+
+        // 如果此灯组被控制了,则不允许使用
+        if(vg[i]->get_status() && vg[i]->m_card_id != pd.m_card_id){
+            log_info("[traffic_light] card_id=%lld was control light group, gid=%d", pd.m_card_id, vg[i]->m_group_id);
+            continue;
+        }
+
+        // 求灯组到车辆的距离(车辆在灯组的左下方,则距离值取反)
+        dist = vg[i]->dist_direct(po.x, po.y);
+        // 车辆在灯组左边或下边
+        if(dist <= 0){
+            // 速度方向与前进方向一致
+            if(speed > 0){
+                // 车辆到灯组的距离小于指定距离
+                if(vg[i]->dist(po.x, po.y) <= g_max_scope){
+                    llist.push_back(vg[i]);
+                }
+
+                // 紧挨着的一个灯组到车距离小于指定阈值
+                if(i + 1 < vg.size()){
+                    if(vg[i+1]->dist(po.x, po.y) <= g_max_scope){
+                        llist.push_back(vg[i+1]);
+                    }
+                }
+            }else if(speed < 0){
+                // 速度方向与前进方向不一致,判断运动方向的灯组是否在可控范围
+                if(i >= 1 && vg[i - 1]->dist(po.x, po.y) <= g_max_scope){
+                    llist.push_back(vg[i-1]);
+                }
+                if(i >= 2 && vg[i-2]->dist(po.x, po.y) <= g_max_scope){
+                    llist.push_back(vg[i-2]);
+                }
+            }
+
+            break;
+        }
+    }
+
+    // 车辆在灯组右边或上边
+    if(dist > 0 && speed < 0){
+        std::size_t i = vg.size();
+        if(i >= 1 && vg[i-1]->dist(po.x, po.y) <= g_max_scope){
+            llist.push_back(vg[i-1]);
+        }
+        if(i >= 2 && vg[i-2]->dist(po.x, po.y) <= g_max_scope){
+            llist.push_back(vg[i-2]);
+        }
+    }
+
+    return std::move(llist);
+}
+
+bool avoidance_rule::find_vehicle_in_group(vt_traffic_group& vg, std::vector<pos_data>& vv)
+{
+    if(vv.size() < 2){
+        log_error("[traffic_light] vv's size less than 2");
+        return false;
+    }
+    bool flag = true;
+    double d = vg[0]->dist(vv[1].x, vv[1].y);
+    line tl(*vg[0], *vg[1]);
+    if(tl.contain(vv[1].x, vv[1].y, 1))
+    {
+        if(vv[1].m_speed * vv[0].m_speed < 0 && d > g_mid_vehicle_length_group){
+            flag = false;
+        }
+    }
+
+    return flag;
+}
+
+bool avoidance_rule::get_vehicle(const pos_data& p, vt_traffic_group& vg)
+{
+    double d = vg[0]->dist(*vg[1]);
+
+    std::vector<uint64_t> vt1 = traffic_light_manager::instance()->find_nearby_vehicle(point(static_cast<int>(vg[0]->x), static_cast<int>(vg[0]->y)), static_cast<int>(d), vg[0]->m_card_id);
+    std::vector<uint64_t> vt2 = traffic_light_manager::instance()->find_nearby_vehicle(point(static_cast<int>(vg[1]->x), static_cast<int>(vg[1]->y)), static_cast<int>(d), vg[1]->m_card_id);
+
+    std::sort(vt1.begin(), vt1.end());
+    std::sort(vt2.begin(), vt2.end());
+
+    std::vector<uint64_t> vti;
+
+    std::set_intersection(vt1.begin(), vt1.end(), vt2.begin(), vt2.end(), std::back_inserter(vti));
+
+    if(vti.empty()){
+        return false;
+    }
+
+    // 筛选出符合条件的车辆,离第一个红绿灯距离进行排序
+    vti.erase(std::remove_if(vti.begin(), vti.end(), [&](const uint64_t& vid) -> bool {
+                pos_data* tp = traffic_light_manager::instance()->get_position(vid);
+                if(tp == nullptr){
+                    return true;
+                }
+
+                std::vector<pos_data> vv;
+                vv.push_back(p);
+                vv.push_back(*tp);
+                return find_vehicle_in_group(vg, vv);
+                }));
+
+    return vti.empty()?false:true;
+}
+
+void avoidance_rule::insert(traffic_light_group_ptr g, pos_data& p, vt_traffic_group& vg, const int lc, const int lcr)
+{
+    p.m_light_group.push_back(g->m_group_id);
+    if(g->get_priority() < priority_avoidance){
+        // 红绿灯组优先级取初始值0或路口控制1
+        change_group(g, point(p.x, p.y), lc, lcr);
+        vg.push_back(g);
+    }
+
+    traffic_light_ptr pl = find_nearby_light(point(p.x, p.y), g);
+    g->m_green_light_id = pl->m_light_id;
+    // 灯组绑定车辆的卡号
+    g->m_card_id = p.m_card_id;
+    g->set_status(true);
+}
+
+void avoidance_rule::erase(bool a, pos_data& p, vt_traffic_group& vg)
+{
+    if(p.m_light_group.size() <= 0){
+        return;
+    }
+
+    traffic_light_group_ptr pg = nullptr;
+
+    bool flag = false;
+    if(a){
+        pg = traffic_light_manager::instance()->find_group(p.m_light_group.front());
+        p.m_light_group.pop_front();
+    }else{
+        pg = traffic_light_manager::instance()->find_group(p.m_light_group.back());
+        p.m_light_group.pop_back();
+    }
+
+    if(nullptr == pg){
+        return;
+    }
+
+    pg->get_turn();
+    if(pg->get_priority() <= priority_avoidance){
+        // 重置灯组
+        pg->reset();
+        flag = true;
+    }
+
+    pg->release_turn();
+    pg->set_status(false);
+
+    if(flag){
+        vg.push_back(pg);
+    }
+}
+
+void avoidance_rule::change_group(const traffic_light_group_ptr& g, const point& p, const int& lc, const int& lcr)
+{
+    // 1.取离p最近的灯组信息
+    traffic_light_ptr pl = find_nearby_light(point(p.x, p.y), g);
+    if(nullptr == pl){
+        return;
+    }
+
+    // 2.获取灯组中临近车辆的灯id
+    g->m_green_light_id = pl->m_light_id;
+    g->get_turn();
+
+    // 3.设置灯组中灯号为ld的灯颜色为lc,其余灯颜色为lcr
+    g->set_avoidance(pl->m_light_id, lc, lcr);
+    g->release_turn();
+}
+
+bool avoidance_rule::is_different(traffic_light_group_ptr g, const point& p, const int& lc, const int& lcr)
+{
+    bool b = false;
+
+    traffic_light_ptr pl = find_nearby_light(p, g);
+    if(g->is_different(pl->m_light_id, lc, lcr)){
+        b = true;
+    }
+
+    return b;
+}
+
+vt_traffic_group avoidance_rule::handle_rule(pos_data& p)
+{
+    vt_traffic_group llist;
+
+    if(p.m_card_id == 0|| p.m_type == 0){
+        return std::move(llist);
+    }
+
+    auto it = m_map_area_group.find(p.m_area_id);
+    if(it != m_map_area_group.end()){
+        // 根据车卡的定位坐标以及定位区域信息获取红绿灯组
+        vt_traffic_group vtg = find_group(p);
+        if(vtg.size() == 0){
+            // 所在区域没有可以控制的红绿灯组
+            switch(p.m_light_group.size())
+            {
+                case 1:
+                    // 当前车辆控制的路口为1个,释放该炉口控制
+                    erase(true, p, llist);
+                    break;
+                case 2:
+                    // 当前车辆控制的路口为两个,释放这两个路口的控制
+                    erase(true, p, llist);
+                    erase(false, p, llist);
+                    break;
+            }
+        }else if(1 == vtg.size()){
+            // 所在区域存在1个红绿灯组
+            switch(p.m_light_group.size())
+            {
+                case 0:
+                    // 当前卡没有绑定红绿灯组,绑定此灯组,并设置灯组颜色为绿色
+                    insert(vtg[0], p, llist, green, red);
+                    break;
+                case 1:
+                    //当前卡绑定了1个红绿灯组
+                    if(p.m_light_group.front() != vtg[0]->m_group_id){
+                        // 检查当前卡绑定的红绿灯组与区域找到的是不是同一个
+                        // 不是,释放之前的绑定,再绑定新灯组
+                        erase(true, p, llist);
+                        insert(vtg[0], p, llist, green, red);
+                    }else{
+                        // 当前卡绑定的红绿灯组与区域找到的是同一个
+                        traffic_light_ptr pl = find_nearby_light(point(p.x, p.y), vtg[0]);
+                        if(nullptr != pl && pl->m_light_id != vtg[0]->m_green_light_id){
+                            erase(true, p, llist);
+                        }
+                    }
+                    break;
+            }
+        }else if(2 == p.m_light_group.size()){
+            // 当前卡绑定了2个红绿灯组
+            traffic_light_group_ptr g = vtg[0];
+            if(p.m_light_group.front() == g->m_group_id){
+                // 第一个绑定的红绿灯组与区域找到的是同一个,删除第二个
+                erase(false, p, llist);
+                if(g->get_priority() <= priority_avoidance){
+                    change_group(g, point(p.x, p.y), green, red);
+                    llist.push_back(g);
+                }
+            }else if(p.m_light_group.back() == g->m_group_id){
+                // 第二个绑定的红绿灯组与区域找到的是同一个,删除第一个
+                erase(true, p, llist);
+                if(g->get_priority() <= priority_avoidance){
+                    change_group(g, point(p.x, p.y), green, red);
+                    llist.push_back(g);
+                }
+            }else{
+                // 两个都不是,全部删除
+                erase(true, p, llist);
+                erase(false, p, llist);
+                insert(g, p, llist, green, red);
+            }
+        }else if(2 == vtg.size()){
+            // 所在区域存在两个红绿灯组,巷道相遇逻辑
+            // 判断两个灯组中是否有车
+            bool b = get_vehicle(p, vtg);
+            light_color la, lb;
+            if(b){
+                la = red;
+                lb = spark;
+            }else{
+                la = green;
+                lb = red;
+            }
+
+            switch(p.m_light_group.size()){
+                case 0:
+                    // 当前卡没有绑定红绿灯组,绑定2个灯组
+                    insert(vtg[0], p, llist, la, lb);
+                    insert(vtg[1], p, llist, green, spark);
+                    break;
+                case 1:
+                    // 当前卡有绑定1个红绿灯组,更新
+                    if(p.m_light_group.front() == vtg[0]->m_group_id){
+                        if(vtg[0]->get_priority() <= priority_avoidance){
+                            change_group(vtg[0], point(p.x, p.y), la, lb);
+                            llist.push_back(vtg[0]);
+                        }
+                        insert(vtg[1], p, llist, green, spark);
+                    }else if(p.m_light_group.front() == vtg[1]->m_group_id){
+                        if(vtg[1]->get_priority() <= priority_avoidance)
+                        {
+                            change_group(vtg[1], point(p.x, p.y), green, spark);
+                            llist.push_back(vtg[1]);
+                        }
+                        p.m_light_group.push_front(vtg[0]->m_group_id);
+                        if(vtg[0]->get_priority() < priority_avoidance)
+                        {
+                            change_group(vtg[0], point(p.x, p.y), la, lb);
+                            llist.push_back(vtg[0]);
+                        }
+                    }else{
+                        // 两个都不相等
+                        erase(false, p, llist);
+                        insert(vtg[0], p, llist, la, lb);
+                        insert(vtg[1], p, llist, green, spark);
+                    }
+                    break;
+                case 2:
+                    // 当前卡有绑定2个红绿灯组,更新
+                    {
+                        std::list<int>::iterator ito = std::find(p.m_light_group.begin(), p.m_light_group.end(), vtg[0]->m_group_id);
+                        std::list<int>::iterator itt = std::find(p.m_light_group.begin(), p.m_light_group.end(), vtg[1]->m_group_id);
+
+                        if(ito != p.m_light_group.end())
+                        {
+                            if(itt != p.m_light_group.end())
+                            {
+                                if(p.m_light_group.front() == vtg[0]->m_group_id){
+                                    if(is_different(vtg[0], point(p.x, p.y), la, lb)){
+                                        llist.push_back(vtg[0]);
+                                    }
+                                    if(is_different(vtg[1], point(p.x, p.y), green, spark)){
+                                        llist.push_back(vtg[1]);
+                                    }
+                                }else{
+                                    p.m_light_group.clear();
+                                    if(vtg[0]->get_priority() <= priority_avoidance){
+                                        change_group(vtg[0], point(p.x, p.y), la, lb);
+                                        llist.push_back(vtg[0]);
+                                    }
+                                    if(vtg[1]->get_priority() <= priority_avoidance){
+                                        change_group(vtg[1], point(p.x, p.y), green, spark);
+                                        llist.push_back(vtg[1]);
+                                    }
+                                    p.m_light_group.push_back(vtg[0]->m_group_id);
+                                    p.m_light_group.push_back(vtg[1]->m_group_id);
+                                }
+                            }
+                            else
+                            {
+                                if(p.m_light_group.front() == vtg[0]->m_group_id){
+                                    erase(false, p, llist);
+                                    insert(vtg[1], p, llist, green, spark);
+                                }else{
+                                    erase(true, p, llist);
+                                    if(vtg[0]->get_priority() <= priority_avoidance){
+                                        change_group(vtg[0], point(p.x, p.y), la, lb);
+                                        llist.push_back(vtg[0]);
+                                    }
+                                    insert(vtg[1], p, llist, green, spark);
+                                }
+                            }
+                        }
+                        else
+                        {
+                            if(itt != p.m_light_group.end()){
+                                if(p.m_light_group.front() == vtg[1]->m_group_id){
+                                    erase(false, p, llist);
+                                }else{
+                                    erase(true, p, llist);
+                                }
+
+                                if(vtg[1]->get_priority() <= priority_avoidance){
+                                    change_group(vtg[1], point(p.x, p.y), green, spark);
+                                    llist.push_back(vtg[1]);
+                                }
+                                p.m_light_group.push_front(vtg[1]->m_group_id);
+                                if(vtg[0]->get_priority() < priority_avoidance){
+                                    change_group(vtg[0], point(p.x, p.y), la, lb);
+                                    llist.push_back(vtg[0]);
+                                }
+                            }else{
+                                erase(true, p, llist);
+                                erase(true, p, llist);
+                                insert(vtg[0], p, llist, la, lb);
+                                insert(vtg[1], p, llist, green, spark);
+                            }
+                        }
+                    }
+                    break;     
+            }
+        }
+    }
+
+    return std::move(llist);
+}

+ 111 - 0
module_service/module_traffic_light_rule.h

@@ -0,0 +1,111 @@
+#ifndef module_traffic_light_rule_h
+#define module_traffic_light_rule_h
+
+#include <vector>
+#include <list>
+#include <map>
+#include <unordered_map>
+#include <thread>
+#include <condition_variable>
+#include "module_traffic_light_common.h"
+#include "module_traffic_light.h"
+
+using vt_traffic_group = std::vector<traffic_light_group_ptr>;
+using mp_traffic_group = std::map<int, vt_traffic_group>;
+
+struct rule{
+    rule(){}
+    virtual ~rule(){}
+
+    virtual vt_traffic_group handle_rule(pos_data& p) = 0;
+    virtual void put(traffic_light_group_ptr tlp) = 0;
+    virtual void put(vt_traffic_group&& vc) = 0;
+
+    // 车子按距离红绿灯组坐标点排序
+    bool sort_vehicle(const uint64_t lhs, const uint64_t rhs, const traffic_light_group_ptr& g);
+
+    // 在红绿灯组数组中找离位置点(x,y)最近的灯组信息
+    traffic_light_ptr find_nearby_light(const point& p, traffic_light_group_ptr g);
+};
+
+// 路口规则
+struct crossing_rule: rule{
+    crossing_rule(){}
+    ~crossing_rule(){}
+
+    vt_traffic_group handle_rule(pos_data& p);
+    // 谁先到达炉口红绿灯指定的距离,变绿灯,其他变红灯
+    bool get_vehicle_state(const uint64_t& card_id);
+    // 自动控制
+    bool handle_manual_ctrl(traffic_light_group_ptr g);
+    // 查找附近的红绿灯
+    bool find_light(const uint64_t& cid, traffic_light_group_ptr g, bool a = false);
+    // 避让处理
+    bool handle_avoidance(traffic_light_group_ptr g);
+    // 路口处理
+    bool handle_crossing(traffic_light_group_ptr g);
+    // 修改红绿灯组状态
+    void change_state(const uint64_t cid, traffic_light_group_ptr g);
+
+    void put(traffic_light_group_ptr g)
+    {
+        m_vt_group.push_back(g);
+    }
+
+    void put(vt_traffic_group&& vc)
+    {
+        m_vt_group = vc;
+    }
+
+    private:
+    vt_traffic_group m_vt_group;
+};
+
+// 避让规则
+struct avoidance_rule: rule{
+    public:
+        avoidance_rule(){}
+        ~avoidance_rule(){}
+
+        vt_traffic_group handle_rule(pos_data& p);
+        // 给车卡绑定路口灯组控制,并更改灯组中灯的颜色状态
+        void insert(traffic_light_group_ptr g, pos_data& p, vt_traffic_group& vg, const int lc, const int lcr);
+        // 改变点p定位附近灯组的状态,满足条件的灯状态改为lc,否改为lcr
+        void change_group(const traffic_light_group_ptr& g, const point& p, const int& lc, const int& lcr);
+        // 把车卡从路口灯组控制中解绑
+        void erase(bool a, pos_data& p, vt_traffic_group& vg);
+        // 根据车辆与灯组的位置关系,查找灯组
+        vt_traffic_group find_group(const pos_data& p);
+        vt_traffic_group find_group(const point& po, int aid, double v, const pos_data& p);
+        // 两个红绿灯组中间是否有车
+        bool get_vehicle(const pos_data& p, vt_traffic_group& vg);
+        // 求坐标点与红绿灯组的距离
+        bool is_different(traffic_light_group_ptr g, const point& p, const int& lc, const int& lcr);
+        // 后续小车避让大车规则,只需要找到前方的两个红绿灯,找到两个对比一下之前的记录,如果灯组改变了,则修改,如果没变,则判断是否有小车,进行改变
+        // 如果只找到一个红绿灯,查看是否含有记录,如果有,则不做任何处理
+        bool find_vehicle_in_group(vt_traffic_group& vg, std::vector<pos_data>& vv);
+
+        void put(traffic_light_group_ptr ptlg)
+        {
+            m_map_area_group[ptlg->m_area_id].push_back(ptlg);
+        }
+
+        void put(vt_traffic_group&& lhs)
+        {
+            for(const auto x : lhs){
+                m_map_area_group[x->m_area_id].push_back(x);
+            }
+        }
+        
+    private:
+        mp_traffic_group m_map_area_group;
+};
+
+struct up_down_rule: rule{
+    
+};
+
+using hashmap_light = std::unordered_map<int, traffic_light_ptr>;
+using hashmap_group = std::unordered_map<int, traffic_light_group_ptr>;
+
+#endif

+ 58 - 3
net-service.cpp

@@ -203,9 +203,13 @@ void net_service::on_message(const std::shared_ptr<client> &clt,const char*data,
                 {
                     int32_t site_id = parse_data_anchor_opt(clt, is);
                     if(site_id < 0){
-                        return;
+                        break;
                     }
                     const auto& site_ptr = sit_list::instance()->get(static_cast<int32_t>(site_id));
+                    if(!site_ptr){
+                        logn_error(1,"在全局分站列表中找不到分站:%d", site_id);
+                        break;
+                    }
                     site_ptr->set_algo(LDT_PDOA);
                     struct timeval tv;
                     gettimeofday(&tv, NULL);
@@ -268,9 +272,13 @@ void net_service::on_message(const std::shared_ptr<client> &clt,const char*data,
 				{
                     int32_t site_id = parse_data_anchor(clt, is);
 					if(site_id < 0){
-                        return;
+                        break;
                     }
                     const auto& site_ptr = sit_list::instance()->get(static_cast<int32_t>(site_id));
+                    if(!site_ptr){
+                        logn_error(1,"在全局分站列表中找不到分站:%d", site_id);
+                        break;
+                    }
                     site_ptr->set_algo(LDT_TDOA);
 
 					while(!is.eof())
@@ -305,6 +313,53 @@ void net_service::on_message(const std::shared_ptr<client> &clt,const char*data,
 			case CHAR_LOCATEDATAHIS_TOF_EXTEND://tof his
 			case CHAR_LOCATEDATAHIS_TDOA_EXTEND://tdoa his
 			case CHAR_CTRL_READER_CMD://ctrl site message
+                break;
+            case CHAR_LIGHT_TCP_STATUS:
+                {
+                    // 请求红绿灯状态
+                    uint32_t id = 0;
+                    uint8_t type = 0;
+                    is>>id>>type;
+                    //logn_info(1, "light info: light_id=%d, type=%d", id, type);
+                    /*auto light_ptr = light_list::instance()->get(id);
+                    if(!light_ptr){
+                        logn_error(1,"在全局信号灯列表中找不到信号灯:%d", id);
+                        break;
+                    }*/
+
+                    task* t = task::alloc<message_light>();
+                    message_light& m = t->body<message_light>();
+                    t->m_cmd_code = cmd;
+                    m.m_light_id = id;
+                    m.m_type = type;
+                    m_loc_worker->request(t);
+                }
+                break;
+            case CHAR_LIGHT_TCP_HEART:
+                {
+                    // 红绿灯心跳
+                    uint32_t id = 0;
+                    uint16_t stamp = 0;
+                    uint8_t status = 0;
+                    is>>id>>stamp>>status;
+                    //logn_info(1, "light info: light_id=%d, stamp=%d, status=%d", id, stamp, status);
+                    /*auto light_ptr = light_list::instance()->get(id);
+                    if(!light_ptr)
+                    {
+                        logn_error(1,"在全局信号灯列表中找不到信号灯:%d", id);
+                        break;
+                    }*/
+
+                    task* t = task::alloc<message_light>();
+                    message_light& m = t->body<message_light>();
+                    t->m_cmd_code = cmd;
+                    m.m_light_id = id;
+                    m.m_stamp = stamp;
+                    m.m_status = status;
+
+                    m_loc_worker->request(t);
+                }
+                break;
 			default:
 				message_handled=false;
 		}
@@ -430,7 +485,7 @@ float net_service::get_pdoa(float poa[], const double& offset)
 
     float poa1 = poa[0];
     float poa2 = poa[1];
-    float poa3 = poa[2];
+    //float poa3 = poa[2];
 
     float pdoa = poa2 - poa1 - offset;
     while(pdoa >= TPI){

+ 0 - 1
net-service.h

@@ -24,7 +24,6 @@ struct net_service:service_callback
     int32_t parse_data_anchor_opt(const std::shared_ptr<client>& clt, zistream& s);
     void parse_data_card();
     float get_pdoa(float poa[], const double& offset);
-
 };
 
 #endif

+ 10 - 2
protocol.h

@@ -22,10 +22,18 @@
 #define CHAR_LOCATEDATA_TDOA                0x813b  // TDOA实时定位数据
 #define CHAR_LOCATEDATA_TDOA_EXTEND_INS     0x901b  // 扩展TDOA实时定位数据,带惯导数据
 
-//3.pdoa
+// 3.pdoa
 #define CHAR_LOCATEDATA_PDOA                0xa03b  // PDOA实时定位数据
 
-// 4.other
+// 4.light
+#define CHAR_LIGHT_STATUS                   0x6a7c  // 红绿灯请求状态指令
+#define CHAR_LIGHT_HEART                    0x5a1a  // 红绿灯心跳指令
+#define CHAR_LIGHT_SETUP                    0x77a4  // 设置红绿灯参数信息
+#define CHAR_LIGHT_TCP_STATUS               0x95a0  // TCP红绿灯请求状态指令
+#define CHAR_LIGHT_TCP_HEART                0x95a1  // TCP红绿灯心跳指令
+#define CHAR_LIGHT_TCP_SETUP                0x95a2  // TCP红绿灯设置参数信息
+
+// 5.other
 #define CHAR_CTRL_READER_CMD                0x804c	// 向分站发送控制指令,控制分站向上位机发送数据
 #define CHAR_VIRTUAL_DATA_PUSH_CMD          0x699a	// 虚拟数据推送
 #define CHAR_SYNC_TIME                      0x783a  // 分站校时

+ 55 - 0
websocket/jsonBuilder.cpp

@@ -566,6 +566,61 @@ namespace YA
         return sb.GetString();
     }
 
+    std::string jsonBuilder::build_tmp_card_pos(const std::map<uint64_t,_CARD_POS_>& cards)
+    {
+        rapidjson::StringBuffer sb;
+        rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
+        rapidjson::Document doc;
+        rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
+
+        rapidjson::Value root(rapidjson::kObjectType);
+
+        // "cmd":
+	    __SetCmd( JSON_CMD_VALUE_POS_MAP, root, allocator );
+        
+        // "data"
+        rapidjson::Value item(rapidjson::kArrayType);
+
+        for(auto it = cards.begin(); it != cards.end(); ++it)
+        {
+            rapidjson::Value elem(rapidjson::kArrayType);
+            rapidjson::Value tmp_obj(rapidjson::kObjectType);
+            
+            // 卡号
+            tmp_obj.SetString(__FmtCardID(it->second).c_str(), allocator);
+            elem.PushBack(tmp_obj, allocator);
+            // x坐标
+            tmp_obj.SetDouble(it->second.x);
+            elem.PushBack(tmp_obj, allocator);
+            // y坐标
+            tmp_obj.SetDouble(it->second.y);
+            elem.PushBack(tmp_obj, allocator);
+            // z坐标
+            tmp_obj.SetDouble(it->second.z);
+            elem.PushBack(tmp_obj, allocator);
+            // 时间戳
+            tmp_obj.SetDouble(it->second.rec_time);
+            elem.PushBack(tmp_obj, allocator);
+            // 加速度
+            tmp_obj.SetDouble(it->second.m_acc);
+            elem.PushBack(tmp_obj, allocator);
+            // 速度
+            tmp_obj.SetDouble(it->second.speed);
+            elem.PushBack(tmp_obj, allocator);
+
+            item.PushBack(elem, allocator);
+        }
+
+        root.AddMember("data", item, allocator);
+
+ 	    // "version"
+        __AddVersion(root, allocator);
+
+        root.Accept(writer);
+
+        return sb.GetString();
+    }
+
 	std::string jsonBuilder::BuildSpecialAreaProcess( const _BASE_CARD_ & stCard )
 	{
 		rapidjson::StringBuffer sb;

+ 1 - 1
websocket/jsonBuilder.h

@@ -6,7 +6,6 @@ json构造器类
   V 1.0.0
 
 * @author
-  王益俊
 
 * @date
   创建时间:  2018-08-17\n
@@ -246,6 +245,7 @@ namespace YA
 		*/
 		std::string BuildCardPos( const std::map<uint64_t, _CARD_POS_>& CardPosList );
         std::string build_ios_card_pos(const _CARD_POS_& card);
+        std::string build_tmp_card_pos(const std::map<uint64_t, _CARD_POS_>& cards);
 		/**
 		* @brief
 		生成车辆进入特殊区域jason函数。

+ 14 - 2
websocket/wsTimerThread.cpp

@@ -91,6 +91,17 @@ namespace YA
         }
     }
 
+    void wsTimerThread::temp_send_card_pos()
+    {
+        if(__CardPosList.empty()){
+            return;
+        }
+        std::map<uint64_t, _CARD_POS_> cards;
+        __CardPosList.copy(cards);
+        std::string json_pos = __jsBuilder.build_tmp_card_pos(cards);
+        swsClientMgr.send(JSON_CMD_VALUE_PUSH, json_pos);
+    }
+
     /*
      * 定时器线程发送定位数据
      *
@@ -105,9 +116,10 @@ namespace YA
 
 			if ( seconds >= pOwner->__Config.SendInterval )
 			{
-				pOwner->__SendCardPos();
+				//pOwner->__SendCardPos();
                 //service_position send
-                pOwner->send_card_pos();
+                //pOwner->send_card_pos();
+                pOwner->temp_send_card_pos();
 				__LastSendTime = t;
 			}
           	boost::this_thread::sleep( boost::posix_time::millisec( 1 ) );

+ 1 - 1
websocket/wsTimerThread.h

@@ -6,7 +6,6 @@ websocket定时发送线程类
   V 1.0.0
 
 * @author
-  王益俊
 
 * @date
   创建时间:  2018-08-17\n
@@ -99,6 +98,7 @@ namespace YA
 		*/
 		void __SendCardPos();
         void send_card_pos();
+        void temp_send_card_pos();
 	protected:
 		/**
 		* @brief

+ 7 - 0
worker.cpp

@@ -234,6 +234,13 @@ struct worker_thread: loop_thread ,visitor<std::shared_ptr<card_location_base>>
 				t.destroy();
 			break;
 
+            case CHAR_LIGHT_STATUS:
+                log_info("light message: 0x%04X", t.m_cmd_code);
+                break;
+            case CHAR_LIGHT_HEART:
+                log_info("light message: 0x%04X", t.m_cmd_code);
+                break;
+
 			case 0x10001://区域业务类型修改
 			{
 				update_local_cards();

+ 1 - 1
ya_setting.h

@@ -15,7 +15,7 @@ struct  SSys_setting // system_limit_setting
 	unsigned int over_time_vehicle; // 井下车辆超时
 	double over_speed; // 井下车辆超速
 
-	// lihongzhen  2017/8/18 考勤偏移时间
+	// 考勤偏移时间
 	int att_starttime_offset_staff;
 	int att_endtime_offset_staff;
 	int att_starttime_offset_vehicle;