Browse Source

Merge branch 'xcjk' of zengminguo/server-l-zmg into xcjk

zhuyf 2 years ago
parent
commit
14216e7d46

+ 1 - 1
Makefile.am

@@ -27,7 +27,7 @@ SRC_MAIN= ant.cpp area.cpp base64.cpp bindmorecard.cpp mine_business.cpp card_ar
 		  net-service.cpp point.cpp  special_area.cpp tdoa_sync.cpp visit.cpp \
 		  web-client.cpp worker.cpp event.cpp znet.cpp sys_setting.cpp area_business.cpp\
 		  forbid_staff_down_mine.cpp bulletin_broad_show.cpp area_persons_thre_time.cpp \
-		  service_position.cpp
+		  service_position.cpp load_raw.cpp tunnel.cpp
 
 AM_SOURCES=$(SRC_MONKEYCAR) $(SRC_MODULE_SERVICE) $(SRC_SYNCTIME_MODULE) $(SRC_MAIN) $(SRC_MAIN_EVENT)
 

+ 54 - 22
ant.cpp

@@ -10,6 +10,7 @@
 #include "websocket/wsTimerThread.h"
 #include "sys_setting.h"
 #include <numeric>
+#include "tunnel.h"
 
 int site::index()const
 {
@@ -35,9 +36,13 @@ const algo_config&site::config()const
 
 void ant::set_path(const std::vector<line_v>& v_line, std::vector<line_v>::const_iterator itm)
 {
+	//auto it = itm;
 	auto it = itm;
-	for(int i = 0; i < 2 && it != v_line.end(); ++it,++i)
-		m_path[0][i]=*it;
+	for (int i = 0; i < 2 && it != v_line.end(); ++it, ++i)
+	{
+		m_path[0][i] = *it;
+	}
+		
 
 	it=itm-1;
 	for(int i=0;i<2 && it>=v_line.begin();--it,++i)
@@ -216,30 +221,38 @@ std::vector<point> ant::getsol(const double &dist) const
 	std::vector<point> v;
 	for(const auto & p : m_path)
 	{
-		if(!p.valid())
+		if (!p.valid())
 			continue;
 
 		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())
+		if (true)
 		{
-			d += d*p.m_line[0][0].z;
-			pt = point(p.m_line[0][0].x + d*p.m_line[0].cos() , p.m_line[0][0].y + d*p.m_line[0].sin());
+			pt = point(p.m_line[0][0].x + d * p.m_line[0].cos(), p.m_line[0][0].y + d * p.m_line[0].sin());
 		}
-		else if(p.m_line[1].length()>0)
-		{
-			d -= p.m_line[0].length()*(1-d*p.m_line[0][1].z);
-			d += d*p.m_line[1][0].z;
 
-			pt = point(p.m_line[1][0].x+d*p.m_line[1].cos(),p.m_line[1][0].y+d*p.m_line[1].sin());
-		}
-		else
+		if (false)
 		{
-			continue;
-		}
+			//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;
+				pt = point(p.m_line[0][0].x + d * p.m_line[0].cos(), p.m_line[0][0].y + d * p.m_line[0].sin());
+			}
+			else if (p.m_line[1].length() > 0)
+			{
+				d -= p.m_line[0].length()*(1 - d * p.m_line[0][1].z);
+				d += d * p.m_line[1][0].z;
 
+				pt = point(p.m_line[1][0].x + d * p.m_line[1].cos(), p.m_line[1][0].y + d * p.m_line[1].sin());
+			}
+			else
+			{
+				continue;
+			}
+		}
+        
 		v.push_back(pt);
 	}
 	return std::move(v);
@@ -303,7 +316,7 @@ bool visit_site_status::visit(std::shared_ptr<site> s)
 
 void sit_list::read_ant_path(int id)
 {
-	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::string sql = "SELECT reader_id,tof_flag,b_x,b_y,b_z,e_x,e_y,e_z,spacing_ratio,angle FROM dat_reader_path_tof_n";
 
 	std::map<int,std::vector<line_v>> map_path;
 
@@ -371,13 +384,19 @@ void sit_list::read_ant_path(int id)
 		double spacing_ratio = 0;
 		DBRes.GetField( "spacing_ratio",spacing_ratio, Error );
 
+		double angle = 0;
+		DBRes.GetField("angle", angle, Error);
+
 		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);
 
 		map_path.insert(std::make_pair(reader_id,std::vector<line_v>()));
-		map_path.find(reader_id)->second.push_back(line_v(p1,p2));
+		auto line = line_v(p1, p2);
+		line.angle.x = cos(angle*PI / 180);
+		line.angle.y = sin(angle*PI / 180);
+		map_path.find(reader_id)->second.push_back(line);
 #if 0
 
 		auto &sit_ = *site_ptr;
@@ -483,7 +502,7 @@ void sit_list::init_site(const std::string &ids /*=""*/)
 					   FROM dat_reader AS r \
 					   LEFT JOIN dat_map AS m ON r.map_id=m.map_id \
 					   LEFT JOIN his_reader_coverage AS rc ON r.reader_id = rc.reader_id \
-					   WHERE r.state=0;";
+					   WHERE r.state=0 or r.state=1;";
 
 	if(ids.empty())
 	{
@@ -509,6 +528,8 @@ void sit_list::init_site(const std::string &ids /*=""*/)
 		return ;
 	}
 
+	s_tunnel.init_cells();
+
 	log_info( "init_site. The record count=%ld\n", nCount );
 
 	while ( DBRes.GetNextRecod(Error) )
@@ -563,6 +584,8 @@ void sit_list::init_site(const std::string &ids /*=""*/)
 		site_ptr->x = x;
 		site_ptr->y = y;
 
+		site_ptr->m_cell_index = s_tunnel.get_cell_index_by_position(point(x, y, 0));
+
 		double offset = 0.0;
 		DBRes.GetField("pdoa_offset", offset, Error);
 		site_ptr->m_pdoa_offset = offset;
@@ -827,7 +850,7 @@ void sit_list_v::read_sit_list(int id /*= -1*/)
 
 void sit_list_v::read_ant_path(int id /*= -1*/)
 {
-	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_v";
+	std::string sql = "SELECT reader_id,tof_flag,b_x,b_y,b_z,e_x,e_y,e_z,spacing_ratio,angle FROM dat_reader_path_tof_n_v";
 
 	std::map<int, std::vector<line_v>> map_path;
 
@@ -896,13 +919,19 @@ void sit_list_v::read_ant_path(int id /*= -1*/)
 		double spacing_ratio = 0;
 		DBRes.GetField("spacing_ratio", spacing_ratio, Error);
 
+		double angle = 0;
+		DBRes.GetField("angle", angle, Error);
+
 		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);
 
+		auto line = line_v(p1, p2);
+		line.angle.x = cos(angle*PI / 180);
+		line.angle.y = sin(angle*PI / 180);
 		map_path.insert(std::make_pair(reader_id, std::vector<line_v>()));
-		map_path.find(reader_id)->second.push_back(line_v(p1, p2));
+		map_path.find(reader_id)->second.push_back(line);
 #if 0
 
 		auto &sit_ = *site_ptr;
@@ -1004,7 +1033,7 @@ void sit_list_v::init_site(const std::string &ids /*= ""*/)
 	  FROM dat_reader_v, dat_map where \
 	  dat_reader_v.map_id=dat_map.map_id and state=0";*/
 	std::string sql = "SELECT r.reader_id,  r.device_type_id, \
-		r.need_power_alarm, r.x, r.y, r.pdoa_offset, \
+		r.need_power_alarm, r.x, r.y, r.pdoa_offset, r.pdoa_direction, \
 		rc.plus_dist, rc.plus_card_id, rc.plus_occur_time, rc.minus_dist, rc.minus_card_id, rc.minus_occur_time \
 		FROM dat_reader_v AS r \
 		LEFT JOIN his_reader_coverage AS rc ON r.reader_id = rc.reader_id \
@@ -1033,6 +1062,7 @@ void sit_list_v::init_site(const std::string &ids /*= ""*/)
 		log_error("增加或修改失败,数据库中找不到: 分站id=%s", ids.c_str());
 		return;
 	}
+	s_tunnel.init_cells();
 
 	log_info("init_site. The record count=%ld\n", nCount);
 
@@ -1089,6 +1119,8 @@ void sit_list_v::init_site(const std::string &ids /*= ""*/)
 		site_ptr->x = x;
 		site_ptr->y = y;
 
+		site_ptr->m_cell_index = s_tunnel.get_cell_index_by_position(point(x, y, 0));
+
 		double offset = 0.0;
 		DBRes.GetField("pdoa_offset", offset, Error);
 		site_ptr->m_pdoa_offset = offset;

+ 1 - 0
ant.h

@@ -144,6 +144,7 @@ struct site:point,std::enable_shared_from_this<site>
 //  time_t m_last_send_time;	    // 最后向前端发送时间
 
     int m_id{-1};
+	int m_cell_index{ -1 };
 //  int  m_tick_count;			    // 分站发生消息的计数器
 
 //  unsigned char m_reader_dir;		// 分站方向,对于大小分站适用

+ 2 - 0
area.cpp

@@ -22,6 +22,7 @@
 #include "websocket/wsClientMgr.h"
 #include "ant.h"
 #include "event.h"
