zhuyf пре 4 година
родитељ
комит
0113b25c58
48 измењених фајлова са 1726 додато и 621 уклоњено
  1. 9 7
      ant.cpp
  2. 7 8
      ant.h
  3. 11 15
      area.cpp
  4. 3 2
      area.h
  5. 0 4
      bulletin_broad_show.cpp
  6. 1 3
      card.cpp
  7. 73 36
      card_base.cpp
  8. 0 2
      card_base.h
  9. 10 12
      card_car.cpp
  10. 2 6
      card_path.cpp
  11. 3 0
      card_person.cpp
  12. 2 1
      common.h
  13. 9 10
      geo_hash.cpp
  14. 66 14
      his_location.cpp
  15. 1 0
      his_location.h
  16. 8 19
      main.cpp
  17. 2 3
      message.cpp
  18. 7 4
      message.h
  19. 4 2
      mine_business.cpp
  20. 13 15
      module_service/area_business_geofault.cpp
  21. 0 2
      module_service/area_business_person_dwell_checker.cpp
  22. 5 3
      module_service/area_business_post_area.cpp
  23. 5 7
      module_service/area_business_speed_checker.cpp
  24. 20 7
      module_service/module_call.cpp
  25. 7 8
      module_service/module_call_help.cpp
  26. 16 15
      module_service/module_meta_data_changed.cpp
  27. 11 15
      module_service/module_mgr.cpp
  28. 229 32
      module_service/module_traffic_light.cpp
  29. 79 8
      module_service/module_traffic_light.h
  30. 10 4
      module_service/module_traffic_light_common.h
  31. 251 15
      module_service/module_traffic_light_manager.cpp
  32. 150 24
      module_service/module_traffic_light_manager.h
  33. 296 103
      module_service/module_traffic_light_rule.cpp
  34. 21 13
      module_service/module_traffic_light_rule.h
  35. 5 2
      module_service/module_web.cpp
  36. 5 7
      module_service/module_web.h
  37. 65 52
      net-service.cpp
  38. 6 3
      protocol.h
  39. 47 2
      websocket/jsonBuilder.cpp
  40. 1 0
      websocket/jsonBuilder.h
  41. 97 2
      websocket/wsClient.cpp
  42. 7 5
      websocket/wsClient.h
  43. 0 4
      websocket/wsClientMgr.h
  44. 19 3
      websocket/wsTimerThread.cpp
  45. 4 0
      websocket/wsTimerThread.h
  46. 137 119
      websocket/ws_common.h
  47. 2 2
      worker.cpp
  48. 0 1
      znet.cpp

+ 9 - 7
ant.cpp

@@ -131,7 +131,6 @@ void site::set_path(const std::vector<line_v>&v_line)
 	};
 	
 	//构造一个首尾相连的结构
-
 	std::vector<line_v> vl(v_line.begin()+1,v_line.end());
 	std::vector<line_v> target(v_line.begin(),v_line.begin()+1);
 #if 0
@@ -190,6 +189,7 @@ std::vector<point> ant::getsol(const double &dist) const
 		point pt;
 		double d  = dist;
 
+        logn_info(3, "[pdoa] dist=%.2f, line.length()=%.2f, %s", dist, p.m_line[0].length(), p.to_str().c_str());
 		if(dist <= p.m_line[0].length())
 		{
 			d += d*p.m_line[0][0].z;
@@ -288,8 +288,8 @@ void sit_list::read_ant_path(int id)
 
 		log_info("src-path:site=%d,x0=%.2f,y0=%.2f,x1=%.2f,y1=%.2f",reader_id,b_x,b_y,e_x,e_y);
 
-		point p1(b_x,-b_y, spacing_ratio);
-		point p2(e_x,-e_y, spacing_ratio);
+		point p1(b_x, b_y, spacing_ratio);
+		point p2(e_x, e_y, spacing_ratio);
 
 		map_path.insert(std::make_pair(reader_id,std::vector<line_v>()));
 		map_path.find(reader_id)->second.push_back(line_v(p1,p2));
@@ -369,12 +369,14 @@ void sit_list::read_ant_path(int id)
 
 		sit_ptr->set_path(vl.second);
         point p;
-        if(!sit_ptr->m_path_empty) {p=(*sit_ptr)[0][0][0].line::projection(*sit_ptr);sit_ptr->set(p);}
+        if(!sit_ptr->m_path_empty){
+            p=(*sit_ptr)[0][0][0].line::projection(*sit_ptr);
+            sit_ptr->set(p);
+        }
         if(p==*sit_ptr)
             log_info("[site_path]%s",sit_ptr->to_string().c_str());
         else
             log_info("[site_path_diff](%f,%f)--%f--%s",p.x,p.y,p.dist(*sit_ptr),sit_ptr->to_string().c_str());
-
 	}
 
 	card_path::init();
@@ -539,7 +541,7 @@ void sit_list::read_sit_list(int id)
             if(!site_ptr)
               continue;
             site_ptr->m_ant[antid].m_id = antenna_id;
-            site_ptr->m_ant[antid].set(x,-y);
+            site_ptr->m_ant[antid].set(x, y);
             site_ptr->m_ant[antid].m_angle = _angle;
             site_ptr->set_ex();
         }
@@ -548,7 +550,7 @@ void sit_list::read_sit_list(int id)
             auto site_ptr = sit_list::instance()->get(reader_id);
             if(site_ptr)
             {
-                site_ptr->m_ant[antid].set(x,-y);
+                site_ptr->m_ant[antid].set(x, y);
                 site_ptr->m_ant[antid].m_angle = _angle;
                 site_ptr->set_ex();
             }

+ 7 - 8
ant.h

@@ -20,7 +20,6 @@
 #include "write-copy.h"
 #include "net-service.h"
 #include "common.h"
-
 #include <boost/circular_buffer.hpp>
 
 class client;
@@ -256,16 +255,16 @@ struct site:point,std::enable_shared_from_this<site>
     std::vector<point> solving(int ant_id, double dist)const
     {
         const ant &a = m_ant[ant_id];
-        if(dist<50 && dist>0)
+        if(dist < 50 && dist > 0)
         {
-            if(dist<m_height)
+            if(dist < m_height)
             {
-                m_height=dist;
-                dist=0;
+                m_height = dist;
+                dist = 0;
             }
             else
             {
-                dist=sqrt(dist*dist-m_height*m_height);
+                dist = sqrt(dist*dist - m_height*m_height);
             }
         }
         return std::move(a.getsol(dist));
@@ -274,7 +273,7 @@ struct site:point,std::enable_shared_from_this<site>
     std::vector<point> solving_pdoa(const int& ant_id, double dist)const
     {
         const ant& a = m_ant[ant_id];
-        logn_info(3, "[pdoa] solving_pdoa, dist=%.4f, a.x=%.4f, a.y=%.4f", dist, a.x, a.y);
+        //logn_info(3, "[pdoa] solving_pdoa, dist=%.4f, a.x=%.4f, a.y=%.4f", dist, a.x, a.y);
         return std::move(a.getsol(dist));
     }
 
@@ -339,7 +338,7 @@ struct sit_list:single_base<sit_list,int,std::shared_ptr<site>>
         read_ant_path(sid);
     }
     ///id=-1为初始化所有
-    void load_from_db(const std::string&ids="" )
+    void load_from_db(const std::string&ids="")
     {
         init_site(ids);
         load(ids);

+ 11 - 15
area.cpp

@@ -2,7 +2,6 @@
 #include <write-copy.h>
 #include "db_api/CDBSingletonDefine.h"
 #include "log.h"
-
 #include <area.h>
 #include "worker.h"
 #include "point.h"
@@ -13,10 +12,8 @@
 #include "landmark.h"
 #include "area_business.h"
 #include "area_persons_thre_time.h"
-
 #include <boost/algorithm/string/split.hpp>
 #include <boost/algorithm/string/classification.hpp>
-
 #include "area_business.h"
 #include "card.h"
 #include "tool_time.h"
@@ -93,6 +90,7 @@ area::area(int id,int limit_count_person, int limit_time_person,double scale,int
 
 void  area::update(int limit_count_person, int limit_time_person,double scale,int32_t mapid, int limit_count_vehicle, int limit_time_vehicle)
 {
+    log_info("scale_test: o_scale:%.2f, n_scale:%.2f", m_scale, scale);
     m_limit_person_min=limit_time_person;
     m_default_limit_person_count=limit_count_person;
     m_persons_thre_time->set_default_person_count_limit(limit_count_person);
@@ -114,10 +112,8 @@ void area::clear()
 	    event_tool::instance()->handle_event(OT_AREA,ev_,m_id,m_limit_vehicle_count,0,false,DT_NORMAL);
     if(m_event_vehicle_show_count)
 	    event_tool::instance()->handle_event(OT_AREA,ev_,m_id,m_limit_vehicle_count,0,false,DT_SPECIAL);
-
 }
 
-
 void area::change_business(uint32_t new_bits)
 {
 	worker*w=worker::instance();
@@ -438,7 +434,7 @@ void area_list::init_from_db(int id/*=-1*/)
 			break;
 		}
         int downmine_index,patt_index,catt_index;
-        downmine_index=patt_index=catt_index=0;
+        downmine_index = patt_index = catt_index = 0;
 		std::unordered_map<int,std::shared_ptr<area>> map;
 		while ( DBRes.GetNextRecod(Error) )
 		{
@@ -494,10 +490,13 @@ void area_list::init_from_db(int id/*=-1*/)
 				ap->m_speed=std::move(map_);
 				ap->m_is_work_area = is_work_area;
                 ap->m_area_type=area_type_id;
-                if(area_type_id==AREA_TYPE_DOWNMINE)downmine_index++;
-                if(b_type&PERSON_ATT_MASK)patt_index++;
-                if(b_type&CAR_ATT_MASK)catt_index++;
-				ap->m_bound=init_path(path,area_id);
+                if(area_type_id == AREA_TYPE_DOWNMINE)
+                    downmine_index++;
+                if(b_type&PERSON_ATT_MASK)
+                    patt_index++;
+                if(b_type&CAR_ATT_MASK)
+                    catt_index++;
+				ap->m_bound = init_path(path,area_id);
 				for(const auto &p : ap->m_bound)
 					log_info("point:area_id:%d--x:%.2f,y:%.2f",area_id,p.x,p.y);
 				map.insert({area_id,ap});
@@ -732,7 +731,6 @@ void area_tool::on_point(const std::shared_ptr<card_location_base>& c,const poin
 		}
 	}
 
-
 	while(c1!=ce)
 	{
 		if((*c1)->m_area->get_frozen_count()==0)
@@ -783,8 +781,7 @@ void area_tool::on_point(const std::shared_ptr<card_location_base>& c,const poin
 			 snprintf(sql, 1024, "REPLACE INTO rt_location (card_id, site_id,cur_time, x, y, z, state, area_info) VALUES (%s, %d,'%s',%lf, %lf, %lf, 0, '%s');",
 			 tool_other::type_id_to_str(c->m_type, c->m_id).c_str(), m_site->id(),_time.c_str(), pt.x, pt.y, pt.z, strAreaInfo.c_str());
 			 db_tool::PushAsync(sql);
-			 log_info("insert rt_location: card=%d site_id=%d,point=%.2f-%.2f,area_info=%s"
-			 ,c->m_id,m_site->id(),pt.x,pt.y,strAreaInfo.c_str());
+			 log_info("insert rt_location: card=%d site_id=%d,point=%.2f-%.2f,area_info=%s", c->m_id, m_site->id(), pt.x, pt.y, strAreaInfo.c_str());
 		 }
     }
 }
@@ -823,7 +820,7 @@ void area_tool::set_area_info(int mapid,double scale,int areaid,const point &pt,
 	else
 	{
 		log_info("wrong type..");
-	}
+	}    
 }
 
 void area_tool::set_area_info(int mapid,int areaid,const point &pt,uint64_t t)
@@ -836,7 +833,6 @@ void area_tool::set_area_info(int mapid,int areaid,const point &pt,uint64_t t)
 	m_area_info[areaid].swap(tinfo);
 }
 
-
 void area_tool::on_change_business(const std::shared_ptr<card_location_base>& c, const task&t)
 {
 	auto&mcb=t.body<message_change_business>();

+ 3 - 2
area.h

@@ -252,8 +252,9 @@ public:
 		if(s == nullptr || m_site == s)
 			return;
 
-        m_site=s;
-		m_mapid=m_site->m_map_id;
+        m_site  = s;
+		m_mapid = m_site->m_map_id;
+        m_scale = m_site->m_scale;
     }
 
 	void on_change_business(const std::shared_ptr<card_location_base>& c, const task&t);

+ 0 - 4
bulletin_broad_show.cpp

@@ -1,7 +1,3 @@
-//
-// Created by songchao.chen on 2019/6/26.
-//
-
 #include <config_file.h>
 #include <boost/algorithm/string/split.hpp>
 #include <boost/algorithm/string.hpp>

+ 1 - 3
card.cpp

@@ -2,11 +2,9 @@
 #include "common_tool.h"
 #include "message.h"
 #include "loc_message.h"
-
 #include "config_file.h"
 #include "card_person.h"
 #include "card_car.h"
-
 #include "db/db_card.h"
 #include "db/db_api/CDBSingletonDefine.h"
 #include "db/db_api/CDBResultSet.h"
@@ -17,7 +15,7 @@
 #include "card.h"
 #include "mine_business.h"
 #include "worker.h"
-#include "ya_setting.h"
+#include "sys_setting.h"
 
 extern config_file config;
 int three_rates_flag    = 0;

+ 73 - 36
card_base.cpp

@@ -1,7 +1,5 @@
-
 #include <memory>
 #include <message.h>
-
 #include "card_message_handle.h"
 #include "card_person.h"
 #include "card_car.h"
@@ -96,30 +94,30 @@ void card_location_base::do_status(int st)
 		m_pwr_stat=0;
 	}
 
-
     module_mgr::do_status((STATUS_CARD)st, m_id, m_type);
 }
 //写入历史轨迹
 void card_location_base::make_his_location(uint64_t t,const point & pt,bool bclose /*= false*/)
 {
-	int area_id=0,map_id=0,site_id=0;
-	if(auto site_ptr=get_area_tool()->m_site)
+	int area_id = 0, map_id = 0, site_id = 0;
+    double scale = 0.0;
+	if(auto site_ptr = get_area_tool()->m_site)
 	{
-		area_id=site_ptr->m_area_id;
-		map_id=site_ptr->m_map_id;
-		site_id=site_ptr->m_id;
+		area_id = site_ptr->m_area_id;
+		map_id  = site_ptr->m_map_id;
+		site_id = site_ptr->m_id;
+        scale   = site_ptr->m_scale;
 	}
-
-    log_info("make_his_location: card_id: %d,map_id: %d,area_id: %d,site_id: %d",m_id,map_id,area_id,site_id);
-	m_his_location_card->push(t,pt,area_id,map_id,site_id,bclose);
+ 
+	//m_his_location_card->push(t,pt,area_id,map_id,site_id,bclose);
+    m_his_location_card->insert(t, pt, area_id, map_id, site_id, scale);
 }
 
 //坐标点输入业务入口
 void card_location_base::on_location(const std::vector<point>&vp,const std::vector<loc_message> &lm )
 {
-    log_info("[business] card_location_base::on_location");
     loc_point pt = m_sel_tool->select_solution(vp, lm);
-    pt.y = -pt.y;
+    pt.y = pt.y;
     
 	auto site_ptr = get_area_tool()->m_site;
 	int sid = 0;
@@ -132,9 +130,9 @@ void card_location_base::on_location(const std::vector<point>&vp,const std::vect
 
 		double acc = lm[0].m_acc;
         m_acc = lm[0].m_acc;
-		log_info("useful:type=%d,card=%d,site=%d,ct=%d,timestamp=%llu, loc_point,x=%f,y=%f acc=%.2f",m_type,m_id,sid,m_ct,m_time,x,y,acc);
+		log_info("useful loc point: type=%d, card=%d, site=%d, ct=%d, timestamp=%llu, x=%f, y=%f, speed=%.2f, acc=%.2f",m_type,m_id,sid,m_ct,m_time,x,y, m_speed, acc);
 		do_business(lm.front().m_sit, pt, acc);
-	}
+}
 	else
 	{
 		log_warn("坐标不可用:site=%d,type=%d,card=%d,ct=%d,x=%f,y=%f",sid,m_type,m_id,m_ct,pt.x,pt.y);
@@ -181,15 +179,23 @@ void card_location_base::on_message(zloop<task*>* loop, message_tdoa_locinfo& lo
 {
     log_info("[tdoa] start calc location.");
     m_ct = loc.m_card_msg.m_sync_num;
-    //m_time = loc.m_time_stamp;
     auto site_ptr = sit_list::instance()->get(loc.m_site_msg.m_site_id);
     
     if(!site_ptr){
         log_warn("[tdoa] 接收到分站的数据:site=%d, card=%d, ct=%d, 但是分站未定义", loc.m_site_msg.m_site_id, m_id, loc.m_card_msg.m_time_stamp);
         return;
     }
+    
+    auto area_tool=get_area_tool();
+	area_tool->set_site(site_ptr);
 
-    m_message_handle->on_message(loop, loc, is_history);
+    handle_message(loc.m_card_msg.m_time_stamp, loc.m_card_msg.m_battery_status);
+	
+    if(site_ptr->is_up_site())
+	{}
+    else{
+          m_message_handle->on_message(loop, loc, is_history);
+    }
 }
 
 /*
@@ -198,7 +204,6 @@ void card_location_base::on_message(zloop<task*>* loop, message_tdoa_locinfo& lo
  * */
 void card_location_base::on_message(zloop<task*>* loop, message_pdoa_locinfo& loc, bool is_history)
 {
-    //log_info("[pdoa] start calc location");
     m_ct = loc.m_card_ct;
     m_time = loc.m_time_stamp;
     auto site_ptr = sit_list::instance()->get(loc.m_site_id);
@@ -207,7 +212,18 @@ void card_location_base::on_message(zloop<task*>* loop, message_pdoa_locinfo& lo
         return;
     }
 
-    m_message_handle->on_message(loop, loc, is_history);
+    auto area_tool=get_area_tool();
+	area_tool->set_site(site_ptr);
+
+    handle_message(loc.m_card_ct, loc.m_batty_status);
+    if(site_ptr->is_up_site()){
+        log_info("card=%d被井上分站[site=%d]收到",m_id, site_ptr->id());
+        area_tool->on_point(shared_from_this(), point(1,1));
+        this->site_hover(loc.m_site_id);
+    }
+    else{
+        m_message_handle->on_message(loop, loc, is_history);
+    }
 }
 
 //前端推送位置函数.
@@ -216,23 +232,24 @@ void card_location_base::upt_card_pos(YA::_CARD_POS_&cp, point &pt)
     point _p;
     if(pt.empty())
     {
-         _p=*this;
-         pt=_p;
+         _p = *this;
+         pt = _p;
     }
     else
-         _p=pt;
+         _p = pt;
 	
-    cp.Type=m_type;
-	cp.ID = m_id;
-	cp.speed = abs(ceil(m_speed));
-	cp.x = tool_other::round(_p.x,3);
-	cp.y = tool_other::round(_p.y,3);
+    cp.Type     =   m_type;
+	cp.ID       = m_id;
+	cp.speed    = abs(ceil(m_speed));
+	cp.x        = tool_other::round(_p.x,3);
+	cp.y        = tool_other::round(_p.y,3);
 	cp.running_stat = m_stat;
-	cp.dept_id = m_deptid;
-	cp.display=m_display;
-	cp.rec_time=m_time;
+	cp.dept_id  = m_deptid;
+	cp.display  = m_display;
+	cp.rec_time = m_time;
 	cp.level_id = m_level_id;
-	cp.stat=m_pwr_stat;
+	cp.stat     = m_pwr_stat;
+    cp.m_freq   = m_freq;
 	
 	swsTimerThrd.upt_card_pos(cp);
 }
@@ -244,6 +261,7 @@ void card_location_base::del_card_pos()
 	cp.Type=m_type;
 	swsTimerThrd.del_card_pos(cp);
 }