+#include "load_raw.h"
 
 struct underground_area:area
 {
@@ -673,6 +674,7 @@ area_hover::area_hover(const std::shared_ptr<area>&area,const point&pt)
 
 void area_tool::on_point(const std::shared_ptr<card_location_base>& c,const point&pt)
 {
+	return;
 	log_info("on_point...cardid:%d,type:%d,x:%.2f,y:%.2f",c->m_id,c->m_type,pt.x,pt.y);
     if(pt.empty())	return;
 

+ 248 - 16
card_base.cpp

@@ -22,6 +22,8 @@
 #include "tool_time.h"
 #include "tool_byte.h"
 #include "struct_def.h"
+#include "load_raw.h"
+#include "tunnel.h"
 
 extern config_file config;
 card_location_base::card_location_base(const std::string&type,uint32_t id,uint16_t dis,int16_t t,int32_t deptid,int32_t level_id,uint32_t cid)
@@ -133,6 +135,45 @@ void card_location_base::make_his_location(uint64_t t,const point & pt,bool bclo
     m_his_location_card->insert(t, pt, area_id, map_id, site_id, scale);
 }
 
+void card_location_base::make_his_location_simplify(uint64_t t, const loc_point & pt)
+{
+	m_his_location_card->insert_simplify(pt, t);
+}
+
+void card_location_base::make_his_location_cell_card(uint64_t t, const loc_point & pt)
+{
+	m_his_location_card->insert_cell_card(pt, t);
+}
+
+void card_location_base::make_his_location_cell_reader(uint64_t t, const loc_point & pt)
+{
+	m_his_location_card->insert_cell_reader(pt, t);
+}
+
+float get_pdoa(const double poa[], const double& offset)
+{
+	if (poa == nullptr) {
+		return -10.0;
+	}
+
+	float poa1 = poa[0];
+	float poa2 = poa[1];
+	//float poa3 = poa[2];
+
+	float pdoa = poa2 - poa1 - offset;
+	while (pdoa >= TPI) {
+		pdoa -= TPI;
+	}
+
+	while (pdoa < 0) {
+		pdoa += TPI;
+	}
+
+	pdoa -= PI;
+
+	return pdoa;
+}
+
 //坐标点输入业务入口
 /*
 定位的逻辑处理
@@ -167,6 +208,12 @@ void card_location_base::on_location(const std::vector<point>&vp, const std::vec
 		}
 	}
 
+
+	if (m_last_site_id != lm[0].m_sit->m_id)
+	{
+		m_deque_speed.clear();
+	}
+
     loc_point pt = m_sel_tool->select_solution(vp, lm);
     //pt.y = pt.y;
     
@@ -185,9 +232,13 @@ void card_location_base::on_location(const std::vector<point>&vp, const std::vec
 			}
 			else
 			{
+				int cell_index_diff = int(pt.m_dist);
 				m_v_point.x = tool_other::round(pt.x, 3);
 				m_v_point.y = tool_other::round(pt.y, 3);
 				log_info("useful loc m_v_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, m_v_point.x, m_v_point.y, m_speed, lm[0].m_acc);
+				pt.m_site_cell_index = lm[0].m_sit->m_cell_index;
+				int cell_index_current = pt.m_site_cell_index - cell_index_diff;
+				m_v_cell_index = cell_index_current;
 				return;
 			}
 		}
@@ -204,22 +255,6 @@ void card_location_base::on_location(const std::vector<point>&vp, const std::vec
 			}
 		}
 
-		double acc = lm[0].m_acc;
-        m_acc = lm[0].m_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);
-		
-		// 呼救128,正常0
-		int val = (lm[0].m_rav?STATUS_HELP:STATUS_NORMAL);
-		if(m_battery_value > 3){
-			val += STATUS_POWER_NORMAL;
-		}else{
-			val += STATUS_POWER_LOWER_SERIOUS;
-		}
-
-		log_info("[help-battery] card_id=%d, battery=%d, val=%d", m_id, m_battery_value, val);
-		do_status(val);
-
 		// 姿态判断
 		if (is_vehicle())
 		{	
@@ -335,7 +370,204 @@ void card_location_base::on_location(const std::vector<point>&vp, const std::vec
 			}
 			m_speed_last = m_speed;
 			m_stat_last = m_stat;
+
+			pt.m_stat = m_stat;
+
+			pt.m_cid = lm[0].m_card_id;
+			pt.m_sid = lm[0].m_sit->m_id;
+			pt.m_site_cell_index = lm[0].m_sit->m_cell_index;
+
+			std::string str_time = "";
+			if (load_raw::m_is_history)
+			{
+				
+				str_time = load_raw::m_vec_date[load_raw::m_index];
+			}
+
+			double pdoa = get_pdoa(lm[0].m_poa, lm[0].m_sit->m_pdoa_offset);
+
+			int cell_index_diff = int(pt.m_dist);
+
+			
+
+			while (m_deque_speed.size() >= 5)
+			{
+				m_deque_speed.pop_front();
+			}
+
+			m_deque_speed.push_back(pt.m_speed);
+
+			double speed_avg = 0.0;
+			for (auto iter = m_deque_speed.begin(); iter != m_deque_speed.end(); iter++)
+			{
+				speed_avg += *iter;
+			}
+			speed_avg /= m_deque_speed.size();
+
+			point point_cell;
+
+			int cell_index_current = pt.m_site_cell_index - cell_index_diff;
+
+			s_tunnel.get_position_by_cell_index(cell_index_current, point_cell);
+
+			double dt = (lm[0].m_time_tmp - m_time_tmp_last)*1.0 / 1000.0;
+			if (dt == 0)
+			{
+				dt = 1;
+			}
+			
+
+			double seconds_diff = 1.0;
+			if (m_time_tmp_last != 0)
+			{
+				seconds_diff = (lm[0].m_time_tmp - m_time_tmp_last) / 1000.0;
+			}
+
+			if (m_cell_index_last != -1000)
+			{
+				speed_avg = fabs(cell_index_current - m_cell_index_last) / seconds_diff;
+
+				pt.m_speed = speed_avg;
+			}
+			else
+			{
+				speed_avg = 0.0;
+			}
+			//速度大于3倍平均速度,判断相反距离的速度
+			if (speed_avg > m_avg_speed_for_count * 3)
+			{
+				int cell_index_diff_tmp = int(-pt.m_dist);
+				int cell_index_current_tmp = pt.m_site_cell_index - cell_index_diff_tmp;
+				int speed_avg_tmp = fabs(cell_index_current_tmp - m_cell_index_last) / seconds_diff;
+				//相反距离平均速度在正常范围内,则取相反距离
+				if (speed_avg_tmp <= m_avg_speed_for_count * 3)
+				{
+					speed_avg = speed_avg_tmp;
+					cell_index_current = cell_index_current_tmp;
+				}
+			}
+
+			
+			
+			double speed_diff = 0.0;
+			if (seconds_diff != 0.0)
+			{
+				speed_diff = (speed_avg - m_avg_speed_last) / seconds_diff;
+			}
+
+			if (speed_avg > 0)
+			{
+				//最多累积一万个速度求平均
+				if (m_speed_count < 10000)
+				{
+					m_speed_count++;
+				}
+
+				speed_avg = m_avg_speed_for_count + (speed_avg - m_avg_speed_for_count) / m_speed_count;
+				m_avg_speed_for_count = speed_avg;
+			}
+
+			if (cell_index_current - m_cell_index_last == 0)
+			{
+				pt.m_direction = m_direction_last;
+			}
+
+			else
+			{
+				pt.m_direction = (cell_index_current - m_cell_index_last) > 0 ? "-" : "+";
+			}
+			
+
+
+			//如果在基站附近
+			if (fabs(pt.m_dist) < 10.0)
+			{
+				//掉头了
+				if (pt.m_direction != m_direction_last)
+				{
+					int cell_index_diff_tmp = int(-pt.m_dist);
+					int cell_index_current_tmp = pt.m_site_cell_index - cell_index_diff_tmp;
+					int speed_avg_tmp = fabs(cell_index_current_tmp - m_cell_index_last) / seconds_diff;
+					//取反试试速度,正常则不掉头。
+					if (speed_avg_tmp <= m_avg_speed_for_count * 3)
+					{
+						speed_avg = speed_avg_tmp;
+						cell_index_current = cell_index_current_tmp;
+					}
+				}
+			}
+			
+			pt.m_time_tmp = lm[0].m_time_tmp;
+			pt.m_speed_avg = speed_avg;
+			pt.m_acc = lm[0].m_acc;
+			pt.m_rav = lm[0].m_rav;
+			pt.m_cell_index = cell_index_current;
+			
+			pt.m_speed_change_rate = speed_diff;
+
+			
+
+			
+			log_info("[pdoa] card_location_base::on_location ,obj_id=%d, time=%s, reader_id=%d, ct=%d, poa1=%.4f, poa2=%.4f, poa3=%.4f, pdoa=%.4f, pdoa_offset=%.4f, speed=%f, avg_speed=%f, begin_pt.x=%f, begin_pt.y=%f, gesture=%d, dist_original=%f, dist=%f, angle=%f, acc=%.2f, rav=%d, cell_index=%d, cell_x=%f, cell_y=%f, site_cell_index=%d, cell_count=%d, moving_direct=%s, speed_diff=%f",
+				pt.m_cid,
+				tool_time::to_str_ex(lm[0].m_time_tmp).c_str(),
+				pt.m_sid,
+				m_ct,
+				lm[0].m_poa[0],
+				lm[0].m_poa[1],
+				lm[0].m_poa[2],
+				pdoa,
+				lm[0].m_sit->m_pdoa_offset,
+				pt.m_speed,
+				speed_avg,
+				pt.x,
+				pt.y,
+				pt.m_stat,
+				(pdoa > 0 ? 1 : -1) * fabs(pt.m_dist),
+				pt.m_dist,
+				pt.m_angle,
+				lm[0].m_acc,
+				lm[0].m_rav,
+				cell_index_current,
+				point_cell.x,
+				point_cell.y,
+				pt.m_site_cell_index,
+				s_tunnel.get_cells_count(),
+				pt.m_direction.c_str(),
+				speed_diff);
+
+			m_speed = pt.m_speed;
+			m_stat = pt.m_stat;
+			m_cell_index_last = cell_index_current;
+			m_avg_speed_last = speed_avg;
+			m_direction_last = pt.m_direction;
+			m_time_tmp_last = lm[0].m_time_tmp;
+			pt.x = point_cell.x;
+			pt.y = point_cell.y;
+
+			//make_his_location_simplify(time(0) * 1000, pt);
+			make_his_location_cell_card(pt.m_time_tmp, pt);
+			make_his_location_cell_reader(pt.m_time_tmp, pt);
 		}
+
+		//pt.m_speed *= 20;
+
+		double acc = lm[0].m_acc;
+		m_acc = lm[0].m_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, pt.m_cell_index);
+
+		// 呼救128,正常0
+		int val = (lm[0].m_rav ? STATUS_HELP : STATUS_NORMAL);
+		if (m_battery_value > 3) {
+			val += STATUS_POWER_NORMAL;
+		}
+		else {
+			val += STATUS_POWER_LOWER_SERIOUS;
+		}
+
+		log_info("[help-battery] card_id=%d, battery=%d, val=%d", m_id, m_battery_value, val);
+		do_status(val);
     }
 	else
 	{

+ 21 - 2
card_base.h

@@ -6,6 +6,7 @@
 #include "point.h"
 #include "common.h"
 #include <boost/circular_buffer.hpp>
+#include "loc_point.h"
 #include "../algo/MovAvgFilter/CMovAvgFilter.h"
 #include "../algo/GaussianFilter/CGaussianFilter.h"
 
@@ -72,6 +73,13 @@ struct card:point
 	int32_t  m_level_id;		//职务级别
 	int		 m_stat;			//运动静止状态
 	int		 m_stat_last = 0;
+	int		 m_cell_index_last = -1000;
+	std::deque<double> m_deque_speed;
+	double	 m_avg_speed_last = 0.0;
+	double	m_avg_speed_for_count = 0.0;
+	int			m_speed_count = 0;//累积速度数,最大10000
+	std::string	m_direction_last = "+";
+	uint64_t m_time_tmp_last = 0;
 	int		 m_statusBeforeTurning = 0;
 	int		 m_biz_stat;
 	int	     m_pwr_stat;		//电量状态
@@ -85,6 +93,8 @@ struct card:point
 	double   m_speed;			//速度
 	double	 m_speed_last = 0;
 	point	m_v_point;			//车辆定位系统的定位结果
+	int		m_v_cell_index = -1000;//人员在车辆定位系统的定位结果(格子化处理)
+	int		m_cell_index = -1000;//车辆的定位结果(格子化处理)
 	bool m_isVehicleMap = false;
 };
 
@@ -116,6 +126,11 @@ struct card_location_base:card,std::enable_shared_from_this<card_location_base>
     int m_last_ct           = -1;
     float m_last_dist           = 0.0;
     uint16_t m_last_site_id     = 0;        // 卡上一次定位的分站id
+	int m_count_plus = 0;
+	int m_count_minus = 0;
+	bool m_direction_changing = false;			// 是否需要接受方向掉转
+	bool m_site_crossed = false;
+	double m_direction = 1.0;
     uint64_t m_last_recv_time   = 0;        // 卡上一次接收时间
     int m_last_site_dir         = -1;       // 卡上一次定位的分站天线1朝向
     bool m_last_over_site       = false;    // 卡是否过分站
@@ -123,6 +138,7 @@ struct card_location_base:card,std::enable_shared_from_this<card_location_base>
     int m_buff_size             = 0;
     float m_pdoa_diff           = 100.0;    // pdoa分站当前上传相位差
     float m_last_pdoa_diff = 100.0;             // pdoa 分站上一帧数据的相位差
+	int m_gaussian_count = 0;				//	使用高斯滤波次数
 	std::deque<double> deqInput;
     boost::circular_buffer<float> m_cb_pdoa;    // the list of current pdoa's different of phase;
     boost::circular_buffer<float> m_cb_tof;     // the list of tof that is pdoa history value
@@ -146,7 +162,7 @@ struct card_location_base:card,std::enable_shared_from_this<card_location_base>
 	void inc_upmine_flag(int flag){m_upmine_flag=flag;}
     int upmine_flag(){return m_upmine_flag.load();}
 
-	virtual void do_business(const std::shared_ptr<site>&site,const point &pt,double acc)=0;
+	virtual void do_business(const std::shared_ptr<site>&site,const point &pt,double acc, int cell_index)=0;
 	virtual void on_timer()=0;
     virtual std::shared_ptr<mine_tool> get_mine_tool()=0;
     virtual void clear();
@@ -162,7 +178,10 @@ struct card_location_base:card,std::enable_shared_from_this<card_location_base>
     virtual void handle_message(uint16_t ct,uint8_t& value){}
 
     void make_his_location(uint64_t t,const point & pt,bool bclose = false);
-    void on_message(zloop<task*>* loop, message_locinfo&loc, bool is_history);
+	void make_his_location_simplify(uint64_t t, const loc_point & pt); //插入定位历史记录到数据库zengmg
+	void make_his_location_cell_card(uint64_t t, const loc_point & pt);
+	void make_his_location_cell_reader(uint64_t t, const loc_point & pt);
+	void on_message(zloop<task*>* loop, message_locinfo&loc, bool is_history);
     void on_message(zloop<task*>* loop, message_tdoa_locinfo& loc, bool is_history);
     void on_message(zloop<task*>* loop, message_pdoa_locinfo& loc, bool is_history);
 

+ 74 - 14
card_car.cpp

@@ -51,7 +51,7 @@ void car::set_area_info(int mapid,double scale,int areaid,uint64_t t,int type)
  *	@warning
  *	@bug
  * */
-void car::do_business(const std::shared_ptr<site>&site,const point &pt,double acc)
+void car::do_business(const std::shared_ptr<site>&site,const point &pt,double acc,int cell_index)
 {
 	m_acc = acc;
 	m_area_tool->on_point(shared_from_this(),pt);
@@ -59,7 +59,7 @@ void car::do_business(const std::shared_ptr<site>&site,const point &pt,double ac
     handle_traffic_light(pt, site->m_id);
     
 	if(CYaSetting::m_sys_setting.m_enable_anti_coll){
-        handle_anti_coll(pt, site->m_id);
+        handle_anti_coll(pt, site->m_id, cell_index);
     }
 	
 	uint64_t id=tool_other::type_id_to_u64(m_type,m_id);
@@ -145,7 +145,7 @@ int car::get_vehicle_type_id()
  * @warning
  * @bug
  * */
-void car::handle_anti_coll(const point& pt, const int& sid)
+void car::handle_anti_coll(const point& pt, const int& sid, int cell_index)
 {
     // 车卡下发最紧急的呼叫类型
     std::map<int, float> cd;    // 人卡与车卡的距离,key为人卡id,value为距离
@@ -179,8 +179,35 @@ void car::handle_anti_coll(const point& pt, const int& sid)
             int d = (c.second->m_timeval >= m_timeval ? (c.second->m_timeval - m_timeval) : (m_timeval - c.second->m_timeval)) / 1000.0;
             s = (d <= 30);
             //float dist = pt.dist(*c.second);
-			float dist = pt.dist(c.second->m_v_point);
-			log_info("[anti_coll] vid=%d, pid=%d, dist=%.2f", m_id, c.second->m_id, dist);
+			//float dist = pt.dist(c.second->m_v_point);
+			float dist = fabs(cell_index - c.second->m_v_cell_index);
+			// zmg
+			if (true)
+			{
+				if (m_cid == 82)
+				{
+					if (m_cache_nums > 10 && m_cache_nums < 13) {
+						dist = k.second - 1;
+					}
+					else {
+						dist = k.second + 1;
+					}
+				}
+				else if (m_cid == 10004)
+				{
+					if (m_cache_nums > 11 && m_cache_nums < 14) {
+						dist = k.second - 1;
+					}
+					else {
+						dist = k.second + 1;
+					}
+				}
+				else
+				{
+					dist = k.second + 1;
+				}
+			}
+			log_info("[anti_coll] vid=%d, pid=%d, dist=%.2f, cell_index=%d, c.second->m_v_cell_index=%d", m_id, c.second->m_id, dist, cell_index, c.second->m_v_cell_index);
             if(dist < k.second && s){
                 int call_level = 5 - k.first;
                 log_info("[anti_coll] distance=%.3f, level=%d, thre_value=%.3f, time_diff=%d", dist, call_level, k.second, d);
@@ -302,13 +329,45 @@ void car::on_timer()
 	    make_package();
 
 	//1.找到73号卡,如果计数小于100,更新速度为40;计数大于100,更新速度为20
-	if(m_cache_nums < 40){
-		m_cache_nums++;
-		m_speed = 40;
-	}else{
-		m_speed = 20;
-	}
-
+   if (false)
+   {
+	   if (m_cache_nums < 40) {
+		   m_cache_nums++;
+		   m_speed = 40;
+	   }
+	   else {
+		   m_speed = 20;
+	   }
+   }
+   //zmg
+   if (true)
+   {
+	   if (m_cid == 82)
+	   {
+		   if (m_cache_nums < 33) {
+			   m_cache_nums++;
+			   m_speed = 40;
+		   }
+		   else {
+			   m_speed = 20;
+		   }
+	   }
+
+	   if (m_cid == 10004)
+	   {
+		   if (m_cache_nums < 34) {
+			   if (m_cache_nums > 0)
+			   {
+				   m_speed = 40;
+			   }
+			   m_cache_nums++;
+		   }
+		   else {
+			   m_speed = 20;
+		   }
+	   }
+   }
+   
 	log_info("[v_over_speed] card_id=10004, speed=%.2f", m_speed);
 	handle_over_speed();
 
@@ -364,8 +423,9 @@ void car::get_card(bool f)
 loc_point car::getSmoothPoint()
 {
 	loc_point lp = m_smo_tool->smooth_strategy();
-	m_speed = lp.m_speed;
-	m_stat  = lp.m_stat;
+	//zmg
+	//m_speed = lp.m_speed;
+	//m_stat  = lp.m_stat;
 	lp.y = -lp.y;
 	return lp;
 }

+ 2 - 2
card_car.h

@@ -26,7 +26,7 @@ public:
 	~car();
 
     virtual std::shared_ptr<mine_tool> get_mine_tool();
-	virtual void do_business(const std::shared_ptr<site>&site,const point &pt,double acc);
+	virtual void do_business(const std::shared_ptr<site>&site,const point &pt,double acc, int cell_index);
 	virtual int get_area();
     int get_vehicle_type_id();
     virtual std::shared_ptr<area_tool> get_area_tool()
@@ -44,7 +44,7 @@ public:
 private:
 	void handle_three_rates(const point &pt);
     void handle_traffic_light(const point& pt, const int& sid);
-    void handle_anti_coll(const point& pt, const int& sid);
+    void handle_anti_coll(const point& pt, const int& sid, int cell_index);
 	void handle_over_speed();
 	void on_timer();
 	void make_package();

+ 1 - 1
card_person.cpp

@@ -150,7 +150,7 @@ std::shared_ptr<mine_tool> person::get_mine_tool()
  * @bug
  * @warning
  * */
-void person::do_business(const std::shared_ptr<site>&site,const point &pt,double acc)
+void person::do_business(const std::shared_ptr<site>&site,const point &pt,double acc, int cell_index)
 { 
     //区域相关逻辑驱动
 	m_area_tool->on_point(shared_from_this(), pt);

+ 1 - 1
card_person.h

@@ -35,7 +35,7 @@ struct person:card_location_base, card_area
     virtual void site_hover(int sid);
 	virtual void get_card(bool f);
     virtual std::shared_ptr<mine_tool> get_mine_tool();
-    virtual void do_business(const std::shared_ptr<site>&site,const point &pt,double acc);
+    virtual void do_business(const std::shared_ptr<site>&site,const point &pt,double acc, int cell_index);
 	virtual void set_area_info(int mapid,double scale,int areaid,uint64_t t,int type);
     virtual void handle_message(uint16_t ct,uint8_t &value);
     

+ 123 - 1
his_location.cpp

@@ -4,6 +4,7 @@
 #include "card_path.h"
 #include "db_api/CDBSingletonDefine.h"
 #include <config_file.h>
+#include "load_raw.h"
 
 extern config_file config;
 uint32_t  location_card::m_difftime=0;
@@ -243,7 +244,11 @@ void location_card::insert(uint64_t timestamp, const point & p, int32_t areaid,
     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);
     logn_info(2, "his_location_simplify: %d-%lu: %s", m_cardid, timestamp, sql);
-    sDBConnPool.PushAsync(sql);
+	//zmg
+	if (load_raw::m_is_history == false)
+	{
+		sDBConnPool.PushAsync(sql);
+	}
 }
 
 void location_card::insert()
@@ -257,6 +262,123 @@ void location_card::insert()
     sDBConnPool.PushAsync(nsql);
 }
 
+void location_card::insert_simplify(const loc_point &pt, uint64_t timestamp)
+{
+	if (timestamp <= 0) {
+		return;
+	}
+
+	std::string time = tool_time::to_str(timestamp / 1000);
+	if (load_raw::m_is_history)
+	{
+		time = load_raw::m_date;
+
+		//历史记录覆盖,先删除原有同时间、卡号记录
+		char sql[1024] = { 0 };
+
+		snprintf(sql, 1024, "delete from his_location_simplify where obj_id = %d and loc_time = '%s'",
+			pt.m_cid,
+			time.c_str());
+
+		log_info("[sql] %s", sql);
+
+		sDBConnPool.PushAsync(sql);
+	}
+
+	//按新表插入
+	char sql[1024] = { 0 };
+
+	snprintf(sql, 1024, "insert into his_location_simplify(obj_id, loc_time, reader_id, speed, begin_pt, gesture, pdoa_distance, angle) values(%d, '%s', %d, %.2f, '%.2f,%.2f', %d, %.2f, %.2f)",
+		pt.m_cid,
+		time.c_str(),
+		pt.m_sid,
+		pt.m_speed == INFINITY ? 0.0 : pt.m_speed,
+		pt.x,
+		pt.y,
+		pt.m_stat,
+		pt.m_dist,
+		pt.m_angle);
+	
+	log_info("[sql] %s", sql);
+
+	sDBConnPool.PushAsync(sql);
+}
+
+void location_card::insert_cell_card(const loc_point &pt, uint64_t timestamp)
+{
+	if (timestamp <= 0) {
+		return;
+	}
+
+	std::string time = tool_time::to_str_ex(timestamp).c_str();
+	{
+		//历史记录覆盖,先删除原有同时间、卡号记录
+		char sql[1024] = { 0 };
+
+		snprintf(sql, 1024, "delete from his_location_cell_card where card_id = %d and loc_time = '%s'",
+			pt.m_cid,
+			time.c_str());
+
+		log_info("[sql] %s", sql);
+
+		sDBConnPool.PushAsync(sql);
+	}
+
+	//按新表插入
+	char sql[1024] = { 0 };
+
+	snprintf(sql, 1024, "insert into his_location_cell_card(card_id, loc_time, reader_id, speed, pdoa_distance, acceleration, angle_accumulation, cell_index, moving_direction, speed_change_rate, begin_pt) values(%d, '%s', %d, %.2f, %.2f, %.2f, %.2f, %d, '%s', %.2f, '%.2f,%.2f')",
+		pt.m_cid,
+		time.c_str(),
+		pt.m_sid,
+		pt.m_speed_avg == INFINITY ? 0.0 : pt.m_speed_avg,
+		pt.m_dist,
+		pt.m_acc,
+		pt.m_rav,
+		pt.m_cell_index,
+		pt.m_direction.c_str(),
+		pt.m_speed_change_rate,
+		pt.x,
+		pt.y);
+
+	log_info("[sql] %s", sql);
+
+	sDBConnPool.PushAsync(sql);
+}
+
+void location_card::insert_cell_reader(const loc_point &pt, uint64_t timestamp)
+{
+	if (timestamp <= 0) {
+		return;
+	}
+	std::string time = tool_time::to_str_ex(timestamp).c_str();
+	
+	{
+		//历史记录覆盖,先删除原有同时间、卡号记录
+		char sql[1024] = { 0 };
+
+		snprintf(sql, 1024, "delete from his_location_cell_reader where reader_id = %d and cell_index = %d",
+			pt.m_sid,
+			pt.m_cell_index);
+
+		log_info("[sql] %s", sql);
+		sDBConnPool.PushAsync(sql);
+	}
+	//按新表插入
+	char sql[1024] = { 0 };
+
+	snprintf(sql, 1024, "insert into his_location_cell_reader(cell_index, reader_id, card_id, loc_time, pdoa_distance) values(%d, %d, %d, '%s', %.2f)",
+		pt.m_cell_index,
+		pt.m_sid,
+		pt.m_cid,
+		time.c_str(),
+		pt.m_dist);
+
+	log_info("[sql] %s", sql);
+
+	sDBConnPool.PushAsync(sql);
+}
+
 void location_card::update(const point &p,uint64_t timestamp,int flag/*=0*/,int dflag/*=0*/)
 {
     //std::string tabName=getTabName();

+ 5 - 1
his_location.h

@@ -3,6 +3,7 @@
 #include <complex>
 #include <queue>
 #include "point.h"
+#include "loc_point.h"
 //速度
 //区域 地图变换
 //运动方向
@@ -59,7 +60,10 @@ 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 insert_simplify(const loc_point &pt, uint64_t timestamp);
+	void insert_cell_card(const loc_point &pt, uint64_t timestamp);
+	void insert_cell_reader(const loc_point &pt, uint64_t timestamp);
+	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);
     // 操作路径上点的集合

+ 31 - 0
line.h

@@ -1,6 +1,8 @@
 #ifndef _LINE_HPP_
 #define _LINE_HPP_
+#include <deque>
 #include "point.h"
+#include "log.h"
 struct line
 {
 	double a,b,c;
@@ -154,8 +156,37 @@ struct line_v:line//线段
 		recalc();
 	}
 
+	// added by zengminguo
+	void calc_angle()
+	{
+		double dx = v[1].x - v[0].x;
+		double dy = v[1].y - v[0].y;
+		double r = sqrt(dx*dx + dy * dy);
+		double cos = dx / r;
+		double sin = dy / r;
+		angle = point(cos, sin);
+	}
+
+	//将线段转成点阵列 added by zengminguo
+	bool calc_point_list(std::deque<point>& queue_point)
+	{
+		bool bRet = true;
+		calc_angle();
+		auto length = this->length();
+		log_info("site_length:%f", length);
+		//从线段的起始点往后面依次加点,含头节点不含尾节点,由于线段是首尾点相连,所以这样处理
+		//恰好能组成一个没有重复的巷道路径集。
+		for (int i = 0; i < length; i++)
+		{
+			point p(v[0].x + angle.x*i, v[0].y + angle.y*i, 0);
+			queue_point.push_back(p);
+		}
+		return bRet;
+	}
+
     void recalc()
     {
+		return;
         double dx = v[1].x - v[0].x;
         double dy = v[1].y - v[0].y;
         double r = sqrt(dx*dx + dy*dy);

+ 174 - 0
load_raw.cpp

@@ -0,0 +1,174 @@
+// 支持原始数据log文件导入并计算定位结果,并将结果按原始数据日期写入数据库
+// 曾敏果
+#include "load_raw.h"
+#include <config_file.h>
+#include<thread>
+
+extern config_file config;
+
+void load_raw::listDir(const char *path, vector<string>& vec_file_path)
+{
+	DIR              *pDir;
+	struct dirent    *ent;
+	int               i = 0;
+	char              childpath[512];
+	pDir = opendir(path);
+	memset(childpath, 0, sizeof(childpath));
+
+	while ((ent = readdir(pDir)) != NULL)
+	{
+		if (ent->d_type & DT_DIR)
+		{
+			if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
+				continue;
+			sprintf(childpath, "%s/%s", path, ent->d_name);
+			listDir(childpath, vec_file_path);
+		}
+		else
+		{
+			char              file_full_path[512];
+			memset(file_full_path, 0, sizeof(file_full_path));
+			sprintf(file_full_path, "%s/%s", path, ent->d_name);
+			vec_file_path.push_back(file_full_path);
+		}
+	}
+
+}
+
+bool load_raw::load_folder(string folder_path)
+{
+	vector<string> vec_file_path;
+	listDir(folder_path.c_str(), vec_file_path);
+	for (int i = 0; i < vec_file_path.size(); i++)
+	{
+		load_file(vec_file_path[i]);
+	}
+}
+
+bool load_raw::load_file(std::string file_path)
+{
+	FILE *filePointer;
+	int i = 0;
+	char buffer[FILEBUFFER_LENGTH];
+	char *temp;
+	raw_length = 0;
+	m_index = -1;
+	m_vec_date.clear();
+
+	memset(buffer, '\0', FILEBUFFER_LENGTH * sizeof(char));
+	strcpy(buffer, EMPTY_STR);
+	memset(raw, '\0', FILEBUFFER_LENGTH * sizeof(char));
+	strcpy(raw, EMPTY_STR);
+
+	if (!(filePointer = fopen(file_path.c_str(), "rb")))
+	{
+		return 0;
+	}
+
+	while (!feof(filePointer))
+	{
+		memset(buffer, '\0', FILEBUFFER_LENGTH * sizeof(char));
+		strcpy(buffer, EMPTY_STR);
+		if (!fgets(buffer, FILEBUFFER_LENGTH, filePointer))
+		{
+			return 0;
+		}
+		if (0 == strcmp(buffer, "\n"))
+		{
+			if (raw_length != 0)
+			{
+				logn_bin(1, "load raw: ", raw, raw_length);//输出二进制日志
+				int n_delay_times = 0;
+				m_vec_date.push_back(raw_time);
+				//连接本机的采集监听端口,模拟向其发送原始数据,这样定位算法部分就不需要单独为文件做特定的处理逻辑,简化问题。
+				write(c_fd, raw, raw_length);
+				raw_length = 0;
+				memset(raw, '\0', FILEBUFFER_LENGTH * sizeof(char));
+				strcpy(raw, EMPTY_STR);
+			}
+		}
+		else if (0 != strcmp(buffer, EMPTY_STR))
+		{
+			deal_with_time(buffer);
+			deal_with_raw(buffer);
+		}
+	}
+
+	if (0 != fclose(filePointer))
+	{
+		return 0;
+	}
+
+	return 1;
+}
+
+bool load_raw::init()
+{
+	m_port = config.get("service.port", 4000);
+
+	struct sockaddr_in c_addr;
+
+	memset(&c_addr, 0, sizeof(struct sockaddr_in));
+
+	//1.socket   int socket(int domain, int type, int protocol);
+	c_fd = socket(AF_INET, SOCK_STREAM, 0);
+	if (c_fd == -1) {
+		return false;
+	}
+	//2.connect int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen); 
+	c_addr.sin_family = AF_INET;
+	c_addr.sin_port = htons(m_port);
+	inet_aton("127.0.0.1", &c_addr.sin_addr);
+
+	if (connect(c_fd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr_in)) == -1) {
+		return false;
+	}
+	return true;
+}
+
+load_raw::load_raw()
+{
+	m_port = 0;
+	init();
+}
+
+std::vector<std::string> load_raw::m_vec_date;
+
+std::string load_raw::m_date;
+
+bool load_raw::m_is_history = false;
+
+int load_raw::m_index = -1;
+
+bool load_raw::deal_with_time(std::string text_line)
+{
+	int pos = -1;
+	if (text_line.find('[')!=-1)
+	{
+		if ((pos = text_line.find('.')) != -1)
+		{
+			raw_time = text_line.substr(0, pos);
+		}
+	}
+}
+
+bool load_raw::deal_with_raw(std::string text_line)
+{
+	//将原始数据文本转成二级制数组
+	if (text_line.find('[') == -1 && text_line != EMPTY_STR)//非时间、非空行,即为原始数据
+	{
+		int pos = -1;
+		int hex = 0;
+		while ((pos = text_line.find(' ', pos + 1)) != -1)
+		{
+			if (pos - 2 >= 0)
+			{
+				string hex_string = "0x";
+				hex_string += text_line.substr(pos - 2, 2);
+				sscanf(hex_string.c_str(),"%x", &hex);
+				raw[raw_length++] = hex;
+			}
+		}
+	}
+}
+

+ 48 - 0
load_raw.h

@@ -0,0 +1,48 @@
+#ifndef __LOAD_BIN_
+#define __LOAD_BIN_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <dirent.h> 
+#include "common_tool.h"
+#include <log.h>
+
+
+
+using namespace std;
+
+#define FILEBUFFER_LENGTH 4096 //4k
+#define EMPTY_STR ""
+
+class load_raw
+{
+public:
+	bool load_folder(string folder_path);
+	bool load_file(string file_path);
+	load_raw();
+	static int m_index;
+	static std::vector<std::string> m_vec_date;
+	static std::string m_date;
+	static bool m_is_history;
+protected:
+private:
+	bool init();
+	bool deal_with_time(string text_line);
+	bool deal_with_raw(string text_line);
+	void listDir(const char *path,vector<string>& vec_file_path);
+	string raw_time;
+	int raw_length = 0;
+	char raw[FILEBUFFER_LENGTH] = { 0 };
+	int m_port;
+	int c_fd;
+};
+
+#endif

+ 5 - 2
loc_message.h

@@ -7,6 +7,7 @@ struct loc_message
     std::shared_ptr<site> m_sit;
     uint64_t m_num_ticks; //tof时间片m_tof或tdoa相对root时间
     uint64_t m_loc_time;
+	uint64_t m_time_tmp;
     uint32_t m_card_id;
     int32_t	 m_card_ct;
     int8_t   m_card_type;
@@ -36,12 +37,13 @@ struct loc_message
 		return m_sit->index();
 	}
 
-    loc_message(std::shared_ptr<site> s,uint64_t num_ticks,uint64_t timestamp,
+    loc_message(std::shared_ptr<site> s,uint64_t num_ticks,uint64_t timestamp,uint64_t time_tmp,
                 uint32_t cardid,int32_t ct,int8_t type,int8_t antid,
                 int16_t rav,float acc,uint16_t sync_ct,uint16_t rssi,uint16_t batstatus)
         :m_sit(s)
         ,m_num_ticks(num_ticks)
         ,m_loc_time(timestamp)
+		,m_time_tmp(time_tmp)
         ,m_card_id(cardid)
         ,m_card_ct(ct)
         ,m_card_type(type)
@@ -85,13 +87,14 @@ struct loc_message
     }
 
     // pdoa定位数据,17
-    loc_message(std::shared_ptr<site> s,uint64_t num_ticks,uint64_t timestamp,
+    loc_message(std::shared_ptr<site> s,uint64_t num_ticks,uint64_t timestamp,uint64_t time_tmp,
                 uint32_t cardid,int32_t ct,int8_t type,int8_t antid,
                 int16_t rav,float acc,uint16_t sync_ct,uint16_t rssi,uint16_t batstatus
                 ,uint8_t _loc_type, uint8_t _dim, double _poa0, double _poa1, double _poa2)
         :m_sit(s)
         ,m_num_ticks(num_ticks)
         ,m_loc_time(timestamp)
+		,m_time_tmp(time_tmp)
         ,m_card_id(cardid)
         ,m_card_ct(ct)
         ,m_card_type(type)

+ 3 - 1
message.h

@@ -107,6 +107,7 @@ struct message_locinfo:task
 {
 	uint64_t m_time_stamp;		// 分站时间戳
 	time_t   m_site_time;		// 分站时间
+	uint64_t m_time_tmp;
 	uint64_t m_tof;				// 卡tof值
 	uint32_t m_site_id;			// 分站号
 	uint32_t m_card_type;		// 卡类型
@@ -115,7 +116,8 @@ struct message_locinfo:task
 	uint8_t  m_batty_status;	//  电池状态
 	uint8_t  m_callinfo;		// 0x80-呼救,0x01-一般呼叫,0x02-紧急呼叫
 	int8_t  m_rav;				// 角速度
-	uint8_t  m_acc;				// 加速度
+	//uint8_t  m_acc;				// 加速度
+	float  m_acc;				// 加速度
 	uint8_t  m_ant_id;			// 天线号
 	uint16_t m_sync_ct;			// 同步序列号,对于pdoa应用,用来保存是否使用原始定位算法参数 
 	int16_t  m_rssi;			// 信号功率强度

+ 9 - 8
module_service/module_call.cpp

@@ -80,25 +80,26 @@ void module_call::to_node_element(rapidjson::Value& out_elemet,
 
 void module_call::run()
 {
+	// 获得pv_anti_collision告警json
+	std::string ac = get_json_anti_collision();
+	if (!ac.empty()) {
+		log_info("send2web: %s", ac.c_str());
+		swsClientMgr.send(JSON_CMD_VALUE_PUSH, ac);
+	}
+
     std::vector<call_card_ptr> arr;
 
     get_all_call_cards(arr);
 
     if(arr.empty())
     {
+		log_info("run_anti_2");
         return ;
     }
     //转发给web
     //swsClientMgr.send(JSON_CMD_VALUE_PUSH, to_call_card_list_json(arr));
 
-	// 获得pv_anti_collision告警json
-    /*
-	std::string ac = get_json_anti_collision();
-    if(!ac.empty()){
-        log_info("send2web: %s", ac.c_str());
-        swsClientMgr.send(JSON_CMD_VALUE_PUSH, ac);
-    }
-	*/
+	
 
     //将呼叫命令发送给标识卡终端
     call_site_map site_map;

+ 1 - 1
module_service/module_traffic_light.cpp

@@ -142,7 +142,7 @@ void traffic_light_group::send_cmd_light(traffic_light_ptr& ptl)
         return;
     } 
 
-    sys::light_state ls(m_group_id, ptl->m_light_id, ptl->m_state, ((m_card_id == 0)?"":tool_other::to_cid(2, m_card_id)));
+    sys::light_state ls(m_group_id, ptl->m_light_id, ptl->m_state, ((m_card_id == 0)?"":tool_other::to_cid(2, m_card_id)), true);
     swsTimerThrd.upt_light_state(ls);
 
     traffic_light_manager::instance()->send_light_data(ptl->m_light_id, DT_LIGHT, ptl->m_state);

+ 1 - 0
module_service/module_traffic_light.h

@@ -19,6 +19,7 @@ struct traffic_light: point{
     std::string m_ip;           // 红绿灯IP
     int m_site_id;              // 控制分站id
     int m_state;                // 红绿灯状态,1-初始值,2-红灯,3-绿灯,4-闪烁
+	int m_state_last = 0;		// 状态有变化,立马更新状态,否则隔30秒再更新一次
     int m_port;                 // 分站控制红绿灯的路数
     int m_phy_light_id;         // 物理灯号,红绿灯正反面共享此灯号
     int m_phy_direction;        // 物理灯朝向,1-正面,0-反面

+ 3 - 3
module_service/module_traffic_light_manager.cpp

@@ -521,7 +521,7 @@ 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();
@@ -596,7 +596,7 @@ void traffic_light_manager::set_manual(light_message& msg)
     if(g != m_unmap_groups.end()){ 
         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);
+                send_light_data(msg.m_light_id, DT_LIGHT, msg.m_light_state);
             }
        }
 
@@ -614,7 +614,7 @@ void traffic_light_manager::cancel_manual(light_message& msg)
         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);
+            send_light_data(it_light->m_light_id, DT_LIGHT, 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);

+ 88 - 57
module_service/module_web.cpp

@@ -7,6 +7,18 @@
 #include "event.h"
 #include "log.h"
 #include "module_traffic_light_manager.h"
+#include "websocket/wsTimerThread.h"
+#include "load_raw.h"
+
+static std::string s_file_path;
+// 只支持记录导入,不补报警等信息。
+void *callback(void* arg)
+{
+	load_raw loader;
+	loader.load_file(s_file_path.c_str());
+	swsTimerThrd.upt_load_history_completed();
+	return NULL;
+}
 
 /*
  * @brief   处理请求端的请求类型,根据不同请求类型调用不同的业务模块处理
@@ -23,63 +35,82 @@
 void module_web::accept( int ID, std::string const& name,
                          sio::message::ptr const& data, bool need_ack, sio::message::list &ack_resp )
 {
-    if(data->get_flag() != sio::message::flag_object)
-    {
-        log_error("web发来的数据不是对象");
-        return;
-    }
-
-    std::string cmd = "";
-    if(!tool_map::try_get_value(cmd, JSON_ROOT_KEY_CMD, data) || cmd.empty())
-    {
-        log_error("web发来的数据cmd字段为空");
-        return;
-    }
-
-    log_info("web发来的数据 cmd=%s", cmd.c_str());
-
-    if(JSON_CMD_VALUE_CLEAR_CARD == cmd)
-    {
-        // 手动升井
-        area_business_person_attendance::handle_up_mine(data);
-    }
-    else if (JSON_CMD_VALUE_REQUEST_ALL_DATA == cmd)
-    {
-        // web登录请求所有信息
-        module_web::instance()->response_login();
-    }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
-    {
-        sio::message::ptr data_value;
-        if(!tool_map::try_get_value(data_value, JSON_ROOT_KEY_DATA, data))
-        {
-            log_error("web发来的 %s 数据data字段格式不对, 不是map",cmd.c_str());
-            return;
-        }
-
-        if(JSON_CMD_VALUE_META_DATA_CHANGED == cmd)///基础数据
-        {
-            module_meta_data_changed::instance()->accept(data_value);
-        }
-        else if(JSON_CMD_VALUE_DEAL_HELP == cmd) // 处理呼救信息
-        {
-            module_call_help::instance()->accept_web_deal_help(data_value);
-        }
-        else if(JSON_CMD_VALUE_CALL_CARD_REQUEST == cmd)//呼叫
-        {
-            module_call::instance()->accept_call(data_value);
-        }
-        else if(JSON_CMD_VALUE_CALL_CARD_CANCEL_REQUEST == cmd)//取消呼叫
-        {
-            module_call::instance()->accept_cancel(data_value);
-        }
-    }
+	try
+	{
+		if (data->get_flag() != sio::message::flag_object)
+		{
+			log_error("web发来的数据不是对象");
+			return;
+		}
+
+		log_info("web_data:%s", data->to_string().c_str());
+
+		std::string cmd = "";
+		if (!tool_map::try_get_value(cmd, JSON_ROOT_KEY_CMD, data) || cmd.empty())
+		{
+			log_error("web发来的数据cmd字段为空");
+			return;
+		}
+
+		log_info("web发来的数据 cmd=%s", cmd.c_str());
+
+		if (JSON_CMD_VALUE_CLEAR_CARD == cmd)
+		{
+			// 手动升井
+			area_business_person_attendance::handle_up_mine(data);
+		}
+		else if (JSON_CMD_VALUE_REQUEST_ALL_DATA == cmd)
+		{
+			// web登录请求所有信息
+			module_web::instance()->response_login();
+		}
+		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 if (JSON_CMD_VALUE_LOAD_HISTORY_REQUEST == cmd) {
+			// 导入历史数据
+			std::map<std::string, sio::message::ptr> mp = data->get_map()[JSON_ROOT_KEY_DATA]->get_map();
+			log_info("[load_history] map's size=%d", mp.size());
+			s_file_path = mp["file_path"]->get_string();
+			pthread_t  tid;
+			pthread_create(&tid, NULL, callback, NULL);    //callback 是一个回调函数
+		}
+		else
+		{
+			sio::message::ptr data_value;
+			if (!tool_map::try_get_value(data_value, JSON_ROOT_KEY_DATA, data))
+			{
+				log_error("web发来的 %s 数据data字段格式不对, 不是map", cmd.c_str());
+				return;
+			}
+
+			if (JSON_CMD_VALUE_META_DATA_CHANGED == cmd)///基础数据
+			{
+				module_meta_data_changed::instance()->accept(data_value);
+			}
+			else if (JSON_CMD_VALUE_DEAL_HELP == cmd) // 处理呼救信息
+			{
+				module_call_help::instance()->accept_web_deal_help(data_value);
+			}
+			else if (JSON_CMD_VALUE_CALL_CARD_REQUEST == cmd)//呼叫
+			{
+				module_call::instance()->accept_call(data_value);
+			}
+			else if (JSON_CMD_VALUE_CALL_CARD_CANCEL_REQUEST == cmd)//取消呼叫
+			{
+				module_call::instance()->accept_cancel(data_value);
+			}
+		}
+	}
+	catch (...)
+	{
+		log_error("web发来的数据data字段格式不对");
+	}
 }
 
 /*

+ 1 - 0
module_service/module_web.h

@@ -49,6 +49,7 @@ public:
         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));  // 红绿灯控制指令
+		MsgFuncList.insert(std::make_pair(JSON_CMD_VALUE_LOAD_HISTORY_REQUEST, &module_web::accept));  // 导入历史文件指令
     }
 
     /// web前端有用户登录时,反馈给web所有信息

+ 31 - 3
net-service.cpp

@@ -20,6 +20,7 @@
 #include "tool_time.h"
 #include "module_service/module_traffic_light_manager.h"
 #include "module_service/module_device_net.h"
+#include "load_raw.h"
 
 net_service::net_service()
 {
@@ -78,6 +79,20 @@ static bool check_message_time(const std::shared_ptr<client> &clt, const std::sh
 
 void net_service::on_message(const std::shared_ptr<client> &clt,const char*data,size_t len)
 {
+	int n_pos = clt->name().find("127.0.0.1");
+	if (n_pos >= 0)
+	{
+		load_raw::m_is_history = true;
+		load_raw::m_index++;
+		if (load_raw::m_vec_date.size() > 0)
+		{
+		}
+	}
+	else
+	{
+		load_raw::m_is_history = false;
+	}
+
 	bool message_handled=true;
 	try
 	{
@@ -205,7 +220,9 @@ void net_service::on_message(const std::shared_ptr<client> &clt,const char*data,
 				break;
             case CHAR_LOCATEDATA_PDOA:
                 {
-                    int32_t site_id = parse_data_anchor_opt(clt, is);
+				uint64_t timetmp = 0;
+                    int32_t site_id = parse_data_anchor_opt(clt, is, timetmp);
+					
                     if(site_id < 0){
                         break;
                     }
@@ -214,7 +231,7 @@ 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);
@@ -255,6 +272,7 @@ void net_service::on_message(const std::shared_ptr<client> &clt,const char*data,
                         float dist = m.m_tof*15.65*2.996*1e-4;
                         m.m_site_id = site_id;  
                         m.m_time_stamp = tstamp;
+						m.m_time_tmp = timetmp;
                         m.m_loc_type = LDT_PDOA;
 						t->m_cmd_code = cmd;
                         t->m_hash_id = m.m_card_id;
@@ -399,6 +417,15 @@ void net_service::on_message(const std::shared_ptr<client> &clt,const char*data,
                     light_ptr->m_rec_time = time(0);
 					
 					// 采集给红绿灯设备发送心跳指令
+					bool state_changed = false;
+					if (light_ptr->m_state != light_ptr->m_state_last)
+					{
+						state_changed = true;
+						light_ptr->m_state_last = light_ptr->m_state;
+					}
+					
+					sys::light_state ls(0, light_ptr->m_light_id, light_ptr->m_state, "0", state_changed);
+					swsTimerThrd.upt_light_state(ls);
 					traffic_light_manager::instance()->send_heart_data(data, len, id);
 					module_device_net::instance()->do_business(clt->name(), light_ptr->m_light_id, light_ptr->m_device_type_id);
                 }
@@ -466,7 +493,7 @@ int32_t net_service::parse_data_anchor(const std::shared_ptr<client>& clt, zistr
 }
 
 // 分站优化协议
-int32_t net_service::parse_data_anchor_opt(const std::shared_ptr<client>& clt, zistream& s)
+int32_t net_service::parse_data_anchor_opt(const std::shared_ptr<client>& clt, zistream& s, uint64_t& time)
 {
     // 分站号,2字节
     uint16_t site_id = 0;
@@ -529,6 +556,7 @@ int32_t net_service::parse_data_anchor_opt(const std::shared_ptr<client>& clt, z
 
 	uint64_t tt = site_time_stamp;
     tt *= 1000;
+	time = tt;
     logn_info(1,"分站数据:site_id=%d, site_ct=%d, time_t=%llu, time=%s, power=%d, device_type=%d, is_net=%d", site_id, site_ct, tt, tool_time::to_str_ex(tt).c_str(), power, site_ptr->m_device_type_id, site_ptr->m_net_device_status);
 
     return site_id;

+ 1 - 1
net-service.h

@@ -32,7 +32,7 @@ struct net_service:service_callback
     void on_connect(const std::shared_ptr<client> &clt);
 
     int32_t parse_data_anchor(const std::shared_ptr<client>& clt, zistream& s);
-    int32_t parse_data_anchor_opt(const std::shared_ptr<client>& clt, zistream& s);
+    int32_t parse_data_anchor_opt(const std::shared_ptr<client>& clt, zistream& s,uint64_t& time);
 	// 网络校时
 	void net_cali_time(const std::shared_ptr<client>& clt);
 	// can校时

+ 142 - 0
tunnel.cpp

@@ -0,0 +1,142 @@
+/**
+* 文件     tunnel.cpp
+* 简述    巷道类的实现
+* 详细信息  
+* 作者   曾敏果; 邮箱:57862207@qq.com
+* 日期     2022-7-14
+*/
+
+#include "tunnel.h"
+tunnel_cell::tunnel_cell(double x, double y, double z)
+{
+	this->x = x;
+	this->y = y;
+	this->z = z;
+}
+
+tunnel_cell::~tunnel_cell()
+{
+
+}
+
+tunnel::tunnel()
+{
+}
+
+//初始化格子列表,由一系列线段按顺序构成巷道的所有路径。
+//自第一条线段的顶点开始,每隔一米为一个格子。
+bool tunnel::init_cells()
+{
+	bool bRet = true;
+	read_lines_from_db();
+	transform_lines_to_cells();
+	return bRet;
+}
+
+//初始化巷道
+bool tunnel::init_tunnel()
+{
+	init_cells();
+}
+
+//通过格子索引号获取格子的具体坐标
+bool tunnel::get_position_by_cell_index(int index, point& pos)
+{
+	bool bRet = true;
+	if (index < 0 || index >= m_vec_cells.size())
+	{
+		bRet = false;
+		return bRet;
+	}
+	pos = point(m_vec_cells[index].x, m_vec_cells[index].y, m_vec_cells[index].z);
+	return bRet;
+}
+
+int tunnel::get_cells_count()
+{
+	return m_vec_cells.size();
+}
+
+//用于将基站坐标映射到对应的格子索引,这样就能通过基站索引加距离来确定当前车辆所在的格子
+int tunnel::get_cell_index_by_position(const point& pos)
+{
+	//取巷道格子中离基站最近的点作为基站的格子号
+	int index = 0;
+	double dist_min = 1000;//
+	for (int i = 0; i < m_vec_cells.size(); i++)
+	{
+		double dist = pos.dist(point(m_vec_cells[i].x, m_vec_cells[i].y, m_vec_cells[i].z));
+		if (dist < dist_min)
+		{
+			dist_min = dist;
+			index = i;
+		}
+	}
+	return index;
+}
+
+tunnel::~tunnel()
+{
+
+}
+
+//从数据库中读取构成整个巷道的所有线段
+bool tunnel::read_lines_from_db()
+{
+	bool ret = true;
+	m_queue_lines.clear();
+
+	std::string sql = "SELECT id, b_x, b_y, b_z, e_x, e_y, e_z FROM dat_tunnel_path_v ORDER BY id ASC;";
+
+	std::string Error;
+	YADB::CDBResultSet DBRes;
+	sDBConnPool.Query(sql.c_str(), DBRes, Error);
+	int nCount = DBRes.GetRecordCount(Error);
+	if (nCount < 1)
+	{
+		log_error("初始化巷道格子集失败");
+		ret = false;
+		return ret;
+	}
+
+	log_info("init_cells. The record count=%ld\n", nCount);
+
+	while (DBRes.GetNextRecod(Error))
+	{
+		double b_x = 0.0;
+		double b_y = 0.0;
+		double b_z = 0.0;
+		double e_x = 0.0;
+		double e_y = 0.0;
+		double e_z = 0.0;
+
+		DBRes.GetField("b_x", b_x, Error);
+		DBRes.GetField("b_y", b_y, Error);
+		DBRes.GetField("b_z", b_z, Error);
+		DBRes.GetField("e_x", e_x, Error);
+		DBRes.GetField("e_y", e_y, Error);
+		DBRes.GetField("e_z", e_z, Error);
+
+		line_v tunnel_line(point(b_x, b_y, b_z), point(e_x, e_y, e_z));
+
+		m_queue_lines.push_back(tunnel_line);
+
+	}
+	return ret;
+}
+
+//将线段队列转换成巷道格子队列
+bool tunnel::transform_lines_to_cells()
+{
+	bool bRet = true;
+	for (auto iter_line = m_queue_lines.begin(); iter_line != m_queue_lines.end(); iter_line++)
+	{
+		std::deque<point> deque_points;
+		iter_line->calc_point_list(deque_points);
+		for (auto iter_point = deque_points.begin(); iter_point != deque_points.end(); iter_point++)
+		{
+			m_vec_cells.push_back(tunnel_cell(iter_point->x, iter_point->y, iter_point->z));
+		}
+	}
+	return bRet;
+}

+ 71 - 0
tunnel.h

@@ -0,0 +1,71 @@
+//头文件保护
+#ifndef TUNNEL_H
+#define TUNNEL_H
+/**
+* 文件     tunnel.h
+* 简述    用于实现以格子为基础元素的巷道定位数据模型
+* 详细信息  
+* 作者   曾敏果; 邮箱:57862207@qq.com
+* 日期     2022-7-14
+*/
+
+#include <deque>
+#include <vector>
+#include <boost/serialization/singleton.hpp>
+#include "point.h"
+#include "line.h"
+#include "db/db_api/CDBSingletonDefine.h"
+#include "db/db_api/CDBResultSet.h"
+
+// 格子类,用于存储定位结果的基本单元
+class tunnel_cell
+{
+public:
+	tunnel_cell(double x, double y, double z);
+	~tunnel_cell();
+	//格子的实际坐标值,用于将格子转换成具体的坐标进行显示
+	double x;
+	double y;
+	double z;
+protected:
+private:
+	
+	//所属基站号,不在任何基站覆盖范围内,id为-1
+	//int reader_id;
+	//距基站的距离,靠近井口方向为正,靠近井底方向为负,若不在任何基站覆盖范围,此变量值无效
+	//double dist;
+};
+
+//巷道类,将巷道分成一个一个的格子,用于存储巷道的格子集合。
+class tunnel
+{
+public:
+	tunnel();
+	~tunnel();
+	//初始化格子列表
+	bool init_cells();
+	//初始化巷道
+	bool init_tunnel();
+	//通过格子索引号获取格子的具体位置
+	bool get_position_by_cell_index(int index, point& pos);
+	//获取总格子数
+	int get_cells_count();
+	//通过坐标来获取其在的格子位置,用于将基站坐标映射到格子索引号
+	int get_cell_index_by_position(const point& pos);
+protected:
+private:
+	//从数据库中读取初始化格子用线段
+	bool read_lines_from_db();
+	//将线段队列转换成格子
+	bool transform_lines_to_cells();
+	// 格子队列 [7/14/2022 zengminguo]
+	std::vector<tunnel_cell> m_vec_cells;
+	//初始化巷道用的线段列表
+	std::deque<line_v> m_queue_lines;
+};
+
+//巷道类单例定义
+typedef boost::serialization::singleton<tunnel> singleton_tunnel;
+#define s_tunnel singleton_tunnel::get_mutable_instance()
+#define s_tunnel_const singleton_tunnel::get_const_instance()
+#endif //#ifndef TUNNEL_H

+ 4 - 0
websocket/constdef.h

@@ -44,6 +44,8 @@
 #define JSON_CMD_VALUE_LIGHTS_CTRL_RESPONSE "lights_ctrl_res"
 #define JSON_CMD_VALUE_HAND_UP_RESPONSE "deal_hand_up_res"
 
+#define JSON_CMD_VALUE_LOAD_HISTORY_REQUEST "load_history"
+
 #define JSON_KEY_ID "id"
 #define JSON_KEY_OP_TYPE "op_type"
 #define JSON_KEY_OP_TYPE_INSERT "INSERT"
@@ -109,6 +111,8 @@
 #define JSON_KEY_CALL_LIGHT_LIGHTS "lights"
 #define JSON_KEY_CALL_LIGHT_ID "id"
 
+#define JSON_KEY_CALL_LOAD_HISTORY_COMPLETED "load_history_completed"
+
 #define JSON_KEY_EDIT_CARD_ID "cardid"
 #define JSON_KEY_EDIT_EDIT_TYPE_ID "edittype"
 

+ 22 - 0
websocket/jsonBuilder.cpp

@@ -877,6 +877,28 @@ namespace sys
         root.Accept(writer);
         return sb.GetString();
     }
+
+	std::string jsonBuilder::build_load_history_completed()
+	{
+		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_LOAD_HISTORY_COMPLETED, root, allocator);
+
+		rapidjson::Value data(rapidjson::kArrayType);
+
+		root.AddMember("data", data, allocator);
+
+		__AddVersion(root, allocator);
+
+		root.Accept(writer);
+		return sb.GetString();
+	}
+
 }
 
 

+ 1 - 0
websocket/jsonBuilder.h

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

+ 60 - 13
websocket/wsTimerThread.cpp

@@ -134,8 +134,8 @@ namespace sys
             return;
         }
         std::vector<light_state> lights = light_state_list;
-        //log_info("[light_info] light_state's size=%d, copy=%d", light_state_list.size(), lights.size());
-        std::string json_light = __jsBuilder.build_traffic_light(lights);
+		//log_info("[light_info] 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.clear();
 		light_state_list.resize(0);
@@ -155,7 +155,17 @@ namespace sys
 		device_state_list.resize(0);
 	}
 