+
 int  card_location_base::get_stat()
 {
 	//盲区>呼救>呼叫>超时>超速>正常
@@ -284,6 +302,19 @@ void  card_location_base::clear()
     m_stat=0;			//运动静止状态
     //m_ct;				//ct
     m_time=0;			//时间戳
+
+    //pdoa location info clear
+    m_buff_size = 0;
+    m_last_recv_time = 0;
+    m_last_point = point(0,0);
+    m_last_site_id = 0;
+    m_last_site_dir = -1;
+    m_last_ct = 0;
+    m_last_dist = 0.0;
+    m_pdoa_diff = m_last_pdoa_diff = 100.0;
+    m_cb_pdoa.clear();
+    m_cb_tof.clear();
+    m_cb_point.clear();
 }
 
 void card_location_base::put_three_rates(card_pos & cp)
@@ -323,12 +354,14 @@ void card_location_base::put_traffic_light(card_pos& cp)
     lm.m_pos.z = cp.z;
     lm.m_pos.m_card_id = m_id;
     lm.m_pos.m_type = m_type;
-    //auto site = sit_list::instance()->get(cp.m_reader_id);
-    //lm.m_pos.m_area_id = site->m_site_id;
+    auto site_ptr = get_area_tool()->m_site;
+    if(site_ptr){
+        lm.m_pos.m_area_id = site_ptr->m_area_id;
+    }
     //lm.m_pos.m_bigger = 0;
     lm.m_pos.m_speed = m_speed;
-    log_info("[traffic_light] put light message to traffic light module, card_id=%d, ctype=%d, x=%.2f, y=%.2f", m_id, m_type, x, y);
-    //traffic_light_manager::instance()->update(int(x), int(y), m_id);
+
+    log_info("[traffic_light] put locate info into traffic light module, card_id=%d, ctype=%d, x=%.2f, y=%.2f", m_id, m_type, x, y);
     traffic_light_manager::instance()->put(lm);
 }
 
@@ -343,9 +376,13 @@ bool card_location_base::is_vehicle() const
 }
 
 void card_location_base::set_base_data(uint32_t cid,uint16_t type,uint32_t deptid,int32_t level_id) {
-    m_cid=cid;m_type=type;m_deptid=deptid;m_level_id=level_id;
+    m_cid       = cid;
+    m_type      = type;
+    m_deptid    = deptid;
+    m_level_id  = level_id;
     m_his_location_card->set_cid(cid);
 }
+
 card_location_base::~card_location_base()
 {
 }

+ 0 - 2
card_base.h

@@ -8,8 +8,6 @@
 #include "common.h"
 #include <boost/circular_buffer.hpp>
 
-#define CARD_LOST_TIME_OUT (60*1000)
-
 struct task;
 template<typename T> struct zloop;
 struct select_tool;

+ 10 - 12
card_car.cpp

@@ -13,7 +13,7 @@
 #include "mine_business.h"
 #include "loc_point.h"
 #include "module_service/module_call.h"
-#include "ya_setting.h"
+#include "sys_setting.h"
 #include "event.h"
 
 car::car(const std::string&type,uint32_t cardid,uint16_t needdisplay,int16_t t,int32_t deptid,
@@ -34,7 +34,7 @@ std::shared_ptr<mine_tool> car::get_mine_tool()
 }
 void car::set_area_info(int mapid,double scale,int areaid,uint64_t t,int type)
 {
-	m_area_tool->set_area_info(mapid,scale,areaid,*this,t,type);
+	m_area_tool->set_area_info(mapid, scale, areaid, *this, t, type);
 }
 
 void car::do_business(const std::shared_ptr<site>&site,const point &pt,double acc)
@@ -42,7 +42,6 @@ void car::do_business(const std::shared_ptr<site>&site,const point &pt,double ac
 	m_acc=acc;
 	m_area_tool->on_point(shared_from_this(),pt);
 	m_timeval = m_time;
-    //log_info("[anti_coll] m_id = %d, m_timeval = %lld", m_id, m_timeval);
 	handle_three_rates(pt);
     handle_traffic_light(pt);
     if(m_enable_anti_collision){
@@ -59,7 +58,6 @@ int car::get_vehicle_type_id()
 
 void car::handle_anti_coll(const point& pt, const int& sid)
 {
-    //log_info("[anti_coll] handle anti collision");   
     // 车卡下发最紧急的呼叫类型
     std::map<int, float> cd;    // 人卡与车卡的距离,key为人卡id,value为距离
     std::map<int, call_card> cards;
@@ -153,9 +151,6 @@ void car::handle_three_rates(const point &pt)
 	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;
 	put_three_rates(cp);
@@ -169,7 +164,7 @@ void car::handle_traffic_light(const point& p)
     cp.z = p.z;
     cp.biz_stat = get_stat();
     cp.map_id = m_area_tool->get_mapid();
-    cp.vibration = m_acc;
+    cp.vibration = m_acc; 
     put_traffic_light(cp);
 }
 
@@ -178,6 +173,7 @@ void car::on_timer()
     if(!empty())
 	    make_package();
 }
+
 int car::get_area()
 {
 	int status = m_biz_stat;
@@ -201,10 +197,12 @@ void car::make_package()
 	cp.down_time = m_mine_tool->get_down_time();
 	cp.work_time = m_mine_tool->get_work_time();
 	cp.is_on_duty= m_mine_tool->is_on_duty();
-	upt_card_pos(cp,pt);
-    make_his_location(pt.m_time,pt);
-	uint64_t _now=tool_time::now_to_ms();
-	uint64_t t=_now>m_timeval?_now-m_timeval:m_timeval-_now;
+	upt_card_pos(cp, pt);
+
+    uint64_t _now = tool_time::now_to_ms();
+    pt.m_time = _now;
+    make_his_location(pt.m_time, pt);
+	uint64_t t = _now>m_timeval?_now-m_timeval:m_timeval-_now;
 	if(t>10*1000)
 	{
 		m_area_tool->on_point(shared_from_this(),pt);

+ 2 - 6
card_path.cpp

@@ -15,9 +15,6 @@
 
 namespace{
 
-//static const double PI  = 3.1415926;
-//static const double TPI = 2*PI;
-
 inline bool eq(double a,double b,double e=0.0001)
 {
 	return fabs(a-b)<e;
@@ -103,7 +100,6 @@ struct vertex_list
 		log_info("%s",to_string().c_str());
 	}
 
-
 	static unsigned hash(const point&p)
 	{
 		return (((((unsigned)p.x)>>2)<<16) + (((unsigned)p.y)>>2));
@@ -193,6 +189,7 @@ point  base_path::cross(const vertex_list&v, const base_path&o)const
 
 	return l0.crossing(l1);
 }
+
 void log_path(const std::vector<base_path>&path,const vertex_list&v_list,const char*add_info="")
 {
 	log_info("%s\n","----------------------------------------------------------------");
@@ -202,6 +199,7 @@ void log_path(const std::vector<base_path>&path,const vertex_list&v_list,const c
 		log_info("base_path:%s %.6lf, %03d,(%d,%s),(%d,%s)",add_info,c,i,path[i][0],v_list[path[i][0]].to_string().c_str(),path[i][1],v_list[path[i][1]].to_string().c_str());
 	}
 }
+
 struct handle_path :visitor<std::shared_ptr<site>>
 {
 	std::vector<base_path> ret;
@@ -460,8 +458,6 @@ static std::vector<base_path> init_path(std::vector<base_path> & ret,vertex_list
 	return std::move(ret2);
 }
 
-
-
 #if 0
 struct ghash
 {

+ 3 - 0
card_person.cpp

@@ -45,8 +45,10 @@ person::person(const std::string &type,uint32_t cardid,uint16_t needdisplay,int1
 person::~person()
 {
 }
+
 void person::clear()
 {
+    log_info("make_his_location clear");
     make_his_location(m_time,*this,true);
     //初始化区域和井下部分基础信息
     m_mine_tool->clear();
@@ -118,6 +120,7 @@ void person::do_business(const std::shared_ptr<site>&site,const point &pt,double
     //区域相关逻辑驱动
 	m_area_tool->on_point(shared_from_this(),pt);
     //处理历史轨迹
+    log_info("make_his_location  person");
     make_his_location(m_time,pt);
 	m_timeval=m_time;
     //三率数据处理

+ 2 - 1
common.h

@@ -6,6 +6,7 @@
 #define READER_TIMEOUT 20
 #define PI 3.1415926
 #define TPI (2*3.1415926)
+#define CARD_LOST_TIME_OUT (60*1000)
 
 /**
  * @brief 分站位置 1井上,2井下
@@ -121,7 +122,7 @@ enum EVENT_TYPE{
     ET_OVER_COUNT_VEHICLE = 2,              // 井下车辆超员
     ET_AREA_OVER_COUNT_PERSON = 3,	        // 区域人员超员
     ET_AREA_OVER_COUNT_VEHICLE = 4,	        // 区域车辆超员
-    ET_READER_ERROR = 6,
+    ET_READER_ERROR = 6,                    //
 
     ET_CARD_LOW_POWER_SERIOUS = 12,         // 电量极低
     ET_CARD_OVER_TIME_PERSON = 13,          // 人员井下超时

+ 9 - 10
geo_hash.cpp

@@ -31,15 +31,15 @@ std::vector<uint64_t> geo_list::find_near(int x,int y,int dist,uint64_t card_no)
 
 	unsigned mask=~(t*t-1);
 
-	find_near(r,x,y,ghash::encode(x0-t,y0-t),dist2,mask,card_no);
-	find_near(r,x,y,ghash::encode(x0,y0-t),dist2,mask,card_no);
-	find_near(r,x,y,ghash::encode(x0+t,y0-t),dist2,mask,card_no);
-	find_near(r,x,y,ghash::encode(x0-t,y0),dist2,mask,card_no);
-	find_near(r,x,y,ghash::encode(x0,y0),dist2,mask,card_no);
-	find_near(r,x,y,ghash::encode(x0+t,y0),dist2,mask,card_no);
-	find_near(r,x,y,ghash::encode(x0-t,y0+t),dist2,mask,card_no);
-	find_near(r,x,y,ghash::encode(x0,y0+t),dist2,mask,card_no);
-	find_near(r,x,y,ghash::encode(x0+t,y0+t),dist2,mask,card_no);
+	find_near(r, x, y, ghash::encode(x0-t,y0-t), dist2, mask, card_no);
+	find_near(r, x, y, ghash::encode(x0,y0-t), dist2, mask, card_no);
+	find_near(r, x, y, ghash::encode(x0+t,y0-t), dist2, mask, card_no);
+	find_near(r, x, y, ghash::encode(x0-t,y0), dist2, mask, card_no);
+	find_near(r, x, y, ghash::encode(x0,y0), dist2, mask, card_no);
+	find_near(r, x, y, ghash::encode(x0+t,y0), dist2, mask, card_no);
+	find_near(r, x, y, ghash::encode(x0-t,y0+t), dist2, mask, card_no);
+	find_near(r, x, y, ghash::encode(x0,y0+t), dist2, mask, card_no);
+	find_near(r, x, y, ghash::encode(x0+t,y0+t), dist2, mask, card_no);
 
 	return std::move(r);
 }
@@ -78,7 +78,6 @@ void geo_list::update(int x,int y,uint64_t card_no)
 				geo2card.erase(it1);
 				break;
 			}
-
 		}
 
 		geo2card.insert(std::make_pair(h,card_no));

+ 66 - 14
his_location.cpp

@@ -36,37 +36,46 @@ void location_card::init()
     last_timestamp=0;
     set_invalid();
 }
+
 void location_card::init_att(const point &pt,uint64_t time)
 {
     std::queue<mini_data> tmp;
     m_d.swap(tmp);
     m_d.emplace(pt,time);
 }
+
 void location_card::set_invalid()
 {
     m_arg=0x12345678;
 }
+
 bool location_card::is_valid()
 {
     return m_arg!=0x12345678;
 }
+
 double location_card::make_arg(const point &pt,const point &p)
 {
     log_info("his_location arg[%d],(%.2f,%.2f)--->(%.2f,%.2f)---->(%.2f,%.2f)",m_cardid,m_p.x,m_p.y,p.x,p.y,pt.x,pt.y);
     return  std::arg(std::complex<double>(pt.x,pt.y)-std::complex<double>(p.x,p.y));
 }
+
 void location_card::set(const point &pt,uint64_t time)
 {
     m_timestamp=time;
     m_p.set(pt);
     init_att(pt,time);
 }
+
 bool location_card::line_changed(const point &pt)//,int &df)
 {
     if(!is_valid())
         return false;
     point p;
-    if(m_d.empty())p=m_p;  else p=m_d.back().p;
+    if(m_d.empty())
+        p=m_p;  
+    else 
+        p=m_d.back().p;
 
     if(point::eq(p.x,pt.x,0.2) && point::eq(p.y,pt.y,0.2)) return false;
     double dis1=m_p.dist(pt);
@@ -92,6 +101,7 @@ bool location_card::line_changed(const point &pt)//,int &df)
     //return !point::eq(arg,m_arg,1e-10);
     return !change_flag;
 }
+
 bool location_card::is_speed_changed(const point& pt,uint64_t time)
 {
     bool flag = false;
@@ -118,6 +128,7 @@ bool location_card::is_speed_changed(const point& pt,uint64_t time)
 
     return flag;
 }
+
 bool location_card::time_out(const point &p,uint64_t time)
 {
     uint64_t t=last_timestamp==0?m_timestamp:last_timestamp;
@@ -152,12 +163,14 @@ bool location_card::is_map_changed(int new_mapid)
 
 void location_card::push(uint64_t timestamp,const point & p,int32_t areaid,int32_t mapid,int32_t siteid,bool bclose/* = false*/)
 {
+    //log_info("his_location: 1111111111111111111; timestamp=%d, p.x=%.2f, p.y=%.2f", timestamp, p.x, p.y);
     if (bclose) //卡移除后直接更新his_location
     {
         update(p,timestamp);
         init();
         return;
     }
+    //log_info("his_location: m_p.empty()=%d, m_timestamp=%d, m_areaid=%d, m_mapid=%d, m_siteid=%d", m_p.empty(), m_timestamp, m_areaid, m_mapid, m_siteid);
     if(m_p.empty() || m_timestamp==0||m_areaid<0||m_mapid<0 || m_siteid < 0)
     {
         set(p,timestamp);
@@ -167,7 +180,7 @@ void location_card::push(uint64_t timestamp,const point & p,int32_t areaid,int32
         m_d.emplace(p,timestamp);
         return ;
     }
-
+    //log_info("his_location: 3333333333333333333333333");
     if(!is_valid())
     {
         //if(p==m_p)
@@ -191,7 +204,7 @@ void location_card::push(uint64_t timestamp,const point & p,int32_t areaid,int32
         insert();
         return;
     }
-
+    //log_info("his_location: 44444444444444444444444444444444444");
     bool flag=false;
     int  iflag=0;
     //判断是否路径发生了变化
@@ -218,6 +231,33 @@ void location_card::push(uint64_t timestamp,const point & p,int32_t areaid,int32
         }
     }
 }
+
+void location_card::insert(uint64_t timestamp, const point & p, int32_t areaid, int32_t mapid, int32_t siteid, double scale)
+{
+    double speed = 0.0;
+    double dist = 0.0;
+    if(m_timestamp != 0){
+        dist = m_p.dist(p)*scale;
+        
+        if(fabs(dist) < 1){
+            return;
+        }
+   
+        double t	= (timestamp - m_timestamp)/1000;
+        speed       = dist/t;
+        if(std::isnan(speed)|| std::isinf(speed))
+            speed=0;
+    }
+
+    m_timestamp = timestamp;
+    m_p = p;
+
+    char sql[512] = {0};
+    snprintf(sql, 512, "replace into his_location_simplify(obj_id, card_type_id, ident, loc_time, map_id, area_id, begin_pt, reader_id, speed) values (%d, %d, %d, '%s', %d, %d, '%.2f,%.2f', %d, %.2f);", m_objid, m_type, m_cardid, tool_time::to_str(timestamp/1000).c_str(), mapid, areaid, p.x, p.y, siteid, speed);
+    log_info("his_location_simplify: %d-%lu: %s", m_cardid, timestamp, sql);
+    sDBConnPool.PushAsync(sql);
+}
+
 void location_card::insert()
 {
     //std::string tabName=getTabName();
@@ -228,6 +268,7 @@ void location_card::insert()
     log_info("his_location[%d,%lu]:%s",m_cardid,m_timestamp,nsql);
     sDBConnPool.PushAsync(nsql);
 }
+
 void location_card::update(const point &p,uint64_t timestamp,int flag/*=0*/,int dflag/*=0*/)
 {
     //std::string tabName=getTabName();
@@ -258,15 +299,15 @@ std::vector<point> location_card::find_path(const point &p1,const point &p2)
     std::vector<point> rc=card_path::inst().find_path(point(p1.x,-p1.y),point(p2.x,-p2.y));
     return std::move(rc);
 }
-//virtual bool  handle_message(const point &p,uint64_t timestamp)=0;
+
 bool  location_card::handle_message(const point &p,uint64_t timestamp)
 {
     bool flag = false;
-    //int df=0;
-    if(line_changed(p))//,df))
+
+    if(line_changed(p))
     {
         flag = true;
-        //std::vector<point> rc=find_path(m_d.back().p,p);
+
         std::vector<point> rc=find_path(m_p,p);
         if(rc.empty())
         {
@@ -281,23 +322,34 @@ bool  location_card::handle_message(const point &p,uint64_t timestamp)
         }
         //置m_arg非法
         set_invalid();
+    }else{
+        log_info("his_location: line not change");
     }
-    //if(df==1)flag=true;
+
     return flag;
 }
+
 bool location_card::handle_path(std::vector<point> &rc,uint64_t timestamp,bool flag)
 {
-    double dis=0;point _p=m_p;
+    double dis=0;
+    point _p=m_p;
     std::for_each(rc.begin(),rc.end(),[&dis,&_p](point &pt){
-        pt.y=-pt.y;dis+=_p.dist(pt);_p=pt;
+        pt.y = pt.y;
+        dis+=_p.dist(pt);
+        _p=pt;
     });
     uint64_t t=timestamp/1000 - m_timestamp/1000;
-    if(t==0||dis<0.1)return true;
+    if(t==0||dis<0.1){
+        log_info("his_location: card_id=%d, t=%d, dist=%.2f, rc.size=%d", m_cardid, t, dis, rc.size());
+        return true;
+    }
     double avge_speed= dis/t;
     //有拐点  盲区时间差 距离
-    uint64_t difftime=t;int dflag=0;
-    if(!m_d.empty()) difftime=timestamp/1000-(m_d.back().time)/1000;
-    if(difftime>=location_card::m_difftime && dis>location_card::m_distance)
+    uint64_t difftime = t;
+    int dflag = 0;
+    if(!m_d.empty()) 
+        difftime = timestamp/1000-(m_d.back().time)/1000;
+    if(difftime >= location_card::m_difftime && dis>location_card::m_distance)
     {
         log_info("his_location[%d]:abnormal_line difftime:%lu,ltime:%u,dis:%.2f,limit_dis:%d",m_cardid,difftime,location_card::m_difftime,dis,location_card::m_distance);
         dflag=1;

+ 1 - 0
his_location.h

@@ -59,6 +59,7 @@ struct location_card
 	void push(uint64_t timestamp,const point & p,int32_t areaid,int32_t mapid,int32_t siteid,bool bclose = false);
 
 	void insert();
+    void insert(uint64_t timestamp, const point & p, int32_t areaid, int32_t mapid, int32_t siteid, double scale);
 
 	void update(const point &p,uint64_t timestamp,int flag=0,int dflag=0);
     // 操作路径上点的集合

+ 8 - 19
main.cpp

@@ -17,7 +17,7 @@
 #include <config_file.h>
 #include "three_rates.h"
 #include "mine_business.h"
-#include "ya_setting.h"
+#include "sys_setting.h"
 #include "websocket/web_connect.h"
 #include "forbid_staff_down_mine.h"
 #include "bulletin_broad_show.h"
@@ -38,11 +38,6 @@ 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()
@@ -80,26 +75,20 @@ struct Init_Setting
             log_warn("连接webServer[%s] 失败!",url.c_str());
         }
 		CYaSetting::Init_sys_setting();
-        bulletin_broad_show::inst()->OnInit(&config);
+        //公告牌功能
+        //bulletin_broad_show::inst()->OnInit(&config);
 
         sit_list::instance()->load_from_db();
         card_list::instance()->init_card_from_db();
         area_list::instance()->init_from_db();
         area_list::instance()->init_area_persons_dynamic_thre_from_db();
 
-        forbid_staff_down_mine::instance()->init_forbid_staff();
-        //point pt(3348,100);
-        //int id = area_list::instance()->get_area(pt)->id();
-        //std_info("test area:%d",id);
-        Landmark_list::instance()->init_from_db();
-        //auto a = Landmark_list::instance()->get(5,id,pt);
-        //std_info("test landmark:id:%d,dir:%d,dis:%.2f",std::get<0>(a),std::get<1>(a),std::get<2>(a));
-        special_area_list::instance()->init_from_db();
-        //auto s = special_area_list::instance()->get_special_id(1013,point(4727,-254),2);
-        //std_info("test special_area:%d",s);
+        //forbid_staff_down_mine::instance()->init_forbid_staff();
+        //Landmark_list::instance()->init_from_db();
+        //special_area_list::instance()->init_from_db();
 		mine_business::inst()->load();
         card_list::instance()->load_his_card_postion_from_db();
-        event_list::instance()->load_his_data_from_db();
+        //event_list::instance()->load_his_data_from_db();
         if(three_rates_flag){
             db_para dp;	
             dp.Host=DBSetting.Host;
@@ -135,7 +124,7 @@ struct Init_Setting
     void init_traffic_light()
     {
         log_info("init traffic_light ...................");
-        traffic_light_manager::instance()->init(handle_traffic_light);
+        traffic_light_manager::instance()->init(CYaSetting::m_sys_setting.light_group_count);
         traffic_light_manager::instance()->start();
         std_info("成功加载信号灯模块");
     }

+ 2 - 3
message.cpp

@@ -320,14 +320,13 @@ void message_pdoa_locinfo::zero_this()
     m_site_id = 
     m_card_type = 
     m_card_id = 
-    m_card_type =
     m_card_ct = 
     m_batty_status = 
     m_callinfo = 
-    m_rav = 
     m_acc = 
     m_ant_id = 
     m_rssi = 0; 
+    m_rav = 0;
     m_poa[0] = 
     m_poa[1] = 
     m_poa[2] = 0.0;
@@ -391,5 +390,5 @@ void message_pdoa_locinfo::load(zistream& is)
         m_poa[i] = (float)((((short)_poa)*1.0)/1000.0);
     }
 
-    logn_info(3,"[pdoa] card_type=%d, card_id=%d, ct=%d, status=%d, acc=%d, tof=%llu, ant_id=%d, rssi=%d, poa1=%.2f, poa2=%.2f, poa3=%.2f", m_card_type, m_card_id, m_card_ct, m_batty_status, m_acc, m_tof, m_ant_id, m_rssi, m_poa[0], m_poa[1], m_poa[2]);
+    logn_info(3,"[pdoa] card_type=%d, card_id=%d, ct=%d, status=%d, rav=%d, acc=%d, tof=%llu, ant_id=%d, rssi=%d, poa1=%.2f, poa2=%.2f, poa3=%.2f", m_card_type, m_card_id, m_card_ct, m_batty_status, m_rav, m_acc, m_tof, m_ant_id, m_rssi, m_poa[0], m_poa[1], m_poa[2]);
 }

+ 7 - 4
message.h

@@ -39,7 +39,7 @@ struct message_tdoa_card{
 	uint16_t m_time_stamp;          // 卡报文时间戳
 	uint8_t  m_battery_status;      //  电池状态
 	uint8_t  m_call_info;           // 0x80-呼救,0x01-一般呼叫,0x02-紧急呼叫
-	uint8_t  m_rav;                 // 角速度
+	int8_t  m_rav;                 // 角速度
 	uint8_t  m_acc;                 // 加速度
     uint64_t m_loc_stamp;           // 定位时间戳
 	uint8_t  m_ant_id;              // 天线号
@@ -109,13 +109,12 @@ struct message_locinfo:task
 	time_t   m_site_time;   // 分站时间
 	uint64_t m_tof;         // 卡tof值
 	uint32_t m_site_id;     // 分站号
-
 	uint32_t m_card_type;   // 卡类型
 	uint32_t m_card_id;     // 卡id
 	uint16_t m_card_ct;     // 卡报文时间戳
 	uint8_t  m_batty_status;//  电池状态
 	uint8_t  m_callinfo;    // 0x80-呼救,0x01-一般呼叫,0x02-紧急呼叫
-	uint8_t  m_rav;         // 角速度
+	int8_t  m_rav;         // 角速度
 	uint8_t  m_acc;         // 加速度
 	uint8_t  m_ant_id;      // 天线号
 	uint16_t m_sync_ct;     // 同步序列号 
@@ -170,9 +169,13 @@ struct message_light: task{
     uint32_t m_light_id;
     uint8_t  m_type;
     uint16_t m_stamp;
+    uint64_t m_recv_time;
     uint8_t  m_status;
 
-    message_light(): m_light_id(0), m_type(0), m_stamp(0), m_status(0)
+    message_light(): m_light_id(0), m_type(0), m_stamp(0), m_recv_time(0), m_status(0)
+    {}
+
+    message_light(const uint32_t& lid, const uint16_t& type, const uint8_t& stamp, const uint64_t& rtime): m_status(0)
     {}
 };
 

+ 4 - 2
mine_business.cpp

@@ -11,12 +11,11 @@
 #include "db/db_tool.h"
 #include "common_tool.h"
 #include "ant.h"
-#include "ya_setting.h"
+#include "sys_setting.h"
 #include "card_path.h"
 #include "card.h"
 #include "area.h"
 #include "event.h"
-
 #include <rapidjson/writer.h>
 #include <rapidjson/stringbuffer.h>
 #include <rapidjson/prettywriter.h>
@@ -497,6 +496,9 @@ void reverse_alarm_business::get_status()
 	value.SetString("vehicle_state", Allocator );
 	root.AddMember( "cmd", value, Allocator );
 
+    if(LArray.Capacity() == 0){
+        return;
+    }
     root.AddMember("data",LArray,Allocator);
 
 	value.SetString("1.0.0.4", Allocator );

+ 13 - 15
module_service/area_business_geofault.cpp

@@ -1,18 +1,16 @@
-#include"area_business_geofault.h"
-
-#include<memory>
-#include<string>
-
-#include"area_business.h"
-#include"event.h"
-#include"db_api/CDBSingletonDefine.h"
-#include"ya_setting.h"
-#include"common_tool.h"
-#include"log.h"
-#include"card.h"
-#include"config_file.h"
-#include"point.h"
-#include"area.h"
+#include "area_business_geofault.h"
+#include <memory>
+#include <string>
+#include "area_business.h"
+#include "event.h"
+#include "db_api/CDBSingletonDefine.h"
+#include "sys_setting.h"
+#include "common_tool.h"
+#include "log.h"
+#include "card.h"
+#include "config_file.h"
+#include "point.h"
+#include "area.h"
 
 struct geofault_data:business_data
 {

+ 0 - 2
module_service/area_business_person_dwell_checker.cpp

@@ -46,10 +46,8 @@ void area_business_person_dwell_checker::on_hover(const std::shared_ptr<area_hov
         uint64_t id = tool_other::type_id_to_u64(c->m_type, c->m_id);
         event_tool::instance()->handle_event(OT_CARD,evType,id, a->m_area->m_limit_person_min,cur_val/60,true);
     }
-
 }
 
-
 //如果有超时告警,取消超时告警
 void area_business_person_dwell_checker::on_leave(const std::shared_ptr<area_hover>&a,
 							const std::shared_ptr<card_location_base>&c,std::shared_ptr<business_data> ptr)

+ 5 - 3
module_service/area_business_post_area.cpp

@@ -14,21 +14,23 @@ void area_business_post_area::on_load_his(const std::shared_ptr<area_hover>&a,co
 void area_business_post_area::on_enter(const std::shared_ptr<area_hover>&a,
 						const std::shared_ptr<card_location_base>&c,std::shared_ptr<business_data>&ptr)
 {
-    log_info("pos_area:cardid:%d,area_id:%d",c->m_id,a->id());
+    log_info("post_area: type:0, cardid:%d, area_id:%d, scale:%.2f", c->m_id, a->id(), a->scale());
 	c->set_area_info(a->mapid(),a->scale(),a->id(),a->m_enter_time,0);
 }
 
 void area_business_post_area::on_hover(const std::shared_ptr<area_hover>&a,
 						const std::shared_ptr<card_location_base>&c,std::shared_ptr<business_data> ptr)
 {
-	c->set_area_info(a->mapid(),a->scale(),a->id(),a->m_enter_time,1);
+    log_info("post_area: type:1, cardid:%d, area_id:%d, scale:%.2f", c->m_id, a->id(), a->scale());
+    c->set_area_info(a->mapid(),a->scale(),a->id(),a->m_enter_time,1);
 }
 
 //从人员数据中清除区域信息
 void area_business_post_area::on_leave(const std::shared_ptr<area_hover>&a,
 						const std::shared_ptr<card_location_base>&c,std::shared_ptr<business_data> ptr)
 {
-	c->set_area_info(0,0,a->id(),0,2);
+    log_info("post_area: type:2, cardid:%d, area_id:%d, scale:%.2f", c->m_id, a->id(), a->scale());
+    c->set_area_info(0,0,a->id(),0,2);
 }
 
 

+ 5 - 7
module_service/area_business_speed_checker.cpp

@@ -1,11 +1,9 @@
 #include "area_business_speed_checker.h"
-
-#include"event.h"
-#include"common_tool.h"
-#include"db/db_api/CDBSingletonDefine.h"
-#include"log.h"
-
-#include"area.h"
+#include "event.h"
+#include "common_tool.h"
+#include "db/db_api/CDBSingletonDefine.h"
+#include "log.h"
+#include "area.h"
 #include "card.h"
 
 struct over_speed_data:business_data

+ 20 - 7
module_service/module_call.cpp

@@ -1,5 +1,4 @@
 #include "module_call.h"
-
 #include <boost/bind.hpp>
 #include <boost/algorithm/string.hpp>
 #include <vector>
@@ -16,6 +15,7 @@
 #include "crc.h"
 #include "mine.h"
 #include "event.h"
+#include "tool_byte.h"
 
 uint64_t call_card::to_id64()
 {
@@ -796,9 +796,17 @@ std::string module_call::get_json_anti_collision()
      
         rapidjson::Value obj(rapidjson::kObjectType);
         
-        rapidjson::Value vid(rapidjson::kObjectType); 
-        vid.SetInt(atoi(it_ev->second->m_obj_id.c_str()));
-        obj.AddMember("vid", vid, allocator);
+        //rapidjson::Value vid(rapidjson::kObjectType); 
+        //vid.SetInt(atoi(it_ev->second->m_obj_id.c_str()));
+
+        /*std::string str_vid = "";
+        char szID[32] = {0};
+        sprintf(szID, "%03d%.10d", 2, atoi(it_ev->second->m_obj_id.c_str()));
+        str_vid = szID;
+        */
+
+        rapidjson::Value val;
+        obj.AddMember("vid", val.SetString(it_ev->second->m_obj_id.c_str(), allocator), allocator);
 
         rapidjson::Value elems(rapidjson::kArrayType);
         std::string msg = it_ev->second->m_desc;
@@ -815,11 +823,16 @@ std::string module_call::get_json_anti_collision()
             rapidjson::Value e(rapidjson::kArrayType);
             rapidjson::Value o(rapidjson::kObjectType);
 
-            o.SetInt(atoi(vt_cid_d[0].c_str()));
-            e.PushBack(obj, allocator);
+            //o.SetInt(atoi(vt_cid_d[0].c_str()));
+            /*memset(szID, 0, 32);
+            sprintf(szID, "%03d%.10d", 1, atoi(vt_cid_d[0].c_str()));
+            str_vid = szID;
+            */
+            o.SetString(tool_byte::to_cardid(1, atoi(vt_cid_d[0].c_str())).c_str(), allocator);
+            e.PushBack(o, allocator);
 
             o.SetDouble(atof(vt_cid_d[1].c_str()));
-            e.PushBack(obj, allocator);
+            e.PushBack(o, allocator);
             
             elems.PushBack(e, allocator);   
         }

+ 7 - 8
module_service/module_call_help.cpp

@@ -1,11 +1,10 @@
-#include"module_call_help.h"
-
-#include"event.h"
-#include"common_tool.h"
-#include"websocket/constdef.h"
-#include"log.h"
-#include"db/db_tool.h"
-#include"tool_time.h"
+#include "module_call_help.h"
+#include "event.h"
+#include "common_tool.h"
+#include "websocket/constdef.h"
+#include "log.h"
+#include "db/db_tool.h"
+#include "tool_time.h"
 
 /**
  * @brief //1.如果已经有呼救告警

+ 16 - 15
module_service/module_meta_data_changed.cpp

@@ -1,25 +1,25 @@
 #include "module_meta_data_changed.h"
-#include"area_business_person_attendance.h"
-#include"area_business_car_attendance.h"
-
-#include"common_tool.h"
+#include "area_business_person_attendance.h"
+#include "area_business_car_attendance.h"
+#include "common_tool.h"
 #include "websocket/wsClientMgr.h"
-#include"db/db_api/CDBSingletonDefine.h"
-#include"event.h"
-
-#include"ant.h"
-#include"card.h"
-#include"area.h"
+#include "db/db_api/CDBSingletonDefine.h"
+#include "event.h"
+#include "ant.h"
+#include "card.h"
+#include "area.h"
 #include "forbid_staff_down_mine.h"
 #include "landmark.h"
 #include <three_rates.h>
-#include"area_business_geofault.h"
+#include "area_business_geofault.h"
 #include <boost/format.hpp>
 #include <boost/tokenizer.hpp>
 #include <boost/algorithm/string/split.hpp>
 #include <boost/algorithm/string.hpp>
 #include <card_path.h>
-#include "ya_setting.h"
+#include "sys_setting.h"
+#include "module_traffic_light_manager.h"
+
 ///基础数据
 void module_meta_data_changed::accept(sio::message::ptr const& data)
 {
@@ -33,9 +33,6 @@ void module_meta_data_changed::accept(sio::message::ptr const& data)
     std::string szParam = "0";
     tool_map::try_get_value(szParam,JSON_KEY_ID,data);
 
-   // int id=-1;
-   // tool_map::try_get_value(id,JSON_KEY_ID,data);
-
     std::string op_type="";
     tool_map::try_get_value(op_type, JSON_KEY_OP_TYPE, data);
 
@@ -294,9 +291,11 @@ void module_meta_data_changed::deal_call_edit_light(int id, EDIT_TYPE_ID edit_ty
 {
     if(ET_INSERT == edit_type_id || ET_UPDATE == edit_type_id)
     {
+        traffic_light_manager::instance()->init_light_from_db(id);
     }
     else if(ET_DELETE == edit_type_id)
     {
+        traffic_light_manager::instance()->remove_light(id);
     }
 }
 
@@ -304,9 +303,11 @@ void module_meta_data_changed::deal_call_edit_lights_group(int id, EDIT_TYPE_ID
 {
     if(ET_INSERT == edit_type_id || ET_UPDATE == edit_type_id)
     {
+        traffic_light_manager::instance()->init_light_group_from_db(id);
     }
     else if(ET_DELETE == edit_type_id)
     {
+        traffic_light_manager::instance()->remove_light_group(id);
     }
 }
 

+ 11 - 15
module_service/module_mgr.cpp

@@ -1,16 +1,14 @@
-#include"module_mgr.h"
-
-
-#include"module_web.h"
-#include"module_call_help.h"
-#include"module_call.h"
-#include"area_business_speed_checker.h"
-#include"module_other_alarm.h"
-#include"area_business_car_attendance.h"
-#include"area_business_motionless_persion.h"
-#include"area_business_geofault.h"
-#include"log.h"
-#include"common_tool.h"
+#include "module_mgr.h"
+#include "module_web.h"
+#include "module_call_help.h"
+#include "module_call.h"
+#include "area_business_speed_checker.h"
+#include "module_other_alarm.h"
+#include "area_business_car_attendance.h"
+#include "area_business_motionless_persion.h"
+#include "area_business_geofault.h"
+#include "log.h"
+#include "common_tool.h"
 #include "config_file.h"
 
 /**
@@ -84,5 +82,3 @@ void module_mgr::do_status(STATUS_CARD st, uint32_t card_id, int32_t type)
         }
     }
 }
-
-

+ 229 - 32
module_service/module_traffic_light.cpp

@@ -1,50 +1,100 @@
 #include <algorithm>
 #include "module_traffic_light.h"
 #include "module_traffic_light_manager.h"
+#include "websocket/wsTimerThread.h"
 
 void traffic_light_group::reset()
 {
     m_time_stamp = 0;
     m_ctrl_name = "";
     m_card_id = 0;
+    m_stream_state = move_stream::unknown;
     set_status(false);
     set_priority(priority_init);
 
+    log_info("[traffic_light] reset light group, gid=%d", m_group_id);
     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);
+        auto tl = traffic_light_manager::instance()->find_light((*it)->m_light_id);
         if(tl != nullptr){
             tl->set_state();
+            send_cmd_light(tl);
         }
     }
 }
 
 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;
-   }
+    if(exist(ptl->m_light_id)){
+        return;
+    }
+
+    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;
+    }
+}
+
+bool traffic_light_group::exist(const int& lid)
+{
+    if(m_vt_lights.size() == 0){
+        return false;
+    }
+
+    bool exist = false;
+    for(size_t i = 0; i < m_vt_lights.size(); ++i){
+        if(m_vt_lights[i]->m_light_id == lid){
+            exist = true;
+            break;
+        }
+    }
+
+    return exist;
 }
 
+bool traffic_light_group::is_at_path(point p)
+{
+    return true;
+}
+
+// 设置灯组内所有灯的形状,指定灯ld的形状为lc,其他灯的形状为lcr
 void traffic_light_group::set_light(const int& ld, const int& lc, const int& lcr)
 {
-    log_info("[traffic_light] set light group status, light_id=%d, status=%d, reverse_status=%d",ld, lc, lcr);
+    log_info("[traffic_light] set light group status, total_lights=%d, light_id=%d, status=%d, reverse_status=%d", m_vt_lights.size(), ld, lc, 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;
-            }
+        if((*it)->m_light_id == ld){
+            (*it)->set_state(lc);
+            send_cmd_light(*it);
+        }else{
+            (*it)->set_state(lcr);
+            send_cmd_light(*it);
+        }
+    }
+}
+
+move_stream traffic_light_group::get_stream(const int& cid)
+{
+    move_stream ms = move_stream::unknown;
+
+    pos_data* p = traffic_light_manager::instance()->get_position(cid);
+
+    if(nullptr == p){
+        return ms;
     }
+
+    double dist = p->dist_direct(point(x, y));
+
+    if(dist * updown_dist() > 0){
+        ms = move_stream::up_stream;
+    }else if(dist * updown_dist() < 0){
+        ms = move_stream::down_stream;
+    }
+
+    log_info("[traffic_light] cid=%d, stream=%d, dist_of_card_group=%.3f, updown=%.3f", p->m_card_id, ms, dist, updown_dist());
+
+    return ms;
 }
 
 bool traffic_light_group::is_different(const int& ld, const int& lc, const int& lcr)
@@ -81,23 +131,139 @@ bool traffic_light_group::is_different(const int& ld, const int& lc, const int&
     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;
+    if(nullptr == ptl){
+        return;
+    } 
+
+    YA::light_state ls(m_group_id, ptl->m_light_id, ptl->m_state, ((m_card_id == 0)?"":tool_byte::to_cardid(2,m_card_id)));
+    swsTimerThrd.upt_light_state(ls);
+
+    traffic_light_manager::instance()->send_light_data(ptl->m_light_id, DT_LIGHT, ptl->m_state);
+}
+
+void traffic_light_group::set_path(const std::vector<line_v>& vl)
+{
+    if(vl.empty()){
+        return;
+    }
+
+    const auto& find_line = [](const point& pt, int first, std::vector<line_v>& vl_){
+        for(auto it = vl_.begin();it != vl_.end(); ++it){
+            if(it->v[first].dist(pt) < 1){
+                return it;
+            }
+
+            if(it->v[first?0:1].dist(pt) < 1){
+                point p = it->v[0];
+                it->v[0] = it->v[1];
+                it->v[1] = p;
+                return it;
+            }
+        }
+
+        return vl_.end();
+    };
+
+    std::vector<line_v> vl_(vl.begin()+1, vl.end());
+    std::vector<line_v> target(vl.begin(), vl.begin()+1);
+
+    for(;;){
+        auto it = find_line(target.back().v[1], 0, vl_);
+        if(it == vl_.end()){
+            break;
         }
 
-        traffic_light_manager::instance()->send_light_ctrl(ptl->m_light_id, DT_LIGHT, shape);
+        target.insert(target.end(), it, it+1);
+        vl_.erase(it);
+    }
+
+    for(;;){
+        auto it = find_line(target.front().v[0], 1, vl_);
+        if(it == vl_.end()){
+            break;
+        }
+
+        target.insert(target.begin(), it, it+1);
+        vl_.erase(it);
+    }
+
+    for(int i = 0, c = target.size();i < c;++i){
+        log_info("[traffic_light] path-id=%d, line=%s", i, target[i].to_string().c_str());    
+    }
+
+    std::vector<line_v> vline(target);
+    vline.reserve(vline.size()+2);
+    // 找到距离红绿灯组最近的端点
+    auto min_it = vline.begin();
+    double dist = 10;
+    for(auto it = vline.begin(); it != vline.end(); ++it){
+        double d = it->as_line().dist(*this);
+        if(d < dist){
+            dist = d;
+            min_it = it;
+        }
+    }
+
+    if(min_it == vline.end()){
+        return;
+    }
+
+    if(abs(min_it->v[0].dist(*this)-dist) < 1){
+        set_path(vline, min_it);
+    }else if(abs(min_it->v[1].dist(*this) - dist) < 1){
+        set_path(vl, min_it+1);
+    }else{
+        point p = min_it->projection(*this);
+        vline.insert(min_it+1, line_v(p, min_it->v[1]));
+        min_it->set_point(1, p);
+
+        if(min_it->v[0].z){
+            double slope = min_it->v[0].z;
+            double len_a = min_it->v[0].dist((min_it+1)->v[1]);
+            double len_0 = slope*min_it->length()/len_a;
+            double len_1 = slope-len_0;
+
+            min_it->v[0].z = min_it->v[1].z = len_0;
+            (min_it+1)->v[0].z = (min_it+1)->v[1].z = len_1;
+        }
+
+        set_path(vline, min_it+1);
+    }
+}
+
+void traffic_light_group::set_path(const std::vector<line_v>& vl, std::vector<line_v>::const_iterator itm)
+{
+    auto it = itm;
+    for(int i=0;i<2&&it!=vl.end();++it,++i){
+        m_path[0][i] = *it;
+    }
+
+    it = itm-1;
+    for(int i=0;i<2&&it>=vl.begin();--it,++i){
+        m_path[1][i] = *it;
+        m_path[1][i].swap_point();
+    }
+
+    for(int i=0;i<2;i++){
+        point p = m_path[i][0].line::projection(*this);
+        m_path[i][0].set_point(0, p);
+    }
+
+    for(const auto& p: m_path){
+        log_info("[traffic_light] light group's path: %s", p.to_str().c_str());
     }
 }
 
+/*
+ *
+ * param
+ *      name        user's name
+ *      ld          light id
+ *      lc          ligth color
+ * */
 void traffic_light_group::set_manual_ctrl(const std::string& name, const int& ld, const int& lc)
 {
     get_turn();
@@ -108,9 +274,9 @@ void traffic_light_group::set_manual_ctrl(const std::string& name, const int& ld
     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;
+            return true;
             }else{
-                return false;
+            return false;
             }
             });
     if(ptl != m_vt_lights.end()){
@@ -119,3 +285,34 @@ void traffic_light_group::set_manual_ctrl(const std::string& name, const int& ld
 
     release_turn();
 }
+
+/*
+ * 计算上行与下行灯之间的距离,带方向
+ * */
+double traffic_light_group::updown_dist()
+{
+    point up;
+    point down;
+
+    for(auto it : m_vt_lights){
+        switch(it->m_stream){
+            case 1:
+                //上行
+                up = point(it->x, it->y, it->z);
+                break;
+            case 2:
+                // 下行
+                down = point(it->x, it->y, it->z);
+                break;
+            default:
+                break;
+        }
+    }
+
+    if(up.empty()||down.empty()){
+        log_info("[traffic_light] the %d's light group, up_light empty=%s, down_light empty=%s", m_group_id, (up.empty()?"true":false), (down.empty()?"true":"false"));
+        return 0;
+    }
+
+    return up.dist_direct(down);
+}

+ 79 - 8
module_service/module_traffic_light.h

@@ -5,9 +5,13 @@
 #include <atomic>
 #include <vector>
 #include <list>
+#include <array>
+#include "ant.h"
 #include "module_traffic_light_common.h"
 #include "line.h"
 
+class client;
+
 // 红绿灯
 struct traffic_light: point{
     int m_light_id;             // 红绿灯id
@@ -22,15 +26,21 @@ struct traffic_light: point{
     int m_special;              // 检查非巷道区域,0-正常,1-特殊
     double m_direct_distance;   // 红绿灯到灯组坐标的距离
     line m_line_group;        // 红绿灯与灯组坐标的连线
+    int m_stream;               // 上下行标志,1为上行,2为下行
 
-    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)
-    {}
+    std::shared_ptr<client> m_clt;
+
+    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), m_stream(0)
+    {
+        m_clt = nullptr;
+    }
 
-    traffic_light(double x, double y, double z, int light_id, int group_id, std::string ip, int state, int port, int pli, int pd, int special): point(x, y, z), m_light_id(light_id), m_group_id(group_id), m_ip(ip), m_state(state), m_port(port), m_phy_light_id(pli), m_phy_direction(pd), m_special(special)
+    traffic_light(double x, double y, double z, int light_id, int group_id, std::string ip, int state, int port, int pli, int pd, int special, int stream): point(x, y, z), m_light_id(light_id), m_group_id(group_id), m_ip(ip), m_state(state), m_port(port), m_phy_light_id(pli), m_phy_direction(pd), m_special(special), m_stream(stream)
     {
+        m_clt = nullptr;
     }
 
-    void update(double x, double y, double z, int light_id, int group_id, std::string ip, int state, int port, int pli, int pd, int special)
+    void update(double x, double y, double z, int light_id, int group_id, std::string ip, int state, int port, int pli, int pd, int special, int stream)
     {
         this->x = x;
         this->y = y;
@@ -43,12 +53,25 @@ struct traffic_light: point{
         this->m_phy_light_id = pli;
         this->m_phy_direction = pd;
         this->m_special = special;
+        this->m_stream = stream;
     }
 
-    void set_state(int value = green)
+    void set_state(int value = light_shape::green_all_on)
     {
         m_state = value;
     }
+
+    void set_client(const std::shared_ptr<client>& clt)
+    {
+        if(m_clt != clt){
+            m_clt = clt;
+        }
+    }
+
+    std::shared_ptr<client> get_client()
+    {
+        return m_clt;
+    }
 };
 
 using traffic_light_ptr = std::shared_ptr<traffic_light>;
@@ -61,7 +84,7 @@ struct traffic_light_group: point{
     double m_scope;                 // 控制半径
     uint16_t m_manual_time;         // 人工控制默认时间
     uint16_t m_auto_interval;       // 断网情况下,自动控制间隔
-    uint64_t m_card_id;             // 如果优先级是1,表示小车id;优先级是2,表示打车id
+    uint64_t m_card_id;          // 如果优先级是1,表示小车id;优先级是2,表示打车id
     int m_map_id;                   // 地图ID
     int m_area_id;                  // 区域ID
     time_t m_time_stamp;            // 控制时长,单位秒
@@ -73,10 +96,16 @@ struct traffic_light_group: point{
     std::atomic<bool> m_used;       // 是否使用
     std::atomic_flag m_owner_flag;  // 控制权
     std::vector<traffic_light_ptr> m_vt_lights;   // 组下红绿灯
+    std::array<path, 2> m_path;
+    int m_up_stream_idx;            // 灯组按上行排序的索引值
+    move_stream m_stream_state;
 
     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();   
+        m_up_stream_idx = 0;
+        m_owner_flag.clear();
+        m_stream_state = move_stream::unknown;
     }
 
     traffic_light_group(double x, double y, double z, int group_id, double scope, int interval, int map_id, int area_id): point(x, y, z), m_group_id(group_id), m_scope(scope), m_auto_interval(interval), m_map_id(map_id), m_area_id(area_id)
@@ -84,17 +113,25 @@ struct traffic_light_group: point{
         m_priority = priority_init;
         m_vt_lights.clear();
         m_used = false;
+        m_card_id = 0;
+        m_up_stream_idx = 0;
+        m_owner_flag.clear();
+        m_stream_state = move_stream::unknown;
     }
 
     // 给红绿灯下发指令设置其颜色
     void send_cmd_light(traffic_light_ptr& ptl);
 
+    void set_path(const std::vector<line_v>& vl);
+    void set_path(const std::vector<line_v>& vl, std::vector<line_v>::const_iterator it);
+    
     void set_crossing(const uint64_t& cid, const int& p)
     {
         m_card_id = cid;
         set_priority(p);
     }
 
+    bool is_at_path(point p);
     // 设置避让
     void set_avoidance(const int& ld, const int& lc, const int& lcr)
     {
@@ -110,6 +147,11 @@ struct traffic_light_group: point{
         m_priority.store(p);   
     }
 
+    void set_up_stream_idx(const int& v)
+    {
+        m_up_stream_idx = v;
+    }
+
     // 获取优先权
     int get_priority()
     {
@@ -128,6 +170,18 @@ struct traffic_light_group: point{
         return m_used.load();
     }
 
+    move_stream get_stream_state()
+    {
+        return m_stream_state;
+    }
+
+    void set_stream_state(const move_stream& state)
+    {
+        m_stream_state = state;
+    }
+
+    move_stream get_stream(const int& cid);
+
     // 控制超时检查
     bool is_time_out()
     {
@@ -140,8 +194,7 @@ struct traffic_light_group: point{
 
     void get_turn()
     {
-        while(m_owner_flag.test_and_set(std::memory_order_acquire))
-        {}
+        while(m_owner_flag.test_and_set(std::memory_order_acquire));
     }
 
     void release_turn()
@@ -158,6 +211,9 @@ struct traffic_light_group: point{
     // 增加红绿灯到灯组
     void insert(traffic_light_ptr ptl);
 
+    // 检查灯在组内是否存在
+    bool exist(const int& lid);
+
     //获取两个灯之间的距离
     bool is_different(const int& ld, const int& lc, const int& lcr);
 
@@ -166,6 +222,9 @@ struct traffic_light_group: point{
 
     uint64_t get_green_light_id();
 
+    // 上行灯与下行灯之间的距离,带方向
+    double updown_dist();
+
     void update(double x, double y, double z, int group_id, double scope, int interval, int map_id, int area_id)
     {
         this->x = x;
@@ -188,4 +247,16 @@ struct traffic_light_data{
     }
 };
 
+// 闯红灯
+struct run_red_light{
+    int32_t m_group_id;
+    int m_light_id;
+    int m_vid;
+    int32_t m_area_id;
+    std::string m_occ_time; // 发生时间
+
+    run_red_light(): m_group_id(0), m_light_id(0), m_vid(0), m_area_id(0), m_occ_time(0)
+    {}
+};
+
 #endif

+ 10 - 4
module_service/module_traffic_light_common.h

@@ -55,13 +55,19 @@ enum light_cmd{
     cmd_card_data,          // 卡数据
 };
 
+enum class move_stream{
+    unknown = 0,
+    up_stream,
+    down_stream,
+};
+
 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
+    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)
     {
@@ -73,14 +79,14 @@ struct light_message{
     uint16_t m_cmd;             // 命令
     int m_group_id;             // 信号灯组id
     int m_light_id;             // 信号灯id
-    int m_light_status;         // 信号灯形状
+    int m_light_state;         // 信号灯形状
     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(): m_cmd(0), m_group_id(0), m_light_id(0), m_light_state(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)
+    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_state(ls), m_ctrl_name(name), m_pos(p)
     {}
 };
 

+ 251 - 15
module_service/module_traffic_light_manager.cpp

@@ -1,6 +1,8 @@
 #include "module_traffic_light_manager.h"
 #include "db_api/CDBSingletonDefine.h"
 #include <db_api/CDBResultSet.h>
+#include "websocket/constdef.h"
+#include "websocket/wsTimerThread.h"
 
 traffic_light_manager* traffic_light_manager::instance()
 {
@@ -8,9 +10,12 @@ traffic_light_manager* traffic_light_manager::instance()
     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";
+    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, stream_state from dat_light";
     if(0 == lid){
         sql += ";";
     }else{
@@ -39,19 +44,20 @@ void traffic_light_manager::init_light_from_db(int lid)
         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;
+        int site_id = 0, state = 0, port = 0, phy_light_id = 0, phy_direction = 0, special = 0, stream = 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);
+        res.GetField("stream_state", stream, err);
         traffic_light_ptr pl = find_light(light_id);
         if(nullptr == pl){
-            pl = std::make_shared<traffic_light>(x, y, z, light_id, group_id, ip, state, port, phy_light_id, phy_direction, special);
+            pl = std::make_shared<traffic_light>(x, y, z, light_id, group_id, ip, state, port, phy_light_id, phy_direction, special, stream);
             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);
+            pl->update(x, y , z, light_id, group_id, ip, state, port, phy_light_id, phy_direction, special, stream);
         }
 
         // 将红绿灯分配到对应组中
@@ -65,9 +71,12 @@ void traffic_light_manager::init_light_from_db(int lid)
     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";
+    std::string sql = "select lights_group_id, x, y, z, scope, map_id, area_id, manual_control_time, light_auto_interval, up_stream_idx from dat_lights_group";
     if(gid > 0){
         sql += " where lights_group_id = " + std::to_string(gid);
     }
@@ -96,6 +105,8 @@ void traffic_light_manager::init_light_group_from_db(int gid)
         res.GetField("area_id", area_id, err);
         int ai = 0;
         res.GetField("light_auto_interval", ai, err);
+        int usi = 0;
+        res.GetField("up_stream_idx", usi, err);
         traffic_light_group_ptr pg = find_group(group_id);
         if(nullptr == pg){
             pg = std::make_shared<traffic_light_group>(x, y, z, group_id, scope, ai, map_id, area_id);
@@ -103,15 +114,87 @@ void traffic_light_manager::init_light_group_from_db(int gid)
         }else{
             pg->update(x, y, z, group_id, scope, ai, map_id, area_id);
         }
+        pg->set_up_stream_idx(usi);
+
+        auto ppg = m_map_groups.find(usi);
+        if(ppg == m_map_groups.end()){
+            m_map_groups.insert(std::make_pair(usi, pg));
+        }
     }
     
     logn_info(2, "sql:%s",sql.c_str());
+    output_upstreamidx();
 }
 
-void traffic_light_manager::init(const traffic_send_callback& tcb)
+void traffic_light_manager::init_light_group_path()
+{
+    std::string sql = "select reader_id, tof_flag, b_x, b_y, b_z, e_x, e_y, e_z, spacing_ratio from dat_reader_path_tof_n;";
+
+    std::map<int, std::vector<line_v>> map_path;
+
+    std::string error;
+    YADB::CDBResultSet res;
+    sDBConnPool.Query(sql.c_str(), res, error);
+    int count = res.GetRecordCount(error);
+
+    log_info("init_light_group_path, the record count=%d\n", count);
+    while(res.GetNextRecod(error)){
+        int reader_id = 0;
+        res.GetField("reader_id", reader_id, error);
+
+        int pid=0;
+        res.GetField("tof_flag", pid, error);
+
+        double b_x = 0;
+        res.GetField("b_x", b_x, error);
+
+        double b_y = 0;
+        res.GetField("b_y", b_y, error);
+
+        double b_z = 0;
+        res.GetField("b_z", b_z, error);
+
+        double e_x = 0;
+        res.GetField("e_x", e_x, error);
+
+        double e_y = 0;
+        res.GetField("e_y", e_y, error);
+
+        double e_z = 0;
+        res.GetField("e_z", e_z, error);
+
+        double spacing_ratio = 0;
+        res.GetField("spacing_ratio", spacing_ratio, error);
+
+        log_info("[traffic_light] src-path: site=%d, x0=%.2f, y0=%.2f, x1=%.2f, y1=%.2f", reader_id, b_x, b_y, e_x, e_y);
+
+        point p1(b_x, -b_y, spacing_ratio);
+        point p2(e_x, -e_y, spacing_ratio);
+
+        map_path.insert(std::make_pair(reader_id, std::vector<line_v>()));
+        map_path.find(reader_id)->second.push_back(line_v(p1, p2));
+    }
+
+    for(auto itg : m_unmap_groups){
+        for(auto itp : map_path){
+            bool tag = false;
+            for(size_t i = 0;i < itp.second.size();i++){
+                if(itp.second[i].contain(point(itg.second->x, itg.second->y),1)){
+                    tag = true;
+                }
+            } 
+            if(tag){
+                itg.second->set_path(itp.second);
+            }
+        }
+    }
+}
+
+void traffic_light_manager::init(const int& lgc)
 {
     // 1.先获得红绿灯组数据
     init_light_group_from_db();
+    init_light_group_path();
     // 2.再获得红绿灯数据
     init_light_from_db();
 
@@ -124,7 +207,11 @@ void traffic_light_manager::init(const traffic_send_callback& tcb)
         }
     }
 
-    set_send_callback(tcb);
+    for(auto it : m_unmap_groups){
+        log_info("[traffic_light] gid=%d, size=%d", it.first, it.second->m_vt_lights.size());
+    }
+
+    m_light_group_ctrl_num = lgc;
 }
 
 void traffic_light_manager::start()
@@ -155,7 +242,6 @@ void traffic_light_manager::start()
     }
 
     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)));
 }
 
@@ -179,7 +265,6 @@ void traffic_light_manager::run()
     while(!m_stop){
         std::list<light_message> tmp_data;
         tmp_data.clear();
-        //log_info("[traffic_light] working... m_stop=%d", m_stop);
         {
             std::unique_lock<std::mutex> lock(m_mutex);
             while(m_list_data.empty()){
@@ -200,8 +285,8 @@ void traffic_light_manager::run()
                     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);
+                    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_state);
+                    handle_manual(it->m_group_id,it->m_light_id, it->m_ctrl_name, it->m_light_state);
                     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);
@@ -212,12 +297,12 @@ void traffic_light_manager::run()
                     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){
@@ -228,18 +313,106 @@ void traffic_light_manager::handle_reload(const int& gid, const int& lid)
     }
 }
 
+// 红绿灯基础数据更新
 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;
 }
 
+std::vector<traffic_light_group_ptr> traffic_light_manager::find_stream_groups(traffic_light_group_ptr ptr_group, const move_stream& stream)
+{
+    std::vector<traffic_light_group_ptr> vt_group;
+
+       switch(stream){
+        case move_stream::up_stream:
+            {
+                auto itg = m_map_groups.end();
+                for(auto it = m_map_groups.begin(); it !=  m_map_groups.end(); ++it){
+                    if(it->second->m_group_id == ptr_group->m_group_id){
+                        itg = it;
+                    }
+                }
+    
+                auto ite = itg;
+                std::advance(ite, m_light_group_ctrl_num);
+
+                std::for_each(itg, ite, [&vt_group](std::pair<int, traffic_light_group_ptr> p){
+                    if(p.second != nullptr){
+                        vt_group.push_back(p.second);
+                    }
+                    });
+            }
+            break;
+        case move_stream::down_stream:
+             {
+                auto itg = m_map_groups.rend();
+                for(auto it = m_map_groups.rbegin(); it != m_map_groups.rend(); ++it){
+                    if(it->second->m_group_id == ptr_group->m_group_id){
+                        itg = it;
+                    }
+                }
+    
+                auto ite = itg;
+                std::advance(ite, m_light_group_ctrl_num);
+
+                std::for_each(itg, ite, [&vt_group](std::pair<int, traffic_light_group_ptr> p){
+                    if(p.second != nullptr){
+                        vt_group.push_back(p.second);
+                    }
+                    });
+            }
+
+            break;
+        default:
+            break;
+    }
+
+    return std::move(vt_group);
+}
+
+// 处理web端发起的手工控制
+void traffic_light_manager::manual_ctrl(sio::message::ptr const& data)
+{
+    std::map<std::string, sio::message::ptr> mp = data->get_map()[JSON_ROOT_KEY_DATA]->get_map();
+    log_info("[traffic_light] map's size=%d", mp.size());
+
+    light_message lm;
+    lm.m_group_id       = mp["group_id"]->get_int();
+    lm.m_light_id       = mp["light_id"]->get_int();
+    lm.m_light_state    = mp["light_color"]->get_int();
+    lm.m_ctrl_name      = mp["ctrl_name"]->get_string();
+    int ctrl = mp["control"]->get_int();
+        
+    // 如果手工控制,否则取消手工控制
+    (ctrl == 1)?set_manual(lm):cancel_manual(lm);
+
+    /*for(auto it = vtc.begin(); it != vtc.end(); ++it)
+    {
+        light_message lm;
+        lm.m_group_id = (*it)->get_map()["group_id"]->get_int();
+        lm.m_light_id = (*it)["light_id"]->get_int();
+        lm.m_light_state = (*it)["light_color"]->get_int();
+        lm.m_ctrl_name = (*it)["ctrl_name"]->get_string();
+        int ctrl = (*it)["control"]->get_int();
+        
+        // 如果手工控制,否则取消手工控制
+        (ctrl == 1)?set_manual(lm):cancel_manual(lm);
+    }
+    std::string rd = data->get_map()[JSON_ROOT_KEY_DATA]->get_string();
+
+    log_info("[traffic light] recv web msg: %s", rd.c_str());
+    */
+
+}
+
 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);
@@ -248,6 +421,7 @@ void traffic_light_manager::handle_manual(const int& gid, const int& ld, const s
     }
 }
 
+// 红绿灯处理模块入口
 void traffic_light_manager::handle_position(pos_data& p)
 {
     if(p.m_type == 3 || p.m_type == 1){
@@ -256,13 +430,11 @@ void traffic_light_manager::handle_position(pos_data& p)
             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);
+            m_crossing_rule->handle_rule(p);
         }
 
         if(!p.m_bigger && nullptr != m_avoidance_rule){
@@ -270,3 +442,67 @@ void traffic_light_manager::handle_position(pos_data& p)
         }
     }
 }
+
+// 手工控制红绿灯
+void traffic_light_manager::set_manual(light_message& msg)
+{
+    auto g = m_unmap_groups.find(msg.m_group_id);
+    if(g != m_unmap_groups.end()){
+        int state = ((msg.m_light_state == 8)?9:8);
+        
+        for(auto it : g->second->m_vt_lights){
+            if(it->m_light_id == msg.m_light_id){
+                send_light_data(msg.m_light_id, 0, msg.m_light_state);
+            }else{
+                send_light_data(msg.m_light_id, 0, state); 
+            }
+       }
+
+        log_info("[traffic_light] manual ctrl's group info, group_id=%d, light %d's shape is %d, other's shape is %d", msg.m_group_id, msg.m_light_id, msg.m_light_state, state);
+    }
+}
+
+// 取消手工控制
+void traffic_light_manager::cancel_manual(light_message& msg)
+{
+    auto g = m_unmap_groups.find(msg.m_group_id);
+    if(g != m_unmap_groups.end()){
+        g->second->get_turn();
+        g->second->reset();
+        g->second->release_turn();
+
+        for(auto it_light : g->second->m_vt_lights){
+            send_light_data(it_light->m_light_id, 0, it_light->m_state);
+        }
+
+        log_info("[traffic_light] %s cancel manual control %d's light group of %d light", msg.m_ctrl_name.c_str(), msg.m_group_id, msg.m_light_id);
+    }
+}
+
+int traffic_light_manager::remove_light(const int& id)
+{
+    std::lock_guard<std::mutex> lg(m_mutex);
+
+    auto it = m_unmap_lights.find(id);
+    if(it != m_unmap_lights.end()){
+        m_unmap_lights.erase(it);
+    } 
+ 
+    log_info("[meta_data_change] remove light, lid=%d", id);
+
+    return 0;
+}
+
+int traffic_light_manager::remove_light_group(const int& id)
+{
+    std::lock_guard<std::mutex> lg(m_mutex);
+
+    auto it = m_unmap_groups.find(id);
+    if(it != m_unmap_groups.end()){
+        m_unmap_groups.erase(it);
+    }
+
+    log_info("[meta_data_change] remove light group, gid=%d", id);
+
+    return 0;
+}

+ 150 - 24
module_service/module_traffic_light_manager.h

@@ -7,22 +7,10 @@
 #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);
-    }
-};
+#include "websocket/sio/sio_client.h"
+#include "tool_byte.h"
+#include "crc.h"
+#include "protocol.h"
 
 // 红绿灯管理
 struct traffic_light_manager{
@@ -31,9 +19,10 @@ struct traffic_light_manager{
     // 从数据库加载数据
     void init_light_from_db(int lid = 0);
     void init_light_group_from_db(int gid = 0);
+    void init_light_group_path();
 
     // 初始化回调信息
-    void init(const traffic_send_callback& cb);
+    void init(const int& lgc);
 
     // 开启
     void start();
@@ -50,11 +39,19 @@ struct traffic_light_manager{
     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)
     {
@@ -79,6 +76,8 @@ struct traffic_light_manager{
         return nullptr;
     }
 
+    std::vector<traffic_light_group_ptr> find_stream_groups(traffic_light_group_ptr, const move_stream& stream);
+
     // 更新红绿灯数据
     void update_light(const int& key, traffic_light_ptr ptl);
 
@@ -108,35 +107,162 @@ struct traffic_light_manager{
         m_geo_list.update(x, y, cid);
     }
 
-    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);
+    void vtlg_insert(const uint64_t& cid, traffic_light_group_ptr& group)
+    {
+        std::lock_guard<std::mutex> 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<traffic_light_group_ptr>()));
+            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<std::mutex> 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& type, const int& shape){
+        std::vector<char> msg;
+
+        uint16_t cmd = THIRD_PARTY_CHAR_LIGHT_SETUP_STATE;
+        tool_byte::memcpy_int<uint16_t>(msg, cmd);
+
+        tool_byte::memcpy_int<uint32_t>(msg, light_id);
+
+        msg.push_back(0x05);
+
+        msg.push_back(static_cast<char>(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_byte::memcpy_int<int16_t>(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<char> 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;
     }
 
-    void set_send_callback(const traffic_send_callback& cb)
+    void output_message(std::vector<char>&& msg, int light_id)
     {
-        m_send_callback = std::move(cb);   
+        std::string s("红绿灯控制的数据帧,灯号=");
+        s.append(std::to_string(light_id));
+        s.append(":");
+
+        char a[4] = {0};
+        for(std::vector<char>::size_type i = 0;i < msg.size(); ++i){
+            sprintf(a, "%02X ", static_cast<unsigned char>(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);
 
     private:
     bool m_stop;
+    unsigned int m_light_group_ctrl_num{0};     // 控制红绿灯组数
     std::list<light_message> m_list_data;
     std::mutex m_mutex;
+    std::mutex m_vtlg_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<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;
+    map_group m_map_groups;
     std::map<uint64_t, pos_data> m_map_card;
+
+    std::map<uint64_t, std::list<traffic_light_group_ptr>> m_vehicle_traffic_groups;
 };
 
 #endif

+ 296 - 103
module_service/module_traffic_light_rule.cpp

@@ -2,6 +2,7 @@
 #include "module_traffic_light_rule.h"
 #include "module_traffic_light_manager.h"
 
+// 车辆与指定灯组g距离比较,lhs近则返回true,否则返回false
 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);
@@ -17,6 +18,17 @@ bool rule::sort_vehicle(const uint64_t lhs, const uint64_t rhs, const traffic_li
     return d1 < d2;
 }
 
+// 根据车辆等级进行排序
+bool rule::sort_vehicle_by_level(const uint64_t lhs, const uint64_t rhs, const traffic_light_group_ptr& g)
+{
+    //pos_data* lp = traffic_light_manager::instance()->get_position(lhs);
+    //pos_data* rp = traffic_light_manager::instance()->get_position(rhs);
+
+    //return lp->
+    return true;
+}
+
+// 从灯组g中找到最近的灯
 traffic_light_ptr rule::find_nearby_light(const point& p, traffic_light_group_ptr g)
 {
     traffic_light_ptr pl = nullptr;
@@ -35,6 +47,7 @@ traffic_light_ptr rule::find_nearby_light(const point& p, traffic_light_group_pt
     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);
@@ -44,7 +57,7 @@ void crossing_rule::change_state(const uint64_t vid, traffic_light_group_ptr 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);
+            g->set_light(pl->m_light_id, light_shape::green_all_on, light_shape::red_all_on);
         }
     }else{
         log_warn("[traffic_light] it can't get vehicle position. vid=%lld, lg's id=%d", vid, g->m_group_id);
@@ -63,7 +76,8 @@ bool crossing_rule::get_vehicle_state(const uint64_t& vid)
 
     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);
@@ -99,6 +113,7 @@ bool crossing_rule::find_light(const uint64_t& vid, traffic_light_group_ptr g, b
     return false;
 }
 
+// 手工控制
 bool crossing_rule::handle_manual_ctrl(traffic_light_group_ptr g)
 {
     if(g->is_time_out()){
@@ -109,135 +124,327 @@ bool crossing_rule::handle_manual_ctrl(traffic_light_group_ptr g)
     return false;
 }
 
-bool crossing_rule::handle_crossing(traffic_light_group_ptr g)
+bool crossing_rule::handle_crossing(traffic_light_group_ptr group)
 {
-    if(g->m_scope <= 0){
+    if(group->m_scope <= 0){
         return false;
     }
+
     // 查找一定范围的车辆
-    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);
-    log_info("[traffic_light] handle crossing rule.gid=%d, group_scope=%.2f, vehicle's num=%d", g->m_group_id, g->m_scope, vtl.size());
+    std::vector<uint64_t> vtl = traffic_light_manager::instance()->find_nearby_vehicle(point(static_cast<int>(group->x), static_cast<int>(group->y)), group->m_scope, group->m_group_id);
+    log_info("[traffic_light] handle crossing rule.gid=%d, group_scope=%.2f, vehicle's num=%d", group->m_group_id, group->m_scope, vtl.size());
     if(vtl.empty()){
-        if(g->m_card_id > 0 && g->m_priority == priority_crossing)
+        if(group->m_card_id > 0 && group->m_priority == priority_crossing)
         {
             // 释放红绿灯组
-            g->reset();
+            group->reset();
             return true;
         }
 
         return false;
     }
 
-    // 是否已经有车记录
-    if(g->m_card_id > 0)
+    // 是否已经有原控制记录
+    if(group->m_card_id > 0)
     {
-        auto it = std::find(vtl.begin(), vtl.end(), g->m_card_id);
+        // check stream
+        if(group->get_stream_state() != group->get_stream(group->m_card_id)){
+            log_info("[traffic_light] %d's vehicle is passed crossing that is gid=%d, old_stream=%d, cur_stream=%d",group->m_card_id, group->m_group_id, group->get_stream_state(), group->get_stream(group->m_card_id));
+            traffic_light_manager::instance()->vtlg_erase(group->m_card_id, group);
+            return false;
+        }
+        auto it = std::find(vtl.begin(), vtl.end(), group->m_card_id);
         if(it != vtl.end()){
-            log_info("[traffic_light] handle crossing rule, there has vehicle that control the light group, card_id=%d", g->m_card_id);
+            log_info("[traffic_light] handle crossing rule, there has vehicle that control the light group, card_id=%d", group->m_card_id);
             return false;
         }
     }
 
     std::sort(vtl.begin(), vtl.end(), [&](const uint64_t& lhs, const uint64_t& rhs){
-            return sort_vehicle(lhs, rhs, g);
+            return sort_vehicle(lhs, rhs, group);
             });
 
-    // 设置优先级以及卡id
-    g->set_crossing(vtl[0], priority_crossing);
-    // 修改红绿灯组状态
-    change_state(vtl[0], g);
+    move_stream ms = group->get_stream(vtl[0]);
+
+    pos_data* p = traffic_light_manager::instance()->get_position(vtl[0]);
+    if((group->m_card_id == 0) && (p->m_speed * p->dist_direct(*group) < 0)){
+        log_info("[traffic_light] gid=%d is not same to vehicle=%d direction", group->m_group_id, p->m_card_id);
+        return false;
+    }
+
+    // 对需要控制的N个灯组进行控制
+    std::vector<traffic_light_group_ptr> vt_groups = traffic_light_manager::instance()->find_stream_groups(group, ms);
+    if(vt_groups.empty()){
+        log_info("[traffic_light] 找不到灯组");
+        return false;
+    }
+
+    std::string s = "[";
+    for_each(vt_groups.begin(), vt_groups.end(), [&s](traffic_light_group_ptr g){ s.append(std::to_string(g->m_group_id));});
+    s.append("]");
+    log_info("[traffic_light] the %d's vehicle control light group of %s", vtl[0], s.c_str());
+
+    for(auto it : vt_groups){
+        traffic_light_manager::instance()->vtlg_insert(vtl[0], it);
+        it->set_crossing(vtl[0], priority_crossing);
+        it->set_stream_state(ms);
+        change_state(vtl[0], it);
+    }
 
     return true;
 }
 
+//避让规则处理
+//1)车辆等级规则
+//2)上下行规则
 bool crossing_rule::handle_avoidance(traffic_light_group_ptr g)
 {
-    // 查看是否是大车,true表示特殊红绿灯,需要检测大车避让规则
-    bool flag = false;
+    if(g->m_card_id == 0){
+        return 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);
-        log_info("[traffic_light] handle avoidance, gid=%d, x=%.2f, y=%.2f, scope=%.2f, vehicle's size=%d", g->m_group_id, g->x, g->y, g->m_scope, vt.size());
-        // 筛选大车
-        if(vt.empty()){
-            flag = true;
-            break;
+    bool ret = false; 
+    ret = avoidance_by_level(g);
+    if(ret){
+        return ret;
+    }else{
+        return avoidance_by_updown(g);
+    }
+}
+
+// 根据车辆等级处理避让
+bool crossing_rule::avoidance_by_level(traffic_light_group_ptr& group)
+{
+    // 根据车辆等级处理避让规则
+    // 查找红绿灯组附近车辆
+    auto vt = traffic_light_manager::instance()->find_nearby_vehicle(point(static_cast<int>(group->x), static_cast<int>(group->y)), group->m_scope, group->m_group_id);
+    
+    // 红绿灯组附近无车辆
+    if(vt.empty()){
+        if(priority_avoidance == group->get_priority() && group->m_card_id > 0){
+            bool exist = traffic_light_manager::instance()->vtlg_exist(group->m_card_id, group->m_group_id);
+            if(!exist){
+                // 重置灯组控制权
+                group->reset();
+            }
         }
-        vt.erase(std::remove_if(vt.begin(), vt.end(), [&](const uint64_t& vid){
-            return get_vehicle_state(vid);
-                    }),
-                vt.end());
+        return false;
+    }
+    
+    if(vt.size() == 1 && vt[0] == group->m_card_id){
+        log_info("[traffic_light] group is controlled, gid=%d, cid=%d", group->m_group_id, group->m_card_id);
+        return false;
+    }
 
-        if(vt.empty()){
-            flag = true;
-            break;
+    log_info("[traffic_light] handle avoidance_by_level, gid=%d, x=%.2f, y=%.2f, scope=%.2f, ctrl_cid=%d, ivehicle's size=%d", group->m_group_id, group->x, group->y, group->m_scope, group->m_card_id, vt.size());
+
+    if(group->m_card_id > 0 && get_vehicle_state(group->m_card_id)){
+        //检查是否释放控制权
+        if(group->get_stream_state() != move_stream::unknown)
+        {
+            // 如果车辆运行方向与灯组上下行方向不一致,则重置
+            if(group->get_stream_state() != group->get_stream(group->m_card_id))
+            {
+                traffic_light_manager::instance()->vtlg_erase(group->m_card_id, group);
+            }
         }
+        return false;
+    }
 
-        // 查看离最近的点是否为特殊点,判断位置是否在直线上,判断方向
+    bool exist_bigger_car = false;
+    if(group->m_card_id == 0){
+        for(size_t i = 0;i < vt.size(); ++i){
+            if(get_vehicle_state(vt[i])){
+                exist_bigger_car = true;
+                break;
+            }
+        }
+    }
+    if(exist_bigger_car || (group->m_card_id > 0 && !get_vehicle_state(group->m_card_id))){
+        // only keep vehicle's state that is bigger flag
         vt.erase(std::remove_if(vt.begin(), vt.end(), [&](const uint64_t& vid){
-            return find_light(vid, g);
+                    if(get_vehicle_state(vid)){
+                    return false;
+                    }else{
+                    return true;
+                    }
                     }),
                 vt.end());
+
         if(vt.empty()){
-            flag = true;
-            break;
+            return false;
         }
-
-        // 特殊规则保留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;
+    }
+    // 删除不在红绿灯组所在路径上的车辆
+    vt.erase(std::remove_if(vt.begin(), vt.end(), [&](const uint64_t& vid){
+                pos_data* p = traffic_light_manager::instance()->get_position(vid);
+                if(group->is_at_path(*p)){
+                return false;
+                }else{
+                return true;
                 }
+                }),
+            vt.end());
+    if(vt.empty()){
+        return false;
+    }
+
+    // 排序,找到离之最近的大车
+    std::sort(vt.begin(), vt.end(), [&](const uint64_t& vid, const uint64_t& cid){
+            return sort_vehicle(vid, cid, group);
+            });
+
+    move_stream ms = group->get_stream(vt[0]);
+    if(ms == move_stream::unknown){
+        return false;
+    }
+
+    // 对需要控制的N个灯组进行控制
+    std::vector<traffic_light_group_ptr> vt_groups = traffic_light_manager::instance()->find_stream_groups(group, ms);
+    if(vt_groups.empty()){
+        log_info("[traffic_light] 找不到灯组");
+        return false;
+    }
+
+    std::string s = "[";
+    for_each(vt_groups.begin(), vt_groups.end(), [&s](traffic_light_group_ptr g){ s.append(std::to_string(g->m_group_id));});
+    s.append("]");
+    log_info("[traffic_light] the %d's vehicle control light group of %s", vt[0], s.c_str());
+
+    for(auto& it : vt_groups){
+        traffic_light_manager::instance()->vtlg_insert(vt[0], it);
+        it->set_crossing(vt[0], priority_avoidance);
+        it->set_stream_state(ms);
+        change_state(vt[0], it);
+    }
+
+    return true;
+}
+
+// 根据车辆上下行处理避让
+bool crossing_rule::avoidance_by_updown(traffic_light_group_ptr& group)
+{
+    // 1.检查控制灯组的车辆是否为上行车,如果是,则直接返回,表示上行车辆已控制灯组
+    // 2.如果是下行车,则查看新车辆是否为上行,如果是,则控制
+    if(group->m_card_id){
+        if(group->get_stream(group->m_card_id) == move_stream::up_stream){
+            return false;
+        }
+        //检查是否释放控制权
+        if(group->get_stream_state() != group->get_stream(group->m_card_id))
+        {
+            traffic_light_manager::instance()->vtlg_erase(group->m_card_id, group);
+            return false;
+        }
+    }
+
+    auto vt = traffic_light_manager::instance()->find_nearby_vehicle(point(static_cast<int>(group->x), static_cast<int>(group->y)), group->m_scope, group->m_group_id);
+    if(vt.empty()){
+        if(priority_avoidance == group->get_priority() && group->m_card_id > 0){
+            bool exist = traffic_light_manager::instance()->vtlg_exist(group->m_card_id, group->m_group_id);
+            if(!exist){
+                // 重置灯组控制权
+                group->reset();
             }
         }
+        return false;
+    }
 
-        // 排序,找到离之最近的大车
-        std::sort(vt.begin(), vt.end(), [&](const uint64_t& vid, const uint64_t& cid){
-                return sort_vehicle(vid, cid, g);
-                });
+    log_info("[traffic_light] handle avoidance_by_updown, gid=%d, x=%.2f, y=%.2f, scope=%.2f, vehicle's size=%d", group->m_group_id, group->x, group->y, group->m_scope, vt.size());
 
-        change_state(vt[0], g);
-        g->set_crossing(vt[0], priority_avoidance);
+    bool exist_up_stream = false;
+    if(group->m_card_id == 0){
+        for(size_t i = 0; i < vt.size(); ++i){
+            if(group->get_stream(vt[i]) == move_stream::up_stream){
+                exist_up_stream = true;
+                break;
+            }
+        }
+    }
 
-        return true;
-    }while(false);
+    if(exist_up_stream || group->m_card_id > 0){
+        // erase vehicles that's state of down_stream
+        vt.erase(std::remove_if(vt.begin(), vt.end(), [&](uint64_t cid){
+                    if(group->get_stream(cid) == move_stream::down_stream){
+                        return true;
+                    }else{
+                        return false;
+                    }
+                    }));
 
-    if(flag){
-        // 找不到之前的车辆,则初始化
-        if(priority_avoidance == g->get_priority() && g->m_card_id > 0){
-            g->reset();
-        }else{
-            flag = false;
+        if(vt.empty()){
+            return false;
         }
     }
 
-    return flag;
+    log_info("[traffic_light] the number of vehicle that's state of up_stream = %d", vt.size());
+    for(size_t i = 0;i < group->m_path.size();i++){
+        log_info("%s", group->m_path[i].to_str().c_str());
+    }
+
+    // 根据车辆远近进行排序
+    std::sort(vt.begin(), vt.end(), [&](const uint64_t& vid, const uint64_t& cid){
+            return sort_vehicle(vid, cid, group);
+            });
+
+    // 每辆车上下行处理
+    // 根据点与灯组的带方向距离和灯组中上行灯与下行灯之间的带方向距离信息,来判断车辆行径方向是上行or下行
+    // 判断位置与红绿灯组的方向与速度得方向是否一致
+    // 如果车辆静止不动的话,不考虑
+    
+    move_stream ms = group->get_stream(vt[0]);
+    // 对需要控制的N个灯组进行控制
+    std::vector<traffic_light_group_ptr> vt_groups = traffic_light_manager::instance()->find_stream_groups(group, ms);
+    if(vt_groups.empty()){
+        log_info("[traffic_light] 找不到灯组");
+        return false;
+    }
+
+    std::string s = "[";
+    for_each(vt_groups.begin(), vt_groups.end(), [&s](traffic_light_group_ptr g){ s.append(std::to_string(g->m_group_id));});
+    s.append("]");
+    log_info("[traffic_light] the %d's vehicle control light group of %s", vt[0], s.c_str());
+
+    for(auto& it : vt_groups){ 
+        if(it->m_card_id == 0
+           || (ms == move_stream::up_stream && it->get_stream_state() == move_stream::down_stream)
+          )
+        {
+            // 以下两种情况,改变灯组的控制权
+            // 1.车辆为上行;
+            // 2.灯组无控制权
+            traffic_light_manager::instance()->vtlg_insert(vt[0], it);
+            it->get_turn();
+            it->set_crossing(vt[0], priority_avoidance);
+            it->set_stream_state(ms);
+            change_state(vt[0], it);
+
+            log_info("[traffic_light] vehicle get group control, cid = %d, group_id=%d", vt[0], it->m_group_id);
+        }    
+    }
+
+    return true;
 }
 
-vt_traffic_group crossing_rule::handle_rule(pos_data& p)
+void crossing_rule::handle_rule(pos_data& p)
 {
-    vt_traffic_group llist;
-    log_info("[traffic_light] crossing_rule::handle_rule, group's size=%d", m_vt_group.size());
+    //log_info("[traffic_light] crossing_rule::handle_rule, group's size=%d", m_vt_group.size());
     for(auto& it : m_vt_group){
         // 获取控制权
         it->get_turn();
         int priority = it->get_priority();
-        log_info("[traffic_light] crossing_rule::handle_rule, gid=%d, priority=%d, special=%d", it->m_group_id, priority, it->m_special);
+        //log_info("[traffic_light] crossing_rule::handle_rule, gid=%d, priority=%d, special=%d", it->m_group_id, priority, it->m_special);
         bool flag = false;
         while(true){
             if(priority_manual_ctrl == priority){
-                 flag = handle_manual_ctrl(it);
-                 log_info("[traffic_light] crossing_rule::handle_rule, after call handle_manual_ctrl, flag=%d", flag);
-                 if(flag){
+                flag = handle_manual_ctrl(it);
+                log_info("[traffic_light] crossing_rule::handle_rule, after call handle_manual_ctrl, flag=%d", flag);
+                if(flag){
                     break;
-                 }
+                }
             }
 
-            if(priority <= priority_avoidance && it->m_special){
+            if(priority <= priority_avoidance){
                 flag = handle_avoidance(it);
                 log_info("[traffic_light] crossing_rule::handle_rule, after call handle_avoidance, flag=%d", flag);
                 if(flag){
@@ -255,16 +462,17 @@ vt_traffic_group crossing_rule::handle_rule(pos_data& p)
 
             break;
         };
- 
+
         it->release_turn();
-        if(flag){
-            llist.push_back(it);
-        }
     }
+}
 
-    return std::move(llist);
+std::shared_ptr<run_red_light> crossing_rule::check_run_red_light(pos_data& p)
+{
+    return nullptr;
 }
 
+// 查找灯组
 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);
@@ -349,6 +557,7 @@ bool avoidance_rule::find_vehicle_in_group(vt_traffic_group& vg, std::vector<pos
         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]);
@@ -384,7 +593,7 @@ bool avoidance_rule::get_vehicle(const pos_data& p, vt_traffic_group& vg)
     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;
+                return true;
                 }
 
                 std::vector<pos_data> vv;
@@ -477,12 +686,12 @@ bool avoidance_rule::is_different(traffic_light_group_ptr g, const point& p, con
     return b;
 }
 
-vt_traffic_group avoidance_rule::handle_rule(pos_data& p)
+void 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);
+        return;
     }
 
     log_info("[traffic_light] avoidance_rule::handle_rule, group's size=%d, area_id=%d", m_map_area_group.size(), p.m_area_id);
@@ -628,20 +837,11 @@ vt_traffic_group avoidance_rule::handle_rule(pos_data& p)
                                     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);
+                                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
@@ -652,17 +852,6 @@ vt_traffic_group avoidance_rule::handle_rule(pos_data& p)
                                 }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);
@@ -676,6 +865,10 @@ vt_traffic_group avoidance_rule::handle_rule(pos_data& p)
     }else{
         log_info("[traffic_light] the %d area has no light group", p.m_area_id);
     }
+}
 