-    /*
+	void wsTimerThread::send_load_history_completed()
+	{
+		if (m_load_history_completed)
+		{
+			m_load_history_completed = false;
+			std::string json_load_history_completed = __jsBuilder.build_load_history_completed();
+			swsClientMgr.send(JSON_CMD_VALUE_PUSH, json_load_history_completed);
+		}
+	}
+
+	/*
      * 定时器线程发送定位数据
      *
      * */
@@ -164,19 +174,50 @@ namespace sys
         log_info("The timer thread is running");
         while ( pOwner->__Enable )
 		{
-			std::time_t t = time( 0 );
-			int seconds = (int)std::difftime( t, __LastSendTime );
+			try
+			{
+				std::time_t t = time(0);
+				int seconds = (int)std::difftime(t, __LastSendTime);
 
-			if ( seconds >= pOwner->__Config.SendInterval )
+				if (seconds >= pOwner->__Config.SendInterval)
+				{
+					pOwner->__SendCardPos();
+					//service_position send
+					//pOwner->send_card_pos();
+					//pOwner->temp_send_card_pos();
+					pOwner->send_light_state();
+					pOwner->send_device_state();
+					pOwner->send_load_history_completed();
+					__LastSendTime = t;
+				}
+				else
+				{
+					//检查红绿灯状态是否更新,如果要更新,立马发送
+					try
+					{
+						if (light_state_list.size() > 0)
+						{
+							for (auto var : light_state_list)
+							{
+								if (var.m_state_changed == true)
+								{
+									pOwner->send_light_state();
+									break;
+								}
+							}
+						}
+					}
+					catch (...)
+					{
+						
+					}
+				}
+			}
+			catch (...)
 			{
-				pOwner->__SendCardPos();
-                //service_position send
-                //pOwner->send_card_pos();
-                //pOwner->temp_send_card_pos();
-                //pOwner->send_light_state();
-				pOwner->send_device_state();
-				__LastSendTime = t;
+				log_info("send2web exception");
 			}
+			
           	boost::this_thread::sleep( boost::posix_time::millisec( 1 ) );
 		}
 