-    return std::move(llist);
+std::shared_ptr<run_red_light> avoidance_rule::check_run_red_light(pos_data& p)
+{
+    return nullptr;
 }
+

+ 21 - 13
module_service/module_traffic_light_rule.h

@@ -13,16 +13,19 @@
 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 handle_rule(pos_data& p) = 0;
     virtual void put(traffic_light_group_ptr tlp) = 0;
     virtual void put(vt_traffic_group&& vc) = 0;
-
+    // 闯红灯检查
+    virtual std::shared_ptr<run_red_light> check_run_red_light(pos_data& p) = 0;
     // 车子按距离红绿灯组坐标点排序
     bool sort_vehicle(const uint64_t lhs, const uint64_t rhs, const traffic_light_group_ptr& g);
+    bool sort_vehicle_by_level(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);
@@ -33,7 +36,8 @@ struct crossing_rule: rule{
     crossing_rule(){}
     ~crossing_rule(){}
 
-    vt_traffic_group handle_rule(pos_data& p);
+    // 
+    void handle_rule(pos_data& p);
     // 谁先到达炉口红绿灯指定的距离,变绿灯,其他变红灯
     bool get_vehicle_state(const uint64_t& card_id);
     // 自动控制
@@ -42,11 +46,15 @@ struct crossing_rule: rule{
     bool find_light(const uint64_t& cid, traffic_light_group_ptr g, bool a = false);
     // 避让处理
     bool handle_avoidance(traffic_light_group_ptr g);
+    bool avoidance_by_level(traffic_light_group_ptr& group);
+    bool avoidance_by_updown(traffic_light_group_ptr& group);
     // 路口处理
-    bool handle_crossing(traffic_light_group_ptr g);
+    bool handle_crossing(traffic_light_group_ptr group);
     // 修改红绿灯组状态
     void change_state(const uint64_t cid, traffic_light_group_ptr g);
-
+    // 闯红灯
+    std::shared_ptr<run_red_light> check_run_red_light(pos_data& p);
+    
     void put(traffic_light_group_ptr g)
     {
         m_vt_group.push_back(g);
@@ -63,7 +71,8 @@ struct crossing_rule: rule{
     }
 
     private:
-    vt_traffic_group m_vt_group;
+        // 灯组
+        vt_traffic_group m_vt_group;
 };
 
 // 避让规则
@@ -72,12 +81,12 @@ struct avoidance_rule: rule{
         avoidance_rule(){}
         ~avoidance_rule(){}
 
-        vt_traffic_group handle_rule(pos_data& p);
+        void 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);
@@ -89,7 +98,9 @@ struct avoidance_rule: rule{
         // 后续小车避让大车规则,只需要找到前方的两个红绿灯,找到两个对比一下之前的记录,如果灯组改变了,则修改,如果没变,则判断是否有小车,进行改变
         // 如果只找到一个红绿灯,查看是否含有记录,如果有,则不做任何处理
         bool find_vehicle_in_group(vt_traffic_group& vg, std::vector<pos_data>& vv);
-
+        // 闯红灯
+        std::shared_ptr<run_red_light> check_run_red_light(pos_data& p);
+        // 将灯组放入指定区域内
         void put(traffic_light_group_ptr ptlg)
         {
             m_map_area_group[ptlg->m_area_id].push_back(ptlg);
@@ -111,11 +122,8 @@ struct avoidance_rule: rule{
         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>;
+using map_group = std::map<int, traffic_light_group_ptr>;
 
 #endif

+ 5 - 2
module_service/module_web.cpp

@@ -5,7 +5,8 @@
 #include "module_meta_data_changed.h"
 #include "common_tool.h"
 #include "event.h"
-#include"log.h"
+#include "log.h"
+#include "module_traffic_light_manager.h"
 
 void module_web::accept( int ID, std::string const& name,
                          sio::message::ptr const& data, bool need_ack, sio::message::list &ack_resp )
@@ -35,6 +36,9 @@ void module_web::accept( int ID, std::string const& name,
     }else if(JSON_CMD_REQ_ALL_PERSON_ON_CAR == cmd)
     {
         //人上车数据
+    }else if(JSON_CMD_VALUE_LIGHTS_CTRL_REQUEST == cmd){
+        // 红绿灯手动控制
+        traffic_light_manager::instance()->manual_ctrl(data);   
     }
     else
     {
@@ -106,7 +110,6 @@ void module_web::run()
 
         std::string tmp = event_list::evs_to_json(arr);
         swsClientMgr.send(JSON_CMD_VALUE_PUSH, tmp);
-//        log_info("发送给web的告警json:%s", tmp.c_str());
     }
 
     std::string help = module_call_help::get_json_help();

+ 5 - 7
module_service/module_web.h

@@ -3,14 +3,12 @@
 
 #include <memory>
 #include <string>
-#include<vector>
+#include <vector>
 #include "rapidjson/prettywriter.h"
 #include "rapidjson/document.h"
-
-#include"config_file.h"
-
-#include"module_singleton_base.h"
-#include"module_i_thread.h"
+#include "config_file.h"
+#include "module_singleton_base.h"
+#include "module_i_thread.h"
 #include "websocket/wsClientMgr.h"
 
 struct ya_event;
@@ -48,9 +46,9 @@ public:
         MsgFuncList.insert( std::make_pair( JSON_CMD_VALUE_DEAL_HELP, &module_web::accept ) );
         MsgFuncList.insert( std::make_pair( JSON_CMD_VALUE_CALL_CARD_REQUEST, &module_web::accept ) );
         MsgFuncList.insert( std::make_pair( JSON_CMD_VALUE_CALL_CARD_CANCEL_REQUEST, &module_web::accept ) );
-
         MsgFuncList.insert( std::make_pair( JSON_CMD_VALUE_CLEAR_CARD, &module_web::accept ) );//手动升井
         MsgFuncList.insert( std::make_pair( JSON_CMD_REQ_ALL_PERSON_ON_CAR,&module_web::accept)); // 接收web端请求的在车上的人卡信息
+        MsgFuncList.insert( std::make_pair( JSON_CMD_VALUE_LIGHTS_CTRL_REQUEST, &module_web::accept));  // 红绿灯控制指令
     }
 
     /// web前端有用户登录时,反馈给web所有信息

+ 65 - 52
net-service.cpp

@@ -18,6 +18,7 @@
 #include "crc.h"
 #include "mine_business.h"
 #include "tool_time.h"
+#include "module_service/module_traffic_light_manager.h"
 
 net_service::net_service()
 {
@@ -210,29 +211,34 @@ void net_service::on_message(const std::shared_ptr<client> &clt,const char*data,
                         logn_error(1,"在全局分站列表中找不到分站:%d", site_id);
                         break;
                     }
+                    
+                    if(clt->type() != 2){
+					    site_ptr->set_client(clt);
+					    //site_ptr->on_power_status((power&1)==0);
+                    }
+
                     site_ptr->set_algo(LDT_PDOA);
+                    //log_info("[scale_test] %.2f", site_ptr->m_scale);
                     struct timeval tv;
                     gettimeofday(&tv, NULL);
-                    uint64_t t = tv.tv_sec*1000 + tv.tv_usec/1000;
+                    uint64_t cur_time = tv.tv_sec*1000 + tv.tv_usec/1000;
                     int index = 0;
                     while(!is.eof()){
-                        uint64_t tstamp = t - 1000 + 50 + index*45;
+                        uint64_t tstamp = cur_time - 1000 + 50 + index*45;
                         ++index;
                         task* t = task::alloc<message_pdoa_locinfo>();
                         message_pdoa_locinfo& m = t->body<message_pdoa_locinfo>();
                         m.load(is);
                         float pdoa = 10.0;
-                        float dist = m.m_tof*15.65*2.996*1e-4/site_ptr->m_scale;
-                        if(fabs(m.m_poa[0]) < 10.0 && fabs(m.m_poa[1]) < 10.0){
-                            m.m_site_id = site_id;  
-                            m.m_time_stamp = tstamp;
-                            m.m_loc_type = LDT_PDOA;
-                            t->m_cmd_code = cmd;
-                            t->m_hash_id = m.m_card_id;
-                            pdoa = get_pdoa(m.m_poa, site_ptr->m_pdoa_offset);
-                            m_loc_worker->request(t);
-                        }
-                        logn_info(3, "[pdoa] site_id=%d, card_id=%d, dist=%.3f, poa1=%.4f, poa2=%.4f, poa3=%.4f, pdoa=%.4f, pdoa_offset=%.4f", site_id, m.m_card_id, dist, m.m_poa[0], m.m_poa[1], m.m_poa[2], pdoa, site_ptr->m_pdoa_offset);
+                        float dist = m.m_tof*15.65*2.996*1e-4;
+                        m.m_site_id = site_id;  
+                        m.m_time_stamp = tstamp;
+                        m.m_loc_type = LDT_PDOA;
+                        t->m_cmd_code = cmd;
+                        t->m_hash_id = m.m_card_id;
+                        pdoa = get_pdoa(m.m_poa, site_ptr->m_pdoa_offset);
+                        m_loc_worker->request(t);
+                        logn_info(3, "[pdoa] site_id=%d, card_id=%d, ct=%d, dist=%.3f, rav=%d, poa1=%.4f, poa2=%.4f, poa3=%.4f, pdoa=%.4f, pdoa_offset=%.4f", site_id, m.m_card_id, m.m_card_ct, dist, m.m_rav, m.m_poa[0], m.m_poa[1], m.m_poa[2], pdoa, site_ptr->m_pdoa_offset);
                     }
                 }
                 break;
@@ -313,55 +319,73 @@ void net_service::on_message(const std::shared_ptr<client> &clt,const char*data,
                 }
                 break;
 
-			case 0x793B: //虚拟推送的心跳测试
+            case CHAR_READER_HEART:
+                {
+                    uint32_t id = 0;
+                    uint16_t site_ct = 0;
+                    uint16_t reserve = 0;
+                    is>>id>>site_ct>>reserve;
+
+                    auto site_ptr = sit_list::instance()->get(id);
+                    if(!site_ptr){
+                        logn_error(1,"在全局分站列表中找不到分站:%d", id);
+                        break;
+                    }
+                }
+                break;
+            case 0x793B: //虚拟推送的心跳测试
 			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:
+            case THIRD_PARTY_CHAR_LIGHT_REQ_STATE:
                 {
-                    // 请求红绿灯状态
+                    // 红绿灯请求状态指令
                     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;
-                    }*/
+                    uint8_t dev_type = 0;
+
+                    is>>id>>dev_type;
+                    logn_info(4, "[traffic_light] light request state, light_id=%d, dev_type=%d", id, dev_type);
+                    // 找灯,并下发指令
+                    auto light_ptr = traffic_light_manager::instance()->get(id);
+                    if(light_ptr)
+                    {
+                        //traffic_light_manager::instance()->send_light_ctrl(id, DT_LIGHT, light_ptr->m_state); 
+                        traffic_light_manager::instance()->send_light_data(id, DT_LIGHT, light_shape::green_all_on);
+                    }else{
+                        traffic_light_manager::instance()->send_light_data(id, DT_LIGHT, light_shape::green_spark);
+                    }
 
-                    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:
+            case THIRD_PARTY_CHAR_LIGHT_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);
+                    logn_info(4, "[traffic_light] light heart message, light_id=%d, stamp=%d, status=%d", id, stamp, status);
+                   
+                    auto light_ptr = traffic_light_manager::instance()->get(id);
                     if(!light_ptr)
                     {
                         logn_error(1,"在全局信号灯列表中找不到信号灯:%d", id);
                         break;
-                    }*/
+                    }
+                    
+                    //log_info("[traffic_light] light client type=%d", clt->type());
+                    if(clt->type() != 2){
+                        light_ptr->set_client(clt);
+                    }
 
-                    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;
+                    light_ptr->m_state = status;
+                    light_ptr->m_rec_time = time(0);
 
-                    m_loc_worker->request(t);
+                    /*if((stamp%10) == 0){
+                        int shape = (status == light_shape::red_spark)?light_shape::green_spark:light_shape::red_spark;
+                        traffic_light_manager::instance()->send_light_ctrl(id, 0x05, shape);
+                    }*/
                 }
                 break;
 			default:
@@ -501,16 +525,5 @@ float net_service::get_pdoa(float poa[], const double& offset)
 
     pdoa -= PI;
 
-    //90 adjust
-    /*float pdoa = pdoa_raw - offset;
-    if(pdoa < -1*PI){
-        pdoa += TPI;
-    }
-    if(pdoa > PI){
-        pdoa -= TPI;
-    }*/
-
-    //logn_info(3, "[pdoa] poa1=%.4f, poa2=%.4f, poa3=%.4f, pdoa=%.4f", poa1, poa2, poa3, pdoa);
-
     return pdoa;
 }

+ 6 - 3
protocol.h

@@ -29,13 +29,16 @@
 #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  // 分站校时
+#define CHAR_READER_HEART                          0x793a  // 无线通信基站心跳
+// 6.third party
+#define THIRD_PARTY_CHAR_LIGHT_REQ_STATE    0x95a0  // 第三方红绿灯请求状态指令,由红绿灯->采集
+#define THIRD_PARTY_CHAR_LIGHT_HEART        0x95a1  // 第三方红绿灯心跳指令,由红绿灯->采集
+#define THIRD_PARTY_CHAR_LIGHT_SETUP_STATE  0x95a2  // 第三方红绿灯设置状态指令,由采集->红绿灯
+
 
 #endif

+ 47 - 2
websocket/jsonBuilder.cpp

@@ -1,6 +1,5 @@
 #include "jsonBuilder.h"
 #include <cstdlib>
-
 #include <rapidjson/writer.h>
 #include <rapidjson/stringbuffer.h>
 #include <rapidjson/prettywriter.h>
@@ -155,7 +154,7 @@ namespace YA
 		//18 车辆当天出勤的标识
 		tmp_object.SetInt( CardPos.is_on_duty );
 		Array.PushBack( tmp_object, Allocator );
-        	log_debug("websocket..%d",CardPos.area_info.size());
+        //log_debug("websocket..%d",CardPos.area_info.size());
 		rapidjson::Value Array_1( rapidjson::kArrayType );
 		for(const auto &a:CardPos.area_info)	
 		{
@@ -774,4 +773,50 @@ namespace YA
 
 		return true;
 	}