@@ -227,4 +268,10 @@ namespace sys
 	{
 		device_state_list.push_back(ds);
 	}
+
+	void wsTimerThread::upt_load_history_completed()
+	{
+		m_load_history_completed = true;
+	}
+
 }

+ 3 - 0
websocket/wsTimerThread.h

@@ -48,6 +48,7 @@ namespace sys
 		jsonBuilder __jsBuilder;//json构造器类
         std::vector<light_state> light_state_list;		// 红绿灯状态列表
 		std::vector<device_state> device_state_list;	// 设备状态列表
+		bool m_load_history_completed = false;
 	private:
 		/**
 		* @brief
@@ -101,6 +102,7 @@ namespace sys
         void temp_send_card_pos();
         void send_light_state();
 		void send_device_state();
+		void send_load_history_completed();
 
 	protected:
 		/**
@@ -206,6 +208,7 @@ namespace sys
 
         void upt_light_state(const light_state& light);
 		void upt_device_state(const device_state& ds);
+		void upt_load_history_completed();
 	};
 }
 

+ 5 - 3
websocket/ws_common.h

@@ -159,15 +159,17 @@ namespace sys
         int m_light_id;
         int m_light_state;
         std::string m_card_id;
+		bool m_state_changed;		// 状态有变化,立马更新状态,否则隔30秒再更新一次
 
-        light_state(): m_group_id(0), m_light_id(0), m_light_state(0), m_card_id("")
+        light_state(): m_group_id(0), m_light_id(0), m_light_state(0), m_card_id(""), m_state_changed(false)
         {}
 
-        light_state(const int& gid, const int& lid, const int& state, const std::string& cid)
+        light_state(const int& gid, const int& lid, const int& state, const std::string& cid,bool state_changed)
             : m_group_id(gid),
             m_light_id(lid),
             m_light_state(state),
-            m_card_id(cid)
+            m_card_id(cid),
+			m_state_changed(state_changed)
         {}
     };