+
+    std::string jsonBuilder::build_traffic_light(const std::vector<light_state> lights)
+    {
+ 		if(lights.size() == 0){
+            return "";
+        }
+
+        rapidjson::StringBuffer sb;
+		rapidjson::Writer<rapidjson::StringBuffer> writer( sb );
+		rapidjson::Document doc;
+		rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();
+
+		rapidjson::Value root(rapidjson::kObjectType );
+
+        __SetCmd(JSON_KEY_CALL_LIGHT_LIGHT_STATE, root, allocator);
+
+        rapidjson::Value data(rapidjson::kArrayType);
+        for(auto it : lights){
+            rapidjson::Value elem(rapidjson::kArrayType);
+            rapidjson::Value tmp_object(rapidjson::kObjectType);
+
+            tmp_object.SetInt(it.m_group_id);
+            elem.PushBack(tmp_object, allocator);
+            
+            tmp_object.SetInt(it.m_light_id);
+            elem.PushBack(tmp_object, allocator);
+
+            tmp_object.SetInt(it.m_light_state);
+            elem.PushBack(tmp_object, allocator);
+
+            tmp_object.SetString(it.m_card_id.c_str(), allocator);
+            elem.PushBack(tmp_object, allocator);
+            
+            data.PushBack(elem, allocator);
+        }
+
+        root.AddMember("data", data, allocator);
+
+        __AddVersion(root, allocator);
+
+        root.Accept(writer);
+        return sb.GetString();
+    }
+
 }
+
+

+ 1 - 0
websocket/jsonBuilder.h

@@ -246,6 +246,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);
+        std::string build_traffic_light(const std::vector<light_state> lights);
 		/**
 		* @brief
 		生成车辆进入特殊区域jason函数。

+ 97 - 2
websocket/wsClient.cpp

@@ -217,7 +217,11 @@ namespace YA
 	void wsClient::_OnCallMessage( std::string const& name, sio::message::ptr const& data, bool need_ack, sio::message::list &ack_resp )
 	{
         // 接收web传送的json
-		log_info("web-message:%s",data->to_string().c_str());
+        if(data->to_string() == ""){
+            log_info("web-message: recv web send message is null!");
+            return;
+        }
+		log_info("web-message:%s", data->to_string().c_str());
 
 		if ( data->get_flag() == sio::message::flag_object ) 
 		{
@@ -246,7 +250,28 @@ namespace YA
 			}
 
 			__recv_ping_time = time(0);
-		}
+		}else if(data->get_flag() == sio::message::flag_string){
+            rapidjson::Document doc;
+            int len = data->to_string().length();
+            std::string str = data->to_string().substr(1, len-2);
+            doc.Parse(str.c_str());
+            if(!doc.HasParseError()){
+                std::string cmd = doc[JSON_ROOT_KEY_CMD].GetString();
+                auto mit_func = __MsgFuncList.find(cmd);
+                log_info("web-message: cmd=%s, type=%d, msg=%s", cmd.c_str(), data->get_flag(),data->to_string().c_str());
+                if(mit_func != __MsgFuncList.end()){
+                    sio::message::ptr msg = to_sio_message(str);  
+                    mit_func->second(GetID(), name, msg, need_ack, ack_resp);
+                }else{
+                    log_info("web-message: not found cmd, MsgFuncList.size()=%d", __MsgFuncList.size());
+                    for(auto it = __MsgFuncList.begin(); it != __MsgFuncList.end(); ++it){
+                        log_info("cmd: %s", it->first.c_str());
+                    }
+                }
+            }else{
+                log_info("web-message: parse error!");
+            }
+        }
 	}
 
 	void wsClient::_OnLoginResponse( std::string const & name, sio::message::ptr const & data, bool need_ack, sio::message::list & ack_resp )
@@ -308,4 +333,74 @@ namespace YA
 		return __recv_ping_time;
 	}
 
+    sio::message::ptr wsClient::to_sio_message(const std::string& val)
+    {
+        sio::message::ptr message = sio::object_message::create();
+        rapidjson::Document doc;
+        doc.Parse(val.c_str());
+
+        log_info("[change sio message] val=%s", val.c_str());
+        for(auto it = doc.MemberBegin(); it != doc.MemberEnd(); ++it){
+            std::string key = it->name.GetString();
+            log_info("[change sio message] name=%s", key.c_str());
+            if(it->value.IsString()){
+                static_cast<sio::object_message*>(message.get())->get_map()[key.c_str()] = sio::string_message::create(it->value.GetString());
+            }else if(it->value.IsObject()){
+                static_cast<sio::object_message*>(message.get())->get_map()[key.c_str()] = from_json(it->value);
+            }else if(it->value.IsArray()){
+                static_cast<sio::object_message*>(message.get())->get_map()[key.c_str()] = from_array(it->value);
+            }
+        }
+
+        return message;
+    }
+
+    sio::message::ptr wsClient::from_json(const rapidjson::Value& val)
+    {
+        sio::message::ptr message = sio::object_message::create();
+
+        log_info("[change sio message] from_json");
+        for(auto it = val.MemberBegin(); it != val.MemberEnd(); ++it){
+            if(it->value.IsInt()){
+                static_cast<sio::object_message*>(message.get())->get_map()[it->name.GetString()] = sio::int_message::create(it->value.GetInt());
+            }else if(it->value.IsString()){
+                static_cast<sio::object_message*>(message.get())->get_map()[it->name.GetString()] = sio::string_message::create(it->value.GetString());
+            }else if(it->value.IsBool()){
+                static_cast<sio::object_message*>(message.get())->get_map()[it->name.GetString()] = sio::bool_message::create(it->value.GetBool());
+            }else if(it->value.IsDouble()){
+                static_cast<sio::object_message*>(message.get())->get_map()[it->name.GetString()] = sio::double_message::create(it->value.GetDouble());
+            }else if(it->value.IsArray()){
+                static_cast<sio::object_message*>(message.get())->get_map()[it->name.GetString()] = from_array(it->value);
+            }else if(it->value.IsNull()){
+                static_cast<sio::object_message*>(message.get())->get_map()[it->name.GetString()] = sio::null_message::create();
+            }else if(it->value.IsObject()){
+                static_cast<sio::object_message*>(message.get())->get_map()[it->name.GetString()] = from_json(it->value);
+            }
+        }
+
+        return message;
+    }
+
+    sio::message::ptr wsClient::from_array(const rapidjson::Value& val)
+    {
+        sio::message::ptr message = sio::array_message::create();
+
+        log_info("[change sio message] from_array: %s", val.GetString());
+        for(auto it = val.Begin(); it != val.End(); ++it)
+        {
+            if(it->IsInt()){
+                static_cast<sio::array_message*>(message.get())->get_vector().push_back(sio::int_message::create(it->GetInt()));
+            }else if(it->IsString()){
+                static_cast<sio::array_message*>(message.get())->get_vector().push_back(sio::string_message::create(it->GetString()));
+            }else if(it->IsBool()){
+                static_cast<sio::array_message*>(message.get())->get_vector().push_back(sio::bool_message::create(it->GetBool()));
+            }else if(it->IsDouble()){
+                static_cast<sio::array_message*>(message.get())->get_vector().push_back(sio::double_message::create(it->GetDouble()));
+            }else if(it->IsObject()){
+                static_cast<sio::array_message*>(message.get())->get_vector().push_back(from_json(*it));
+            }
+        }
+
+        return message;
+    }
 }

+ 7 - 5
websocket/wsClient.h

@@ -6,7 +6,6 @@ websocket客户端类
   V 1.0.0
 
 * @author
-  王益俊
 
 * @date
   创建时间:  2018-08-14\n
@@ -26,17 +25,15 @@ websocket客户端类
 #include <mutex>
 #include <condition_variable>
 #include <map>
-#include<atomic>
-
+#include <atomic>
 #include <rapidjson/writer.h>
 #include <rapidjson/stringbuffer.h>
 #include <rapidjson/prettywriter.h>
-
 #include <boost/function.hpp>
 #include <boost/bind.hpp>
-
 #include "sio_client.h"
 #include "jsonBuilder.h"
+#include "sio_message.h"
 
 namespace YA
 {
@@ -113,6 +110,7 @@ namespace YA
 		*/
 		void _OnLoginResponse( std::string const& name, sio::message::ptr const& data, bool need_ack, sio::message::list &ack_resp );
 
+        sio::message::ptr light_ctrl_to_sio_message(const std::string& val);
 	public:
 		wsClient();
 		~wsClient();
@@ -184,5 +182,9 @@ namespace YA
 		* @brief	获取删除ping的时间。
 		*/
 		int GetPingTime() const ;
+
+        sio::message::ptr to_sio_message(const std::string& val);
+        sio::message::ptr from_json(const rapidjson::Value& val);
+        sio::message::ptr from_array(const rapidjson::Value& val);
 	};
 }

+ 0 - 4
websocket/wsClientMgr.h

@@ -6,7 +6,6 @@ websocket客户端管理器类
   V 1.0.0
 
 * @author
-  王益俊
 
 * @date
   创建时间:  2018-08-17\n
@@ -25,14 +24,11 @@ websocket客户端管理器类
 #include <vector>
 #include <string>
 #include <map>
-
 #include <boost/serialization/singleton.hpp>
-
 #include "wsClient.h"
 #include "ws_common.h"
 #include "jsonBuilder.h"
 
-
 namespace YA
 {
 	class wsClientMgr

+ 19 - 3
websocket/wsTimerThread.cpp

@@ -3,7 +3,7 @@
 #include "wsClientMgr.h"
 #include "constdef.h"
 #include "log.h"
-#include "ya_setting.h"
+#include "sys_setting.h"
 
 namespace YA
 {
@@ -75,13 +75,11 @@ namespace YA
     void wsTimerThread::send_card_pos()
     {
         if(__CardPosList.empty()){
-            //std::cout<<"send_card_pos: card's list is empty.";
             return;
         } 
 
         std::map<uint64_t, _CARD_POS_> cards;
         __CardPosList.copy(cards);
-        //log_info("[service-position] size=%d", cards.size());
         //service_position send
         for(auto it = cards.begin(); it != cards.end(); ++it)
         {
@@ -102,6 +100,18 @@ namespace YA
         swsClientMgr.send(JSON_CMD_VALUE_PUSH, json_pos);
     }
 
+    void wsTimerThread::send_light_state()
+    {
+        if(light_state_list.empty()){
+            return;
+        }
+        std::vector<light_state> lights = light_state_list;
+        log_info("[light_test] light_state's size=%d, copy=%d", light_state_list.size(), lights.size());
+        std::string json_light = __jsBuilder.build_traffic_light(lights);
+        swsClientMgr.send(JSON_CMD_VALUE_PUSH, json_light);
+        light_state_list.erase(light_state_list.begin(), light_state_list.end());
+    }
+
     /*
      * 定时器线程发送定位数据
      *
@@ -120,6 +130,7 @@ namespace YA
                 //service_position send
                 //pOwner->send_card_pos();
                 //pOwner->temp_send_card_pos();
+                pOwner->send_light_state();
 				__LastSendTime = t;
 			}
           	boost::this_thread::sleep( boost::posix_time::millisec( 1 ) );
@@ -162,4 +173,9 @@ namespace YA
 		uint64_t id=type<<32|pos.ID;
 		__CardPosList.erase( id );
 	}
+
+    void wsTimerThread::upt_light_state(const light_state& light)
+    {
+        light_state_list.push_back(light);
+    }
 }

+ 4 - 0
websocket/wsTimerThread.h

@@ -48,6 +48,7 @@ namespace YA
 		thread_safe_map<uint64_t, _CARD_POS_> __CardPosList;//卡位置列表
         std::time_t  __LastSendTime{0};//上一次发送的时间
 		jsonBuilder __jsBuilder;//json构造器类
+        std::vector<light_state> light_state_list;
 	private:
 		/**
 		* @brief
@@ -99,6 +100,7 @@ namespace YA
 		void __SendCardPos();
         void send_card_pos();
         void temp_send_card_pos();
+        void send_light_state();
 	protected:
 		/**
 		* @brief
@@ -200,6 +202,8 @@ namespace YA
 
 		*/
 		void del_card_pos( const _CARD_POS_& pos );
+
+        void upt_light_state(const light_state& light);
 	};
 }
 

+ 137 - 119
websocket/ws_common.h

@@ -1,23 +1,23 @@
 /**
-* @brief
-  websocket公共头文件
+ * @brief
+ websocket公共头文件
 
-* @version
-  V 1.0.0
+ * @version
+ V 1.0.0
 
-* @author
-  王益俊
+ * @author
+ 王益俊
 
-* @date
-  创建时间:  2018-08-17\n
+ * @date
+ 创建时间:  2018-08-17\n
 
-* @note
-  2018-08-17  初次创建。\n
+ * @note
+ 2018-08-17  初次创建。\n
 
-* @warning
+ * @warning
+
+ * @bug
 
-* @bug
-  
 */
 
 #ifndef _WS_COMMON_INC_H_
@@ -25,24 +25,24 @@
 #include <map>
 namespace YA
 {
-	const int MIN_SEND_INTERVAL = 1;//最小发送时间间隔
-
-	/**
-	* @brief
-	线程配置结构体。
-	*/
-	struct _THREAD_CONFIG_
-	{
-		int SendInterval;//发送间隔(单位:秒)
-		void Clear()
-		{
-			SendInterval = 0;
-		}
-		_THREAD_CONFIG_()
-		{
-			Clear();
-		}
-	};
+    const int MIN_SEND_INTERVAL = 1;//最小发送时间间隔
+
+    /**
+     * @brief
+     线程配置结构体。
+     */
+    struct _THREAD_CONFIG_
+    {
+        int SendInterval;//发送间隔(单位:秒)
+        void Clear()
+        {
+            SendInterval = 0;
+        }
+        _THREAD_CONFIG_()
+        {
+            Clear();
+        }
+    };
 
     // 传感器,加速度,角速度
     struct sensor{
@@ -60,96 +60,114 @@ namespace YA
             m_tri_acc[0] = m_tri_acc[1] = m_tri_acc[2] = m_tri_ang[0] = m_tri_ang[1] = m_tri_ang[2] = 0.0;
         }
     };
-	/**
-	* @brief
-	基础卡信息结构体。
-	*/
-	struct _BASE_CARD_: public sensor
-	{
-		int Type;               //卡类型
-		int ID;                 //卡ID
-		double x;               //x坐标
-		double y;               //y坐标
-		double z;               //z坐标
-		double down_time;       //入井时间戳
-		double enter_area_time; //进入区域时间戳
-		double rec_time;        //最后接收时间戳
-		double work_time;       //工作时长
-		int map_id;             //地图编号
-		int area_id;            //区域ID
-		int dept_id;            //部门编号
-		int stat;               //状态
-		int running_stat;       //运行状态: 包括上猴车状态
-		int biz_stat;           //业务状态
-		double speed;           //速度
+    /**
+     * @brief
+     基础卡信息结构体。
+     */
+    struct _BASE_CARD_: public sensor
+    {
+        int Type;               //卡类型
+        int ID;                 //卡ID
+        double x;               //x坐标
+        double y;               //y坐标
+        double z;               //z坐标
+        double down_time;       //入井时间戳
+        double enter_area_time; //进入区域时间戳
+        double rec_time;        //最后接收时间戳
+        double work_time;       //工作时长
+        int map_id;             //地图编号
+        int area_id;            //区域ID
+        int dept_id;            //部门编号
+        int stat;               //状态
+        int running_stat;       //运行状态: 包括上猴车状态
+        int biz_stat;           //业务状态
+        double speed;           //速度
         double m_freq;          // 卡频率
-		_BASE_CARD_()
-		{
-			Type            = 0;
-			ID              = 0;
-			x               = 0;
-			y               = 0;
-			z               = 0;
-			down_time       = 0;
-			enter_area_time = 0;
-			rec_time        = 0;
-			work_time       = 0;
-			map_id          = 0;
-			area_id         = 0;
-			dept_id         = 0;
-			stat            = 0;
-			running_stat    = 0;
-			biz_stat        = 0;
-			speed           = 0.0;
+        _BASE_CARD_()
+        {
+            Type            = 0;
+            ID              = 0;
+            x               = 0;
+            y               = 0;
+            z               = 0;
+            down_time       = 0;
+            enter_area_time = 0;
+            rec_time        = 0;
+            work_time       = 0;
+            map_id          = 0;
+            area_id         = 0;
+            dept_id         = 0;
+            stat            = 0;
+            running_stat    = 0;
+            biz_stat        = 0;
+            speed           = 0.0;
             m_freq          = 0.0;
-		}
-	};
-
-	/**
-	* @brief
-	卡位置结构体。
-	*/
-	struct _CARD_POS_ : public _BASE_CARD_
-	{
-		std::map<int,std::tuple<int,int,int,double,uint64_t>> area_info;
-		int landmark_id;//地标编号
-		int lm_direction;//地标方向
-		int landmark_dis;//距离地标的距离
-		int level_id;//级别编号
-		int is_on_duty;//车辆是否是当天出勤的标识(1:出勤,0:不出勤)
-		int display;//是否显示(1:显示,0:不显示)
-		void Clear()
-		{
-			landmark_id  = 0;
-			lm_direction = 0;
-			landmark_dis = 0;
-			level_id     = 0;
-			is_on_duty   = 0;
-			display      = 1;//默认显示
-		}
-		_CARD_POS_()
-		{
-			Clear();
-		}
-	};
-
-	/**
-	* @brief
-	统计部门结构体。
-	*/
-	struct _STAT_DEPT_ITEM_
-	{
-		int DeptID;//部门ID
-		std::map<int, int> Area;//区域数量列表(key是区域ID,value是区域里的卡数)
-		std::map<int, int> Dept;//部门数量列表(key是区域ID,value是部门里的卡数)
-		std::map<int, int> OcptLvl;//职务级别数量列表(key是区域ID,value是职务级别里的卡数)
-		int Sum;//卡总数
-		_STAT_DEPT_ITEM_()
-		{
-			DeptID = 0;
-			Sum    = 0;
-		}
-	};
+        }
+    };
+
+    /**
+     * @brief
+     卡位置结构体。
+     */
+    struct _CARD_POS_ : public _BASE_CARD_
+    {
+        std::map<int,std::tuple<int,int,int,double,uint64_t>> area_info;
+        int landmark_id;//地标编号
+        int lm_direction;//地标方向
+        int landmark_dis;//距离地标的距离
+        int level_id;//级别编号
+        int is_on_duty;//车辆是否是当天出勤的标识(1:出勤,0:不出勤)
+        int display;//是否显示(1:显示,0:不显示)
+        void Clear()
+        {
+            landmark_id  = 0;
+            lm_direction = 0;
+            landmark_dis = 0;
+            level_id     = 0;
+            is_on_duty   = 0;
+            display      = 1;//默认显示
+        }
+        _CARD_POS_()
+        {
+            Clear();
+        }
+    };
+
+    /**
+     * @brief
+     统计部门结构体。
+     */
+    struct _STAT_DEPT_ITEM_
+    {
+        int DeptID;//部门ID
+        std::map<int, int> Area;//区域数量列表(key是区域ID,value是区域里的卡数)
+        std::map<int, int> Dept;//部门数量列表(key是区域ID,value是部门里的卡数)
+        std::map<int, int> OcptLvl;//职务级别数量列表(key是区域ID,value是职务级别里的卡数)
+        int Sum;//卡总数
+        _STAT_DEPT_ITEM_()
+        {
+            DeptID = 0;
+            Sum    = 0;
+        }
+    };
+
+    struct light_state{
+        int m_group_id;
+        int m_light_id;
+        int m_light_state;
+        std::string m_card_id;
+
+        light_state(): m_group_id(0), m_light_id(0), m_light_state(0), m_card_id("")
+        {}
+
+        light_state(const int& gid, const int& lid, const int& state, const std::string& cid)
+            : m_group_id(gid),
+            m_light_id(lid),
+            m_light_state(state),
+            m_card_id(cid)
+        {}
+    };
+
 }
 
 #endif

+ 2 - 2
worker.cpp

@@ -106,9 +106,9 @@ struct timer_worker_thread: loop_thread
 			mine_business::inst()->clear_vehicle();
 		}
 		card_list::instance()->accept(clv);
-		bulletin_broad_show::inst()->run_bulletin_board();
+		//bulletin_broad_show::inst()->run_bulletin_board();
 		mine_business::inst()->run_business();
-        event_list::instance()->load_his_data_from_db(false);
+        //event_list::instance()->load_his_data_from_db(false);
 
 		//log_info("timer_worker_thread use time:%ldus", clock.count_us());
 	}

+ 0 - 1
znet.cpp

@@ -219,7 +219,6 @@ struct sock_client:fd_io,client_ex
 		m_recv_timer.set<sock_client,&sock_client::on_recv_timeout>(this);
 		int recv_timeout_first=config.get("service.recv_timeout_first",10);
 
-
 		m_recv_timer.start(recv_timeout_first,0);
 
 		int site_sync=config.get("site_sync",0);//分站时间同步,考虑到双IP双机情况,缺省关闭