lixioayao 6 years ago
parent
commit
78db8ce5c7
60 changed files with 4054 additions and 2315 deletions
  1. 36 19
      CMakeLists.txt
  2. 1 1
      CMakeLists.txt.user
  3. 69 3
      Makefile
  4. 6 3
      Makefile.am
  5. 69 3
      Makefile.in
  6. 202 10
      ant.cpp
  7. 125 146
      ant.h
  8. 21 19
      area.cpp
  9. 158 173
      area.h
  10. 111 98
      bindmorecard.h
  11. 431 54
      card.cpp
  12. 46 11
      card.h
  13. 4 2
      cardMgr.cpp
  14. 10 4
      cardMgr.h
  15. 18 0
      common.h
  16. 454 0
      common_tool.h
  17. 46 0
      loc_message.h
  18. 1 0
      loc_point.cpp
  19. 1 1
      loc_tool.h
  20. 13 8
      main.cpp
  21. 21 0
      mine.cpp
  22. 48 0
      mine.h
  23. 0 122
      module_service/module_area.cpp
  24. 128 46
      module_service/module_area.h
  25. 137 0
      module_service/module_area_over_count.h
  26. 0 3
      module_service/module_area_over_speed.cpp
  27. 0 127
      module_service/module_area_over_speed.h
  28. 0 3
      module_service/module_area_overman.cpp
  29. 0 92
      module_service/module_area_overman.h
  30. 0 3
      module_service/module_area_timeout.cpp
  31. 84 60
      module_service/module_area_timeout.h
  32. 0 9
      module_service/module_attendance_person.cpp
  33. 186 77
      module_service/module_attendance_person.h
  34. 0 2
      module_service/module_attendance_vehicle.cpp
  35. 86 30
      module_service/module_attendance_vehicle.h
  36. 160 132
      module_service/module_call.cpp
  37. 284 49
      module_service/module_call.h
  38. 0 8
      module_service/module_call_help.cpp
  39. 80 85
      module_service/module_call_help.h
  40. 0 6
      module_service/module_const.cpp
  41. 22 535
      module_service/module_const.h
  42. 0 2
      module_service/module_mgr.cpp
  43. 87 11
      module_service/module_mgr.h
  44. 44 0
      module_service/module_mine.h
  45. 65 0
      module_service/module_other_alarm.h
  46. 159 0
      module_service/module_over_speed_vehicle.h
  47. 92 0
      module_service/module_site.h
  48. 48 36
      module_service/module_web.cpp
  49. 27 274
      module_service/module_web.h
  50. 8 7
      net-service.cpp
  51. 1 2
      select_tool.h
  52. 16 22
      site_area.cpp
  53. 25 5
      site_area.h
  54. 2 2
      websocket/jsonBuilder.cpp
  55. 1 1
      websocket/jsonBuilder.h
  56. 12 6
      websocket/wsTimerThread.cpp
  57. 2 2
      websocket/wsTimerThread.h
  58. 7 1
      write-copy.h
  59. 108 0
      ya_event.cpp
  60. 292 0
      ya_event.h

+ 36 - 19
CMakeLists.txt

@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 2.8)
 #在项目中显示所有源码
 file(GLOB files_ya-serv ./*.cpp ./*.h ./websocket/* ./db_api/* ./src/* ./src/internal/*
-    ./module_service/*)
+    ./module_service/* ./monkey_car/*)
 add_custom_target(files_ya-serv SOURCES ${files_ya-serv})
 MESSAGE(STATUS "module: ya-serv")
 
@@ -44,35 +44,52 @@ set(SRC_YASL "ant.cpp" "ant.h" "base64.cpp" "base64.h" "card.cpp" "card.h" "cloc
     "websocket/wsClient.h" "websocket/wsClient.cpp"
     "websocket/wsClientMgr.h" "websocket/wsClientMgr.cpp"
     "websocket/wsTimerThread.h" "websocket/wsTimerThread.cpp"
+
+    "monkey_car/monkeycar_area.h" "monkey_car/monkeycar_area.cpp"
+    "monkey_car/monkeycar_bus.h" "monkey_car/monkeycar_bus.cpp"
+    "monkey_car/monkeycar_person.h" "monkey_car/monkeycar_person.cpp"
+    "monkey_car/base_data.h" "monkey_car/fp_path.h"
+    "monkey_car/linear_fit.h" "monkey_car/monkey_fit.h"
+
+    "landmark.h" "landmark.cpp" "area.h" "area.cpp"
+    "site_area.h" "site_area.cpp"
+    "special_area.h" "special_area.cpp"
     )
 
 set(SRC_MODULE
+    "mine.h" "mine.cpp"
+    "ya_event.h" "ya_event.cpp"
+    "common_tool.h"
 
-    "module_service/module_area.h" "module_service/module_area.cpp"
-    "module_service/module_area_over_speed.h" "module_service/module_area_over_speed.cpp"
-    "module_service/module_area_overman.h" "module_service/module_area_overman.cpp"
-    "module_service/module_area_timeout.h" "module_service/module_area_timeout.cpp"
-    "module_service/module_attendance_person.h" "module_service/module_attendance_person.cpp"
-    "module_service/module_attendance_vehicle.h" "module_service/module_attendance_vehicle.cpp"
+    "module_service/module_area.h"
+    "module_service/module_site.h"
+    "module_service/module_area_over_count.h"
+    "module_service/module_area_timeout.h"
+    "module_service/module_attendance_person.h"
+    "module_service/module_attendance_vehicle.h"
     "module_service/module_call.h" "module_service/module_call.cpp"
-    "module_service/module_call_help.cpp" "module_service/module_call_help.h"
-    "module_service/module_const.cpp" "module_service/module_const.h"
-    "module_service/module_web.cpp" "module_service/module_web.h"
-    "module_service/module_mgr.cpp" "module_service/module_mgr.h"
+    "module_service/module_call_help.h"
+    "module_service/module_const.h"
+    "module_service/module_web.h" "module_service/module_web.cpp"
+    "module_service/module_mgr.h"
+
+    "module_service/module_mine.h"
+    "module_service/module_over_speed_vehicle.h"
+    "module_service/module_other_alarm.h"
     )
 
 add_executable(${PROJECT_NAME} "main.cpp" ${SRC_YASL}  ${SRC_MODULE})
 
-target_link_libraries (${PROJECT_NAME}  zlog rt ev boost_system boost_thread mysqlclient)
+target_link_libraries (${PROJECT_NAME}  zlog rt ev boost_chrono boost_system boost_thread mysqlclient)
 
-file(COPY data_reader_antenna.txt DESTINATION ${PROJECT_BINARY_DIR})
-file(COPY path_tof.txt DESTINATION ${PROJECT_BINARY_DIR})
+#file(COPY data_reader_antenna.txt DESTINATION ${PROJECT_BINARY_DIR})
+#file(COPY path_tof.txt DESTINATION ${PROJECT_BINARY_DIR})
 
-file(COPY /root/projection/out/bin/logger DESTINATION ${PROJECT_BINARY_DIR})
-file(COPY /root/projection/out/etc DESTINATION ${PROJECT_SOURCE_DIR})
-file(COPY /root/projection/out/log DESTINATION ${PROJECT_SOURCE_DIR})
-file(COPY /root/projection/out/include/log.h DESTINATION ${PROJECT_SOURCE_DIR})
-file(COPY /root/projection/out/include/config_file.h DESTINATION ${PROJECT_SOURCE_DIR})
+#file(COPY /root/projection/out/bin/logger DESTINATION ${PROJECT_BINARY_DIR})
+#file(COPY /root/projection/out/etc DESTINATION ${PROJECT_SOURCE_DIR})
+#file(COPY /root/projection/out/log DESTINATION ${PROJECT_SOURCE_DIR})
+#file(COPY /root/projection/out/include/log.h DESTINATION ${PROJECT_SOURCE_DIR})
+#file(COPY /root/projection/out/include/config_file.h DESTINATION ${PROJECT_SOURCE_DIR})
 
 
 

+ 1 - 1
CMakeLists.txt.user

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 4.7.0, 2018-09-12T14:57:01. -->
+<!-- Written by QtCreator 4.7.0, 2018-10-11T16:29:55. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>

File diff suppressed because it is too large
+ 69 - 3
Makefile


File diff suppressed because it is too large
+ 6 - 3
Makefile.am


File diff suppressed because it is too large
+ 69 - 3
Makefile.in


+ 202 - 10
ant.cpp

@@ -3,6 +3,7 @@
 #include <string.h>
 #include <math.h>
 #include "ant.h"
+#include "db_api/CDBConnPool.h"
 
 template<> std::shared_ptr<sit_list> 
 single_base<sit_list, int, std::shared_ptr<site>>::m_instance=std::make_shared<sit_list>();
@@ -18,10 +19,6 @@ site::site(int id)
     ,m_path_empty(true)
 {
 
-}
-void site::set_client(std::shared_ptr<client>& clt)
-{
-	m_clt=clt;
 }
 const algo_config&site::config()const
 {
@@ -41,8 +38,8 @@ static int str_split(char*s,char**rc)
 
 	return o-rc;
 }
-
 //1, 101, 1, '101-1', 4727, 75, 0, 0, '2017-08-29 10:21:14'
+/*
 void sit_list::read_sit_list(const char*fname)
 {
 	FILE*fp=fopen(fname,"r");
@@ -85,7 +82,70 @@ void sit_list::read_sit_list(const char*fname)
 	}
 
 	fclose(fp);
+
 }
+*/
+void sit_list::read_sit_list(const char*fname)
+{
+	std::unordered_map<int,std::shared_ptr<site>> map;
+	const char *sql = "SELECT antenna_id, a.reader_id, idx, a.x, a.y, a.z, a.angle \
+						FROM dat_antenna a, dat_reader r \
+						WHERE a.reader_id = r.reader_id;";
+    std::string Error;
+    YADB::CDBResultSet DBRes;
+    sDBConnPool.Query(sql,DBRes,Error);
+    uint64_t nCount = DBRes.GetRecordCount( Error );
+    if (nCount > 0)
+    {
+        log_info( "init_antenna. The record count=%ld\n", nCount );
+
+        while ( DBRes.GetNextRecod(Error) )
+        {
+            int reader_id  = 0;
+            DBRes.GetField( "reader_id",reader_id, Error );
+
+         	int idx=0;
+            DBRes.GetField( "idx",idx, Error );
+
+			int antid = idx-1;
+			if(antid >= 2)
+			  continue;
+
+            double x= 0;
+            DBRes.GetField( "x",x, Error );
+
+            double y= 0;
+            DBRes.GetField( "y",y, Error );
+
+            double z= 0;
+            DBRes.GetField( "z",z, Error );
+
+		   auto site_ptr=sit_list::instance()->get(reader_id);
+            if(nullptr==site_ptr)
+            {
+                site_ptr = std::make_shared<site>(reader_id);
+				map.insert({reader_id,site_ptr});
+            }
+			site_ptr->m_ant[antid].set(x,-y);
+        }
+    }
+	sit_list::instance()->add(map);
+	for(auto&sit_:map)
+	{
+		auto & sit = *(sit_.second);
+		if(sit.m_id==-1)
+			continue;
+
+		if(sit.m_ant[0]==sit.m_ant[1])
+		{
+			log_warn("%d分站天线坐标相等.",sit.m_id);
+		}
+
+		sit.set( (sit.m_ant[0].x+sit.m_ant[1].x)/2,(sit.m_ant[0].y+sit.m_ant[1].y)/2);
+	}
+
+}
+/*
 void sit_list::read_ant_path(const char*fname)
 {
 	FILE*fp=fopen(fname,"r");
@@ -170,16 +230,148 @@ void sit_list::read_ant_path(const char*fname)
         //std_info("%f----%f",s.x,s.y);
 	}
 }
+*/
+void sit_list::read_ant_path(const char*fname)
+{
+	FILE*fp=fopen(fname,"r");
+	char buf[512],*p;
+	int t,id,pid;
+	char* s[20];
+	while((p=fgets(buf,sizeof(buf),fp)))
+	{
+		t=str_split(buf,&s[0]);
+		if(t<9)
+			continue;
+
+		id=atoi(s[0]);
+		auto s_ = sit_list::instance()->get(id);
+		if(s_==nullptr)
+			continue;
 
+		pid=atoi(s[1]);
+		if(pid>2)
+          continue;
+        point p1(atof(s[2]),-atof(s[3]));
+        point p2(atof(s[5]),-atof(s[6]));
+		auto &sit_ = *s_; 
+        if(pid == 0)
+        {
+            line_v l(p1,p2);
+            {
+                point px = l.line::projection(sit_);
+                sit_.set(px);
+                for(int i=0;i<2;i++)
+                {
+                    path p;
+                    p.m_slope[0] = atof(s[8]);
+                    p.m_line[0] = line_v(px,l[i]);
+                    sit_.m_ant[i].m_path.push_back(p);
+                }
+            }
+        }
+        else 
+        {
+            ant &a = pid<0?sit_.m_ant[0]:sit_.m_ant[1];
+            if(a.m_path.size()!=0)
+            {
+                path &p = a.m_path[0];
+                p.m_line[abs(pid)-1] = line_v(p1,p2);
+                p.m_slope[abs(pid)-1] = atof(s[8]);
+            }
+            else
+            {
+                path p;
+                p.m_line[abs(pid)-1] = line_v(p1,p2);
+                p.m_slope[abs(pid)-1] = atof(s[8]);
+                a.m_path.push_back(p);
+            }
+            if(abs(pid)==1)
+				 sit_.set(p1);
+        }
+	}
+	fclose(fp);
 
+	for(auto&_s:sit_list::instance()->m_map)
+	{
+		auto & s = *(_s.second);
+		if(s.m_id==-1)
+			continue;
+        s.swap();
+		if((s.path(0).empty() && s.path(1).empty()))
+			continue;
+        s.m_path_empty=false; 
 
-loc_message::loc_message()
-	 :m_num_ticks(0)
-{
+        for(auto &a:s.m_ant)
+        for(auto &p:a.m_path)
+        {
+            if(!p.m_line[0].empty())
+            {
+                point px = p.m_line[0].line::projection(a);
+                p.m_line[0]=line_v(px,p.m_line[0][1]);
+            }
+        }
+        //std_info("%s",s.to_string().c_str());
+        log_info("%s",s.to_string().c_str());
+        //std_info("%f----%f",s.x,s.y);
+	}
 }
-int loc_message::tool_index()const
+
+
+void sit_list::init_site()
 {
-	return m_sit.index();
+    const char *sql = "SELECT reader_id, reader_type_id, dat_reader.map_id, \
+            area_id, device_type_id, dimension, dat_map.scale\
+            FROM dat_reader, dat_map where \
+            dat_reader.map_id=dat_map.map_id and state=0;";
+
+    std::string Error;
+    YADB::CDBResultSet DBRes;
+    sDBConnPool.Query(sql,DBRes,Error);
+    uint64_t nCount = DBRes.GetRecordCount( Error );
+    if (nCount > 0)
+    {
+        log_info( "init_site. The record count=%ld\n", nCount );
+
+        while ( DBRes.GetNextRecod(Error) )
+        {
+            int reader_id  = 0;
+            DBRes.GetField( "reader_id",reader_id, Error );
+
+            auto site_ptr=sit_list::instance()->get(reader_id);
+            if(nullptr==site_ptr)
+            {
+                site_ptr = std::make_shared<site>(reader_id);
+                sit_list::instance()->add(reader_id,site_ptr);
+            }
+
+            int reader_type_id  = 0;
+            DBRes.GetField( "reader_type_id",reader_type_id, Error );
+
+            int map_id  = 0;
+            DBRes.GetField( "map_id",map_id, Error );
+
+            int area_id  = 0;
+            DBRes.GetField( "area_id",area_id, Error );
+
+            int device_type_id  = 0;
+            DBRes.GetField( "device_type_id",device_type_id, Error );
+
+            int dimension  = 0;
+            DBRes.GetField( "dimension",dimension, Error );
+
+            double scale= 0;
+            DBRes.GetField( "scale",scale, Error );
+
+            site_ptr->m_reader_type_id = reader_type_id;
+            site_ptr->m_map_id = map_id;
+            site_ptr->m_area_id = area_id;
+
+            site_ptr->m_device_type_id = device_type_id;
+
+            site_ptr->m_dimension = dimension;
+            site_ptr->m_scale = scale;
+        }
+    }
 }
 
 algo_config site::g_config[]=

+ 125 - 146
ant.h

@@ -13,9 +13,11 @@
 #include "point.h"
 #include "write-copy.h"
 class client;
+#include"net-service.h"
+#include"common.h"
 struct path
 {
-    std::array<line_v,2>	m_line; 
+    std::array<line_v,2>	m_line;
     std::array<double,2>    m_slope;
     path()
     {
@@ -39,25 +41,25 @@ struct path
     {
         return m_line[i];
     }
-    const line_v & operator[](int i) const 
+    const line_v & operator[](int i) const
     {
         return m_line[i];
     }
-   
+
 };
 //?
 struct algo_config
 {
-	const char*desc;
-	int min_msg_cnt;
-	int best_msg_cnt;
-	double min_wait_time;
-	double max_wait_time;
+    const char*desc;
+    int min_msg_cnt;
+    int best_msg_cnt;
+    double min_wait_time;
+    double max_wait_time;
 };
 //
 struct ant :point
 {
-	std::vector<path> m_path;
+    std::vector<path> m_path;
     path & operator[](int i)
     {
         return m_path[i];
@@ -79,7 +81,7 @@ struct ant :point
             if(p.vaild())
             {
                 point pt;
-                if(dist <= p.m_line[0].length() || (dist > p.m_line[0].length() && p.m_line[1].empty()))        
+                if(dist <= p.m_line[0].length() || (dist > p.m_line[0].length() && p.m_line[1].empty()))
                 {
                     d += d*p.m_slope[0];
                     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());
@@ -94,55 +96,65 @@ struct ant :point
                 //std_info("get_sol:x:%.2f,y:%.2f",pt.x,pt.y);
             }
             else
-                std_error("%s","ant::getsol empty path..");
+                std_error(".%s","ant::getsol empty path..");
         }
         return std::move(v);
     }
 
 };
 
-/**
- * @brief 分站位置 1井上,2井下
- */
-enum UP_DOWN_SITE
-{
-    ///井上分站
-    UP_SITE=1,
-    ///井下分站
-    DOWN_SITE=2
-};
-
 struct site:point
 {
-	static algo_config g_config[];
-	int      m_algo;			//TOF:0,TDOA:1
-	int      m_num_dims;	    //1维:0,2维:1,3维:2
+    static algo_config g_config[];
+    int      m_algo;			//TOF:0,TDOA:1
+    int      m_num_dims;	    //1维:0,2维:1,3维:2
     double  m_scale = 2.0;  // 地图比例尺
 
-	point    m_position;
-	int index()const;
-	const algo_config&config()const;
-	int id()const
-	{
-		return m_id;
-	}
-	site(int id=-1);
+    point    m_position;
+    int index()const;
+    const algo_config&config()const;
+    int id()const
+    {
+        return m_id;
+    }
+    site(int id=-1);
+
+    mutable double m_height=1.5;
+    int m_id;
+    bool m_path_empty;
+    std::array<ant,2> m_ant;
 
-	mutable double m_height=1.5;
-	int m_id;
-	bool m_path_empty;
-	std::array<ant,2> m_ant;
+    mutable double m_ant_dist=0;
+    mutable double m_ant_dist_sum_new=0;
+    mutable int m_ant_dist_cnt_new=0;
 
-	mutable double m_ant_dist=0;
-	mutable double m_ant_dist_sum_new=0;
-	mutable int m_ant_dist_cnt_new=0;
+    ///分站位置 READER_TYPE_ID
+    int m_reader_type_id = 0;
+    int m_map_id = 0;
+    int m_area_id = 0;
 
-    ///分站位置 UP_DOWN_SITE
-    int m_up_down;
-	std::shared_ptr<client> m_clt=nullptr;
-	void set_client(std::shared_ptr<client>& clt);
+    /// 设备类型,分站、通信分站、交通灯等
+    int m_device_type_id=0;
+
+    /// 指定分站定位类型:一维定位,二维定位,三维定位
+    int m_dimension=0;
+
+    std::shared_ptr<client> m_clt=nullptr;
+    void set_client(std::shared_ptr<client>& clt)
+    {
+        m_clt = clt;
+    }
+
+    std::shared_ptr<client> get_client()
+    {
+        return m_clt;
+    }
 
-    point get_dstp(const point pt) const 
+     bool is_up_site()
+    {
+        return READER_TYPE_ID_UP == m_reader_type_id;
+    }
+    point get_dstp(const point pt) const
     {
         point tmp;
         for(const auto & p : m_ant[0].m_path)
@@ -154,9 +166,9 @@ struct site:point
                     if(p[i].contain(pt,0.01))
                     {
                         //if(i==0)
-                         // return *this;
+                        // return *this;
                         //else
-                          tmp = p[i][0];
+                        tmp = p[i][0];
                     }
                 }
             }
@@ -164,51 +176,51 @@ struct site:point
         return tmp;
     }
 
-	void count_ant_dist(double dist_tof1, double dist_tof2)const
-	{
-		if(dist_tof1<10 || dist_tof2<10)
-			return;
-		double dist = fabs(dist_tof1 - dist_tof2);
-		if(dist>5)
-			return;
-		m_ant_dist_sum_new += dist;
-		m_ant_dist_cnt_new++;
-		
-		if(m_ant_dist_cnt_new >= 2500)
-		{
-			m_ant_dist = m_ant_dist_sum_new / m_ant_dist_cnt_new;
-			m_ant_dist_sum_new = 0;
-			m_ant_dist_cnt_new = 0;
-		}
-	}
+    void count_ant_dist(double dist_tof1, double dist_tof2)const
+    {
+        if(dist_tof1<10 || dist_tof2<10)
+            return;
+        double dist = fabs(dist_tof1 - dist_tof2);
+        if(dist>5)
+            return;
+        m_ant_dist_sum_new += dist;
+        m_ant_dist_cnt_new++;
+
+        if(m_ant_dist_cnt_new >= 2500)
+        {
+            m_ant_dist = m_ant_dist_sum_new / m_ant_dist_cnt_new;
+            m_ant_dist_sum_new = 0;
+            m_ant_dist_cnt_new = 0;
+        }
+    }
     void swap()
     {
-       auto v0 =  m_ant[0].m_path;
-       auto v1 =  m_ant[1].m_path;
-       std::copy (std::begin(v0),std::end(v0),std::back_inserter(m_ant[1].m_path));
-       std::copy (std::begin(v1),std::end(v1),std::back_inserter(m_ant[0].m_path));
+        auto v0 =  m_ant[0].m_path;
+        auto v1 =  m_ant[1].m_path;
+        std::copy (std::begin(v0),std::end(v0),std::back_inserter(m_ant[1].m_path));
+        std::copy (std::begin(v1),std::end(v1),std::back_inserter(m_ant[0].m_path));
+    }
+    double ant_dist()const
+    {
+        return m_ant[0].dist(m_ant[1]);
     }
-	double ant_dist()const
-	{
-		return m_ant[0].dist(m_ant[1]);
-	}
-	
-	bool is_path_empty()const
-	{
+
+    bool is_path_empty()const
+    {
         return m_path_empty;
-	}
+    }
 
-	bool have_valid_path()const
-	{
+    bool have_valid_path()const
+    {
         return m_id != -1 && ant_dist() > 0.1;
-	}
+    }
 
-	std::string to_string()const
-	{
+    std::string to_string()const
+    {
         std::stringstream ss;
         ss<<"site_id:"<<m_id<<"x:"<<x<<" y: "<<y<<" scale:"<<m_scale;
         for(const auto a:m_ant)
-        {  
+        {
             ss<<"<";
             for(const auto p:a.m_path)
             {
@@ -217,33 +229,33 @@ struct site:point
             ss<<">";
         }
         return ss.str();
-	}
+    }
 
-	const point&path(int i)const
-	{
+    const point&path(int i)const
+    {
         static point p;
         if(i>=(int)m_ant[0].m_path.size())
             return p ;
-		return m_ant[0].m_path[i].m_line[0][1];
-	}
+        return m_ant[0].m_path[i].m_line[0][1];
+    }
 
     std::vector<point> solving(int ant_id, double dist)const
-	{
+    {
         const ant &a = m_ant[ant_id];
         if(dist<50 && dist>0)
-		{
-			if(dist<m_height)
-			{
-				m_height=dist;
-				dist=0;				
-			}
-			else
-			{
-				dist=sqrt(dist*dist-m_height*m_height);
-			}
-		}
+        {
+            if(dist<m_height)
+            {
+                m_height=dist;
+                dist=0;
+            }
+            else
+            {
+                dist=sqrt(dist*dist-m_height*m_height);
+            }
+        }
         return std::move(a.getsol(dist));
-   	}
+    }
     ant operator[](int i)
     {
         return m_ant[i];
@@ -257,54 +269,21 @@ struct site:point
 
 struct sit_list:single_base<sit_list,int,std::shared_ptr<site>>
 {
-	void load(const char*ant_file,const char*path_file)
-	{
-		read_sit_list(ant_file);
-		read_ant_path(path_file);
-	}
-
-	void load_from_db()
-	{
-		load("data_reader_antenna.txt","path_tof.txt");
-	}
-
-	void read_sit_list(const char*fname);
-	void read_ant_path(const char*fname);
-};
-
-struct loc_message
-{
-	site     m_sit;
-	uint64_t m_num_ticks; //tof时间片m_tof或tdoa相对root时间
-	uint64_t m_loc_time;
-	uint32_t m_card_id;
-	int32_t	 m_card_ct;
-	int8_t   m_card_type;
-	int8_t   m_ant_id;
-	int16_t  m_rav;
-	int16_t  m_acc;
-	uint16_t m_sync_ct;
-	uint16_t m_rssi;
+    void load(const char*ant_file,const char*path_file)
+    {
+        read_sit_list(ant_file);
+        read_ant_path(path_file);
+    }
 
+    void load_from_db()
+    {
+        load("data_reader_antenna.txt","path_tof.txt");
+        init_site();
+    }
 
-	loc_message();
-	loc_message(site s,uint64_t num_ticks,uint64_t timestamp,
-			uint32_t cardid,int32_t ct,int8_t type,int8_t antid,	
-			int16_t rav,int16_t acc,uint16_t sync_ct,uint16_t rssi)
-		:m_sit(s)
-		 ,m_num_ticks(num_ticks)
-         ,m_loc_time(timestamp)
-        ,m_card_id(cardid)
-        ,m_card_ct(ct)
-        ,m_card_type(type)
-        ,m_ant_id(antid)
-        ,m_rav(rav)
-        ,m_acc(acc)
-        ,m_sync_ct(sync_ct)
-        ,m_rssi(rssi)
-	{}
-	int tool_index()const;
+    void read_sit_list(const char*fname);
+    void read_ant_path(const char*fname);
+    void init_site();
 };
-
 #endif
 

+ 21 - 19
area.cpp

@@ -11,37 +11,34 @@
 #include <boost/algorithm/string/split.hpp>
 #include <boost/algorithm/string/classification.hpp>
 
+#include"module_service/module_area.h"
+
 template<> std::shared_ptr<area_list> 
 single_base<area_list, int, std::shared_ptr<area>>::m_instance=std::make_shared<area_list>();
 
-void area::on_hover(int64_t card_id,std::shared_ptr<area_hover>&c,double speed,uint64_t type)
+void area::on_hover(uint32_t card_id,std::shared_ptr<area_hover>&c,double speed,int32_t type)
  {
  	//check超时
 	log_info("on_hover..%d  areaId:%d",card_id,m_id);
- 	time_t now = time(NULL);
- 	if(now-c->m_enter_time>m_limit_time_second && !c->m_is_over_time)
- 	{
- 		c->m_is_over_time=true;
- 		//产生告警
- 	}
+// 	time_t now = time(NULL);
+// 	if(now-c->m_enter_time>m_limit_time_second && !c->m_is_over_time)
+// 	{
+// 		c->m_is_over_time=true;
+// 		//产生告警
+// 	}
+    module_area::on_hover(card_id,c,type);
  }
 
-void area::on_enter(int64_t card_id,std::shared_ptr<area_hover>&c,double speed,uint64_t type)
+void area::on_enter(uint32_t card_id,std::shared_ptr<area_hover>&c,double speed,int32_t type)
 {
 	log_info("on_enter..%d  areaId:%d",card_id,m_id);
-	//入库 : 进入区域
-	//check超员
+    module_area::on_enter(card_id,c,type);
 }
 
-void area::on_leave(int64_t card_id,std::shared_ptr<area_hover>&c,double speed,uint64_t type)
+void area::on_leave(uint32_t card_id,std::shared_ptr<area_hover>&c,double speed,int32_t type)
 {
 	log_info("on_leave..%d  areaId:%d",card_id,m_id);
-	//入库 : 出 区域
-	//check 超员
-	if(c->m_is_over_time)
-	{
-		//取消告警
-	}
+    module_area::on_leave(card_id,c,type);
 }
 bool area::in_area(const point & p)
 {
@@ -74,6 +71,7 @@ bool area::in_area(const point & p)
 area_list::area_list()
 {
 }
+
 void area_list::init_monkeycar_area()
 {
 	std::unordered_map<int,std::shared_ptr<area>> map;
@@ -195,7 +193,11 @@ void area_list::init_from_db()
 
 			log_info("init_area : id:%d,path:%s",area_id, path.c_str());
 			
-			std::shared_ptr<area> ap = std::make_shared<area>(area_id,over_count_person,over_time_person,scale,map_id,area_type_id);
+            std::shared_ptr<area> ap = std::make_shared<area>(area_id,over_count_person,over_time_person,scale,map_id,area_type_id);
+
+            ap->m_limit_vehicle_second = over_time_vehicle;
+            ap->m_limit_vehicle_count = over_count_vehicle;
+
 			ap->m_bound=init_path(path);
 			for(const auto &p : ap->m_bound)
 			  log_info("point:area_id:%d--x:%.2f,y:%.2f",area_id,p.x,p.y);
@@ -243,7 +245,7 @@ std::shared_ptr<area> area_list::get_area(const point&pt)
 }
 
 
-void area_tool::on_point(int64_t card_id,const point&pt,double speed,int16_t type)
+void area_tool::on_point(uint32_t card_id,const point&pt,double speed,int16_t type)
 {
 	log_info("on_point...cardid:%d,type:%d",card_id,type);
 	//获取地标信息

+ 158 - 173
area.h

@@ -7,207 +7,192 @@
 #include <point.h>
 #include "common.h"
 #include <write-copy.h>
-//下午查看代码,整理了一下思路,如下
-//普通区域和考勤区域就不分开了,使用同一个具现类,至于里面的操作,是否区域告警之类的可以通过数据库配置进行控制,比如超员可以查看超员配置是否为0,0则不会进行告警
-//其他区域 井上和井下 考勤区域则不在区域模块进行考虑
-//猴车区域拥有一般区域的行为,所以打算通过继承方式
-//区域超速win版本有实现,没有应用,统一是井下超速,这里待讨论
-//区域超员win版本是通过一个线程循环来进行判断的。这里我觉着可以不采用
-//区域超时win版本的确是当有点过来的时候才会进行判断。这里需讨论是否满足需求,即丢失信号,是否进行告警判断
-//告警对象:分井下 卡  分站 区域 ,不同的告警对象下分不同的告警类型,告警类型分人和车(win版本设计)。
-//考虑到业务需要,以及重叠区域,之前(志军哥)的代码设计可能不使用。至于以后是否考虑重叠区域,后续可以有需求再处理。
-//代码中有对通过坐标点找不到区域的逻辑,使用的是分站注册时候的区域id,这块是否沿用之前思路。
-//益俊那边的json组装需尽快提供
-//月腾那边的区域代码逻辑尽快完善,这边可能需要在你代码实现的基础上进行操作,框架可以先给我
-//区域超员,超时,人车阈值win版本不同,这里需讨论
-//区域进出,插入的数据库表,人车分离。
-
 struct area_hover;
 struct point;
 
 struct area
 {
-	area(int id,int limit_count_person, int limit_time_person,double scale,int32_t mapid,int32_t type)
-		:m_id(id)
-		,m_area_type(type)
-		,m_limit_time_second(limit_time_person)
-		,m_limit_person_count(limit_count_person)
-		,m_scale(scale)
-		,m_mapid(mapid)
-	{
-	}
-
-    virtual void on_hover(int64_t card_id,std::shared_ptr<area_hover>&c,double speed,uint64_t type);
-    virtual void on_enter(int64_t card_id,std::shared_ptr<area_hover>&c,double speed,uint64_t type);
-    virtual void on_leave(int64_t card_id,std::shared_ptr<area_hover>&c,double speed,uint64_t type);
-	bool in_area(const point & p);
-	int id()const
-	{
-		return m_id;
-	}
-	int mapid()const
-	{
-		return m_mapid;
-	}
-	double scale()const
-	{
-		return m_scale;
-	}
-	bool special()const
-	{
-		return m_area_type == AREA_TYPE_NO_COVER;
-	}
-	virtual ~area()
-	{}
-	std::vector<point> m_bound;
-private:
-	std::atomic<int> m_card_count;
-	int32_t    m_id;
+    area(int id,int limit_count_person, int limit_time_person,double scale,int32_t mapid,int32_t type)
+        :m_id(id)
+        ,m_area_type(type)
+        ,m_limit_person_second(limit_time_person)
+        ,m_limit_person_count(limit_count_person)
+        ,m_scale(scale)
+        ,m_mapid(mapid)
+        ,m_person_count(0)
+        ,m_vehicle_count(0)
+    {
+    }
 
+    virtual void on_hover(uint32_t card_id,std::shared_ptr<area_hover>&c,double speed,int32_t type);
+    virtual void on_enter(uint32_t card_id,std::shared_ptr<area_hover>&c,double speed,int32_t type);
+    virtual void on_leave(uint32_t card_id,std::shared_ptr<area_hover>&c,double speed,int32_t type);
+    bool in_area(const point & p);
+    int id()const
+    {
+        return m_id;
+    }
+    int mapid()const
+    {
+        return m_mapid;
+    }
+    double scale()const
+    {
+        return m_scale;
+    }
+    bool special()const
+    {
+        return m_area_type == AREA_TYPE_NO_COVER;
+    }
+    virtual ~area()
+    {}
+    ///区域卡数
+    int card_count()const
+    {
+        return m_person_count + m_vehicle_count;
+    }
+
+    std::vector<point> m_bound;
+public:
+    //std::atomic<int> m_card_count;
+    int    m_id;
     ///区域类型  AREA_TYPE
-    int32_t m_area_type;
+    int m_area_type;
+
+    int m_limit_person_second;
+    int m_limit_person_count;
+
+    int m_limit_vehicle_second;
+    int m_limit_vehicle_count;
+    double m_scale;
+    int32_t m_mapid;
 
-    
     ///区域人卡数
     std::atomic<int> m_person_count;
     ///区域车卡数
     std::atomic<int> m_vehicle_count;
-    std::atomic<bool> m_is_over_person;
-
-    ///区域超时门限
-    int m_limit_time_second;
-    ///人数门限
-    int m_limit_person_count;
-    ///速度门限
-    double m_limit_speed;
-
-	double m_scale;
-	int32_t m_mapid;
 };
 
 struct area_list:single_base<area_list,int,std::shared_ptr<area>>
 {
-	area_list();
+    area_list();
 
-	std::shared_ptr<area> get_area(const point&pt);
-	std::vector<point> init_path(std::string  &str);
-	void init_from_db();
-	void init_monkeycar_area();
+    std::shared_ptr<area> get_area(const point&pt);
+    std::vector<point> init_path(std::string  &str);
+    void init_from_db();
+    void init_monkeycar_area();
 };
 
 struct area_hover
 {
-	std::shared_ptr<area>  m_area;
+    std::shared_ptr<area>  m_area;
     time_t m_enter_time,m_last_time;
-	point  m_enter_point,m_last_point;
-	int    m_num_speeding;
-	bool   m_is_over_time;
-
-	int landmark_id;
-	int landmark_dir;
-	double landmark_dis;
-  	area_hover()=default;
-	area_hover(std::shared_ptr<area>&area,const point&pt,double speed)
-		:m_area(area)
-	{
-		m_enter_time=m_last_time=time(0);
-		m_enter_point=m_last_point=pt;
-		m_num_speeding=0;
-		landmark_id=0;
-		landmark_dir=0;
-		landmark_dis=0;
-	}
-
-	int id()const
-	{
-		return m_area->id();
-	}
-	int mapid()const
-	{
-		return m_area->mapid();
-	}
-	double scale()const
-	{
-		return m_area->scale();
-	}
-	bool operator == (const area_hover&o)const
-	{
-		return m_area->id()==o.m_area->id();
-	}
-
-	bool operator < (const area_hover&o)const
-	{
-		return m_area->id()<o.m_area->id();
-	}
-	std::tuple<time_t,time_t,int,int,int,int,double> getLandmark()
-	{
-		return std::make_tuple(m_enter_time,m_last_time,mapid(),id(),landmark_id,landmark_dir,landmark_dis);
-	}
-	void setLandmark(const point &pt);
-	void set(const point&pt)
-	{
-		m_last_time=time(0);
-		m_last_point = pt;
-	}
+    point  m_enter_point,m_last_point;
+
+    int landmark_id;
+    int landmark_dir;
+    double landmark_dis;
+    area_hover()=default;
+    area_hover(std::shared_ptr<area>&area,const point&pt,double speed)
+        :m_area(area)
+    {
+        m_enter_time=m_last_time=time(0);
+        m_enter_point=m_last_point=pt;
+        landmark_id=0;
+        landmark_dir=0;
+        landmark_dis=0;
+    }
+
+    int id()const
+    {
+        return m_area->id();
+    }
+    int mapid()const
+    {
+        return m_area->mapid();
+    }
+    double scale()const
+    {
+        return m_area->scale();
+    }
+    bool operator == (const area_hover&o)const
+    {
+        return m_area->id()==o.m_area->id();
+    }
+
+    bool operator < (const area_hover&o)const
+    {
+        return m_area->id()<o.m_area->id();
+    }
+    std::tuple<time_t,time_t,int,int,int,int,double> getLandmark()
+    {
+        return std::make_tuple(m_enter_time,m_last_time,mapid(),id(),landmark_id,landmark_dir,landmark_dis);
+    }
+    void setLandmark(const point &pt);
+    void set(const point&pt)
+    {
+        m_last_time=time(0);
+        m_last_point = pt;
+    }
 };
 
 //每张卡包含一个对象
 //在解析出数据点时,调用on_point
 struct area_tool
 {
-	std::shared_ptr<area_hover> m_area_hover=nullptr;
-	void on_point(int64_t card_id,const point&pt,double speed,int16_t type);
-	void setLandmark(const point &pt)
-	{
-		if(m_area_hover)
-		{
-			m_area_hover->setLandmark(pt);
-		}
-	}
-	//special area or no area att.,return true;else return false.
-	bool special_area()
-	{
-		if(m_area_hover==nullptr)
-		  return true;
-		return m_area_hover->m_area->special();
-	}
-	std::tuple<time_t,time_t,int,int,int,int,double> getLandmark()
-	{
-		if(m_area_hover)
-			return m_area_hover->getLandmark();
-		else
-		  return std::make_tuple(0,0,0,0,0,0,0);
-		
-	}
-	//检测是否超时
-	void on_timer(int64_t card_id)
-	{
-
-	}
-
-	void do_hover_biz(int64_t card_id,double speed,int16_t type)
-    {
-		m_area_hover->m_area->on_hover(card_id,m_area_hover,speed,type);
-	}
-
-	void do_enter_biz(int64_t card_id,double speed,int16_t type)
-	{
-		m_area_hover->m_area->on_enter(card_id,m_area_hover,speed,type);
-	}
-
-	void do_leave_biz(int64_t card_id,double speed,int16_t type)
-	{
-		m_area_hover->m_area->on_leave(card_id,m_area_hover,speed,type);
-	}
-
-	void change_area(int64_t card_id,double speed,int16_t type,int32_t new_areaid)
-	{
-		do_leave_biz(card_id,speed,type);
-		auto area = area_list::instance()->get(new_areaid);
-		point pt;
-		m_area_hover.reset(new area_hover(area,pt,speed));
-		do_enter_biz(card_id,speed,type);
-	}
+    std::shared_ptr<area_hover> m_area_hover=nullptr;
+    void on_point(uint32_t card_id,const point&pt,double speed,int16_t type);
+    void setLandmark(const point &pt)
+    {
+        if(m_area_hover)
+        {
+            m_area_hover->setLandmark(pt);
+        }
+    }
+    //special area or no area att.,return true;else return false.
+    bool special_area()
+    {
+        if(m_area_hover==nullptr)
+            return true;
+        return m_area_hover->m_area->special();
+    }
+    std::tuple<time_t,time_t,int,int,int,int,double> getLandmark()
+    {
+        if(m_area_hover)
+            return m_area_hover->getLandmark();
+        else
+            return std::make_tuple(0,0,0,0,0,0,0);
+
+    }
+    //检测是否超时
+    void on_timer(int64_t card_id)
+    {
+
+    }
+
+    void do_hover_biz(uint32_t card_id,double speed,int16_t type)
+    {
+        m_area_hover->m_area->on_hover(card_id,m_area_hover,speed,type);
+    }
+
+    void do_enter_biz(uint32_t card_id,double speed,int16_t type)
+    {
+        m_area_hover->m_area->on_enter(card_id,m_area_hover,speed,type);
+    }
+
+    void do_leave_biz(uint32_t card_id,double speed,int16_t type)
+    {
+        m_area_hover->m_area->on_leave(card_id,m_area_hover,speed,type);
+    }
+
+    void change_area(uint32_t card_id,double speed,int16_t type,int32_t new_areaid)
+    {
+        do_leave_biz(card_id,speed,type);
+        auto area = area_list::instance()->get(new_areaid);
+        point pt;
+        m_area_hover.reset(new area_hover(area,pt,speed));
+        do_enter_biz(card_id,speed,type);
+    }
 };
 
 #endif

+ 111 - 98
bindmorecard.h

@@ -9,46 +9,58 @@
 #include <mutex>
 #include <sstream>
 #include <map>
+#include <functional>
 #include "card.h"
 #include "zlist.h"
 #include "cardMgr.h"
 #include "log.h"
+
 #define TIME_WIN_MILLISEC (15*60*1000)
 #define TIME_LIM_SEC	  (3*1000)
+struct MyHash
+{
+	typedef uint64_t result_type;
+	result_type operator ()(uint64_t c1,uint64_t c2) const
+	{
+		std::string s = std::to_string(c1) + std::to_string(c2);
+		result_type st1 = std::hash<std::string>{}(s);
+		return st1;
+	}
+};
 struct Data
 {
-    Data(uint64_t ct)
-    {
+	Data(uint64_t ct)
+	{
 		reset();
 		m_timestamp = ct;
-    }
-    void reset()
-    {
-        m_index = 0;
-        m_ct.fill(0);
-        m_totaldistance = 0;
+	}
+	void reset()
+	{
+		m_index = 0;
+		m_ct.fill(0);
+		m_totaldistance = 0;
 		m_flag = false;
-    }
-    void increase(const int index)
-    {
-        m_ct[index]++;
-    }
-    uint32_t m_index;
-    std::array<uint16_t,2> m_ct;
-    double   m_totaldistance;
+	}
+	void increase(const int index)
+	{
+		m_ct[index]++;
+	}
+	uint32_t m_index;
+	std::array<uint16_t,2> m_ct;
+	double   m_totaldistance;
 	uint64_t m_timestamp;
 	bool m_flag;
 };
 
 struct TcardInterface
 {
-   // TcardInterface()=default;
-    TcardInterface(std::pair<uint64_t,uint64_t> sp,uint64_t ct,uint64_t owner,int size)
-        :m_cardid(sp)
-        ,m_timestamp(ct)
-		,m_owner(owner)
-		,SIZE(size)
-    {}
+	// TcardInterface()=default;
+	TcardInterface(std::pair<uint64_t,uint64_t> sp,uint64_t ct,uint64_t owner,int size)
+		:m_cardid(sp)
+		 ,m_timestamp(ct)
+		 ,m_owner(owner)
+		 ,SIZE(size)
+	{}
 
 	std::tuple<bool,std::string> setindex(uint64_t tsp,const uint64_t cid,const double d=0,bool ctflag =false)
 	{
@@ -59,9 +71,10 @@ struct TcardInterface
 
 
 		if (empty())
-			grow(tsp);
+		  grow(tsp);
 		uint64_t tmp_tsp_min = back(0).m_timestamp;
 		uint64_t tmp_tsp_max = back(0).m_timestamp + TIME_WIN_MILLISEC;
+		log_info("setindex:%lld,%lld",tsp,tmp_tsp_min);
 		assert(tsp >= tmp_tsp_min);
 
 		do
@@ -104,19 +117,19 @@ struct TcardInterface
 
 	std::tuple<bool,std::string> checkLast()
 	{
-//		std::tuple<bool,std::string> stp(false,std::string(""));
-//		if (!timeout() && size()>=ConfStruct::getCs().remote_slot)
-//		{
-//			auto tp = get();
-//			stp = check(std::get<0>(tp),std::get<1>(tp));
-//		}
-//		return stp;
+		//		std::tuple<bool,std::string> stp(false,std::string(""));
+		//		if (!timeout() && size()>=ConfStruct::getCs().remote_slot)
+		//		{
+		//			auto tp = get();
+		//			stp = check(std::get<0>(tp),std::get<1>(tp));
+		//		}
+		//		return stp;
 		return std::make_tuple(false,"");
 	}
 	void skip(int count)
 	{
 		for(int i =0;i<count&&i<size();i++)
-			m_arr.pop_front();
+		  m_arr.pop_front();
 	}
 	bool empty()
 	{
@@ -153,13 +166,13 @@ struct TcardInterface
 		std::stringstream ss;
 		ss<<m_cardid.first<<"&"<<m_cardid.second<<","<<m_arr[0].m_timestamp/1000<<","<<(back(0).m_timestamp+TIME_WIN_MILLISEC)/1000 <<",";
 		std::for_each(m_arr.begin(),m_arr.end(),[&ss](Data& d){
-			if (!d.m_flag)
-			{
-				ss<<d.m_timestamp/1000<<"&"<<d.m_totaldistance<<"&"<<d.m_index<<",";
-				d.m_flag = true;
-			}
-			
-		});
+					if (!d.m_flag)
+					{
+					ss<<d.m_timestamp/1000<<"&"<<d.m_totaldistance<<"&"<<d.m_index<<",";
+					d.m_flag = true;
+					}
+
+					});
 		return ss.str();
 	}
 	std::string getInfo()
@@ -182,21 +195,21 @@ struct TcardInterface
 		}
 		return std::make_tuple(false,std::string(""));
 	}
-    inline int getstrindex(const uint64_t cardid)
-    {
-        if(m_cardid.first == cardid)
-          return 0;
-        else
-          return 1;
-        return -1;
-    }
-public:
-    std::pair<uint64_t,uint64_t> m_cardid;
-    uint64_t m_timestamp;
+	inline int getstrindex(const uint64_t cardid)
+	{
+		if(m_cardid.first == cardid)
+		  return 0;
+		else
+		  return 1;
+		return -1;
+	}
+	public:
+	std::pair<uint64_t,uint64_t> m_cardid;
+	uint64_t m_timestamp;
 	uint64_t m_owner;
 	std::deque<Data> m_arr;
 	int SIZE;
-    virtual ~TcardInterface(){} 
+	virtual ~TcardInterface(){} 
 };
 
 struct CardFactory
@@ -212,8 +225,8 @@ struct CardFactory
 		auto vec = m_owner->getcard(cid);
 		for(const auto cardid:vec)
 		{
-
-			uint64_t id = cardid+cid;
+			
+			uint64_t id = MyHash{}(cardid,cid);
 			auto iter = m_map.find(id);
 			if(iter != m_map.end())
 			{
@@ -238,10 +251,10 @@ struct CardFactory
 		std::shared_ptr<TcardInterface> ptr = nullptr;
 		for(const auto cardid:vec)
 		{
-			uint64_t id = cid+cardid;
+			uint64_t id = MyHash{}(cardid,cid);
 			auto iter = m_map.find(id);
 			if(iter != m_map.end())
-				ptr = iter->second;
+			  ptr = iter->second;
 			else
 			{
 				ptr = make_shared_(cardid,cid,cttime,id);
@@ -269,8 +282,8 @@ struct CardFactory
 			m_map.erase(it);
 		}
 	}
-    inline std::string InfoMessage()
-    {
+	inline std::string InfoMessage()
+	{
 		std::stringstream ss;
 		ss<<"S: "<<m_map.size();
 		for(auto it : m_map)
@@ -280,15 +293,15 @@ struct CardFactory
 		}
 		return std::move(ss.str());
 
-    }
-    virtual std::map<uint64_t,std::string> selectcard(std::vector<uint64_t> &v,uint64_t cid) = 0;
-    virtual std::shared_ptr<TcardInterface> make_shared_(const uint64_t cid1,const uint64_t cid2,const uint64_t ctime,uint64_t key) = 0;
-    virtual void backup (uint64_t cid1,uint64_t cid2){}
-    virtual void reset (uint64_t cid){}
-    virtual std::tuple<bool,std::string> checkLast(std::shared_ptr<TcardInterface> &ti)=0;
+	}
+	virtual std::map<uint64_t,std::string> selectcard(std::vector<uint64_t> &v,uint64_t cid) = 0;
+	virtual std::shared_ptr<TcardInterface> make_shared_(const uint64_t cid1,const uint64_t cid2,const uint64_t ctime,uint64_t key) = 0;
+	virtual void backup (uint64_t cid1,uint64_t cid2){}
+	virtual void reset (uint64_t cid){}
+	virtual std::tuple<bool,std::string> checkLast(std::shared_ptr<TcardInterface> &ti)=0;
 	virtual ~CardFactory(){}
-public:
-    std::unordered_map<uint64_t,std::shared_ptr<TcardInterface>>     m_map;
+	public:
+	std::unordered_map<uint64_t,std::shared_ptr<TcardInterface>>     m_map;
 	cardMgr * m_owner;
 };
 struct CloserCardFactory : CardFactory
@@ -299,13 +312,13 @@ struct CloserCardFactory : CardFactory
 	bool getAccess(uint64_t cid1,uint64_t cid2)
 	{
 		uint64_t cid = cid1+cid2;
-		if(m_count[cid] < 30)
+		if(m_count[cid] < 600)
 		{
 			m_count[cid]++;
 			return false;
 		}
 		else
-			return true;
+		  return true;
 	}
 	void reset(uint64_t id)
 	{
@@ -313,37 +326,37 @@ struct CloserCardFactory : CardFactory
 		if(it != m_count.end())
 		  m_count.erase(it);
 	}
-    virtual std::map<uint64_t,std::string> selectcard(std::vector<uint64_t> &v,uint64_t cid)
+	virtual std::map<uint64_t,std::string> selectcard(std::vector<uint64_t> &v,uint64_t cid)
 	{
 		std::map<uint64_t,std::string> vec;
 		if(v.empty()) return vec;
 		std::vector<uint64_t> rc(v.begin(),v.end());
 		auto opcard=card_list::instance()->get(cid);
 		rc.erase(std::remove_if(rc.begin(),rc.end(),[&](uint64_t cardid){
-			if(!getAccess(cid,cardid))
-				return true;
-			if(cardid == cid)
-				return true;
-			auto npcard = card_list::instance()->get(cardid);
-			if(npcard->type_()!=opcard->type_())
-				return true;
-			uint64_t ct1 = npcard->time_();
-			uint64_t ct2 = opcard->time_();
-			uint64_t ct3 = ct1>ct2?ct1-ct2:ct2-ct1;
-			return ct3 > TIME_LIM_SEC; 
-		}),rc.end());
+						if(!getAccess(cid,cardid))
+						return true;
+						if(cardid == cid)
+						return true;
+						auto npcard = card_list::instance()->get(cardid);
+						if(npcard->type_()!=opcard->type_())
+						return true;
+						uint64_t ct1 = npcard->time_();
+						uint64_t ct2 = opcard->time_();
+						uint64_t ct3 = ct1>ct2?ct1-ct2:ct2-ct1;
+						return ct3 > TIME_LIM_SEC; 
+						}),rc.end());
 
 		vec = handlecard(rc,cid);
 		return std::move(vec);
 	}
-    virtual void backup (uint64_t cid1,uint64_t cid2)
-    {
+	virtual void backup (uint64_t cid1,uint64_t cid2)
+	{
 		m_owner->addVertex(cid1,cid2);
-    }
-    virtual std::shared_ptr<TcardInterface> make_shared_(const uint64_t cid1,const uint64_t cid2,const uint64_t ctime,uint64_t key)
-    {
-        return std::make_shared<TcardInterface>(std::make_pair(cid1,cid2),ctime,key,m_closer_slot);
-    }
+	}
+	virtual std::shared_ptr<TcardInterface> make_shared_(const uint64_t cid1,const uint64_t cid2,const uint64_t ctime,uint64_t key)
+	{
+		return std::make_shared<TcardInterface>(std::make_pair(cid1,cid2),ctime,key,m_closer_slot);
+	}
 	std::tuple<bool,std::string> checkLast(std::shared_ptr<TcardInterface> &ti)
 	{
 		return ti->checkLast();
@@ -354,7 +367,7 @@ struct RemoteCardFactory : CardFactory
 {
 	RemoteCardFactory(cardMgr*);
 	int m_remote_slot=0;
-    virtual std::map<uint64_t,std::string> selectcard(std::vector<uint64_t> &ov,uint64_t cid)
+	virtual std::map<uint64_t,std::string> selectcard(std::vector<uint64_t> &ov,uint64_t cid)
 	{
 		auto vcard=m_owner->getcard(cid);
 		log_info("%d....remote%d",vcard.size(),(vcard.empty()?0:vcard[0]));
@@ -366,20 +379,20 @@ struct RemoteCardFactory : CardFactory
 		v.resize(it-v.begin());
 		auto opcard = card_list::instance()->get(cid);
 		v.erase(std::remove_if(v.begin(),v.end(),[&](uint64_t cardid){
-			auto npcard = card_list::instance()->get(cardid);
-			uint64_t ct1 = opcard->time_();
-			uint64_t ct2 = npcard->time_();
-			uint64_t ct3 = ct1>ct2?ct1-ct2:ct2-ct1;
-			return ct3 > TIME_LIM_SEC; 
-		}),v.end());
+						auto npcard = card_list::instance()->get(cardid);
+						uint64_t ct1 = opcard->time_();
+						uint64_t ct2 = npcard->time_();
+						uint64_t ct3 = ct1>ct2?ct1-ct2:ct2-ct1;
+						return ct3 > TIME_LIM_SEC; 
+						}),v.end());
 
 		auto vec = handlecard(v,cid);
 		return std::move(vec);
 	}
-    virtual std::shared_ptr<TcardInterface> make_shared_(const uint64_t cid1,const uint64_t cid2,const uint64_t ctime,uint64_t key)
-    {
-        return std::make_shared<TcardInterface>(std::make_pair(cid1,cid2),ctime,key,m_remote_slot);
-    }
+	virtual std::shared_ptr<TcardInterface> make_shared_(const uint64_t cid1,const uint64_t cid2,const uint64_t ctime,uint64_t key)
+	{
+		return std::make_shared<TcardInterface>(std::make_pair(cid1,cid2),ctime,key,m_remote_slot);
+	}
 	std::tuple<bool,std::string> checkLast(std::shared_ptr<TcardInterface> &ti)
 	{
 		return std::make_tuple(false,std::string(""));

+ 431 - 54
card.cpp

@@ -18,6 +18,8 @@
 #include "special_area.h"
 #include "cardMgr.h"
 #include "ant.h"
+#include "mine.h"
+#include "module_service/module_mgr.h"
 
 extern config_file config;
 //一张卡一个ct的所有不同天线的信息
@@ -158,15 +160,24 @@ struct card_message_handle
 			return;
 		}
 		//
-		m_card->site_hover(loc.m_site_id);
+        m_card->site_hover(loc.m_site_id);
 
-        if(loc.m_batty_status == 2) 
+        if(loc.m_batty_status == 2)
         {
-            m_card->do_status(STA_TYPE::STATUS_LOW_POWER_);
+            m_card->do_status(STATUS_POWER_LOWER_SERIOUS);
         }
-        else if(loc.m_callinfo == 0x80)
+        else
         {
-            m_card->do_status(STA_TYPE::STATUS_HELP_);
+            m_card->do_status(STATUS_POWER_NOMARL);
+        }
+
+        if(loc.m_callinfo & 0x80)
+        {
+            m_card->do_status(STATUS_HELP);
+        }
+        if((loc.m_callinfo & 0x01) || (loc.m_callinfo & 0x02))
+        {
+            m_card->do_status(STATUS_CALL);
         }
 
 		m_ct_list[loc.m_card_ct&(m_ct_list.size()-1)]->on_message(loop,loc);
@@ -178,18 +189,20 @@ struct card_area
 	card_area()
 	{
 		m_site_area.reset(new site_area_hover);
-		m_area_tool.reset(new area_tool);
+        m_area_tool.reset(new area_tool);
+        m_mine_tool.reset(new mine_tool);
 	}
 	std::shared_ptr<site_area_hover> m_site_area=nullptr;
 	std::shared_ptr<area_tool> m_area_tool=nullptr;
+    std::shared_ptr<mine_tool> m_mine_tool=nullptr;
 };
 
-struct person:card_location_base,private card_area
+struct person:card_location_base, card_area
 {
 	std::weak_ptr<monkey_person> m_monkeyPerson;
 
-	person(std::string type,uint32_t cardid,uint16_t needdisplay,int16_t t,int32_t deptid)
-        :card_location_base(type,cardid,needdisplay,t,deptid)
+	person(std::string type,uint32_t cardid,uint16_t needdisplay,int16_t t,int32_t deptid,int32_t level_id)
+        :card_location_base(type,cardid,needdisplay,t,deptid,level_id)
 	{
         m_message_handle = new card_message_handle(this);
 	}
@@ -198,29 +211,64 @@ struct person:card_location_base,private card_area
 	{
 		m_message_handle->on_message(loop,loc,is_history);
 	}
+
+    void clear()
+    {
+        //清除定时器
+        m_timer.stop();
+        m_loop = nullptr;
+
+        m_site_area.reset(new site_area_hover);
+        m_area_tool.reset(new area_tool);
+        m_mine_tool.reset(new mine_tool);
+
+        card_location_base::clear();
+    }
 	
 	virtual void site_hover(int sid)
 	{
-		m_site_area->on_point(m_id,sid,0);
+        if(m_time<=0)
+        {
+            return;
+        }
+        m_site_area->on_point(m_id,sid,nullptr, m_type);
 	}
+
+    virtual std::shared_ptr<area_hover> get_area_hover()
+    {
+        return m_area_tool->m_area_hover;
+    }
+
+    virtual std::shared_ptr<mine_tool> get_mine_tool()
+    {
+        return m_mine_tool;
+    }
+
+    virtual std::shared_ptr<site_area_hover> get_site_area()
+    {
+        return m_site_area;
+    }
+
 	virtual void do_business(const point &pt)
 	{
 		//区域
 		m_area_tool->on_point(m_id,pt,m_speed,m_type);
 		//考勤
-		m_site_area->on_point(m_id,0,this);
+        m_site_area->on_point(m_id,0,this, m_type);
 		//
 	}
 	//人卡升井后该线程要停掉
 	//手动升级需要补全区域得同时,需要进区域走区域业务
 	void set(ev::dynamic_loop * loop)
 	{
-		log_info("cardid_id %d",m_id);
+		if(!m_mine_tool->is_attendance())
+		  return;
+		log_info("person_is_on_att......%d",m_id);
 	    m_loop = loop;
 	
 	    m_timer.set(*m_loop);
 	    m_timer.set<person,&person::on_timer>(this);
-		m_timer.start(1,1);
+		m_timer.start(10,1);
 	}
 	void reset(std::shared_ptr<monkey_person> mp)
 	{
@@ -234,7 +282,7 @@ private:
 		point pt = getSmoothPoint();
 		const auto lm = m_area_tool->getLandmark();
 
-		cp.enter_area_time = std::get<0>(lm);
+		cp.enter_area_time = std::get<0>(lm)*1000;
 		cp.rec_time = std::get<1>(lm);
 
 		cp.map_id = std::get<2>(lm);
@@ -244,18 +292,13 @@ private:
 		cp.lm_direction = std::get<5>(lm);
 		cp.landmark_dis=std::get<6>(lm);
 
-		cp.biz_stat = state();
+		cp.biz_stat = get_stat();
+		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);
 	}
-	int state()
-	{
-		int status = get_stat();
-		if(status == STATUS_NORMAL)
-		{
-			//超时
-		}
-		return status;
-	}
 	point getSmoothPoint()
 	{
 		point pt;
@@ -276,25 +319,49 @@ private:
 	}
 };
 
-struct car:card_location_base,private card_area
+struct car:card_location_base,card_area
 {
 	int m_vehicle_category_id=0;
-	car(std::string type,uint32_t cardid,uint16_t needdisplay,int16_t t,int32_t deptid,int32_t categoryid)
-        :card_location_base(type,cardid,needdisplay,t,deptid)
+    int m_vehicle_type_id=0;
+    car(std::string type,uint32_t cardid,uint16_t needdisplay,int16_t t,int32_t deptid,
+        int32_t categoryid, int type_id,int32_t level_id)
+        :card_location_base(type,cardid,needdisplay,t,deptid,level_id)
 		,m_vehicle_category_id(categoryid)
+        ,m_vehicle_type_id(type_id)
     {
         m_message_handle=new card_message_handle(this);
     }
 
 	virtual void site_hover(int sid)
 	{
-		m_site_area->on_point(m_id,sid,0);
+        if(m_time<=0)
+        {
+            return;
+        }
+        m_site_area->on_point(m_id,sid,0, m_type);
 	}
 
+    virtual std::shared_ptr<area_hover> get_area_hover()
+    {
+        return m_area_tool->m_area_hover;
+    }
+
+    virtual std::shared_ptr<mine_tool> get_mine_tool()
+    {
+        return m_mine_tool;
+    }
+
+    virtual std::shared_ptr<site_area_hover> get_site_area()
+    {
+        return m_site_area;
+    }
+
 	virtual void do_business(const point &pt)
 	{
 		m_area_tool->on_point(m_id,pt,m_speed,m_type);
-		m_site_area->on_point(m_id,0,this);
+        m_site_area->on_point(m_id,0,this, m_type);
+
+        m_mine_tool->on_point(m_id, m_type, m_vehicle_category_id);
 	}
 
 	void set(ev::dynamic_loop * loop)
@@ -306,6 +373,12 @@ struct car:card_location_base,private card_area
 	    m_timer.set<car,&car::on_timer>(this);
 		m_timer.start(1,1);
 	}
+
+    int get_vehicle_type_id()
+    {
+        return  m_vehicle_type_id;
+    }
+
 	~car(){}
 private:
 	void on_timer()
@@ -316,12 +389,6 @@ private:
 	int statbiz(int32_t special_id)
 	{
 		int status = get_stat();
-		if(status==STATUS_NORMAL)
-		{
-			//超速
-			//超时
-			//顺序不能变
-		}
 		if(status == STATUS_LOST)
 		{
 			if(!m_area_tool->special_area())			
@@ -350,11 +417,10 @@ private:
 		cp.landmark_dis=std::get<6>(lm);
 		int32_t biz_stat=statbiz(special_id);
 		cp.biz_stat=biz_stat;
-		//cp.down_time
-		//cp.work_time;
-		//cp.level_id;
+		cp.down_time = m_mine_tool->get_down_time();
+		cp.work_time = m_mine_tool->get_work_time();
 		//for now
-		cp.is_on_duty=1;
+		cp.is_on_duty=m_mine_tool->is_on_duty();
 		upt_card_pos(cp,pt);
 
 		if(biz_stat==STATUS_LOST && special_id != -1 && m_display==1)
@@ -383,7 +449,7 @@ uint64_t card_list::getId(uint32_t cardid,uint64_t type)
 void card_list::init_vehicle()
 {
 	std::unordered_map<uint64_t,std::shared_ptr<card_location_base>> map;
-	std::string strategy = config.get("person.strategy","car1");
+	std::string strategy = config.get("car.strategy","car1");
 	const char *sql = "SELECT ve.vehicle_id, ve.card_id, c.card_type_id, \
 						ve.dept_id, ve.group_id, v.vehicle_type_id, vt.vehicle_level_id, \
 						vt.is_railroad AS vt_is_railroad,ve.need_display ,ve.power_alarm,\
@@ -447,7 +513,8 @@ void card_list::init_vehicle()
 			//for now
 			vehicle_id = vsid;
 
-			std::shared_ptr<card_location_base> clb = std::make_shared<car>(strategy,vehicle_id,need_display,card_type_id,dept_id,vehicle_category_id);
+            std::shared_ptr<card_location_base> clb = std::make_shared<car>(strategy,vehicle_id,
+                  need_display,card_type_id,dept_id,vehicle_category_id, vehicle_type_id,vehicle_level_id);
 			uint64_t cardid = getId(vehicle_id,2);
 			log_info("cardId:%llu,vehicle_id:%d dept_id:%d,need_display:%d---cardid:%s,categoryid:%d",cardid,vehicle_id,dept_id,need_display,card_id.c_str(),vehicle_category_id);
 			map.insert({cardid,clb});
@@ -507,7 +574,7 @@ void card_list::init_staffer()
 			//for now;
 			staff_id = vsid;
 
-			std::shared_ptr<card_location_base> clb = std::make_shared<person>(strategy,staff_id,need_display,card_type_id,dept_id);
+			std::shared_ptr<card_location_base> clb = std::make_shared<person>(strategy,staff_id,need_display,card_type_id,dept_id,occupation_level_id);
 			uint64_t cardid = getId(staff_id,1);
 			log_info("cardId:%llu,staff_id:%d dept_id:%d,need_display:%d--c-ard:%s",cardid,staff_id,dept_id,need_display,card_id.c_str());
 			map.insert({cardid,clb});
@@ -523,6 +590,276 @@ void card_list::init_card_from_db()
 	init_vehicle();
 }
 
+void card_list::load_his_card_postion_from_db()
+{
+    load_his_card_postion_vehicle();
+    load_his_card_postion_staff();
+
+    for(auto&iter: m_map)
+    {
+        auto card_ptr = iter.second;
+        auto mine_tool_ptr = card_ptr->get_mine_tool();
+        if(mine_tool_ptr->is_attendance())
+        {
+            auto str = tool_time::to_str_ex( tool_time::to_ms(mine_tool_ptr->m_attendance_start_time));
+            std_debug("加载考勤,考勤开始时间: %s, 卡id=%d,卡type=%d", str.c_str(), card_ptr->m_id, card_ptr->m_type);
+            log_info("加载考勤,考勤开始时间: %s, 卡id=%d,卡type=%d", str.c_str(), card_ptr->m_id, card_ptr->m_type);
+        }
+    }
+
+    auto area_map = area_list::instance()->m_map;
+    for(auto&iter: area_map)
+    {
+        auto area_ptr = iter.second;
+        if(area_ptr->m_person_count)
+        {
+            std_debug("加载区域人数: 区域id=%d,区域人数=%d",area_ptr->m_id, area_ptr->m_person_count.load());
+            log_info("加载区域人数: 区域id=%d,区域人数=%d",area_ptr->m_id, area_ptr->m_person_count.load());
+        }
+
+        if(area_ptr->m_vehicle_count)
+        {
+            std_debug("加载区域车数: 区域id=%d,区域车数=%d",area_ptr->m_id, area_ptr->m_vehicle_count.load());
+            log_info("加载区域车数: 区域id=%d,区域车数=%d",area_ptr->m_id, area_ptr->m_vehicle_count.load());
+        }
+    }
+}
+
+void card_list::load_his_card_postion_vehicle()
+{
+    const char *sql = "select l.card_id, l.cur_time, l.x, l.y, l.z, l.map_id, la.area_id, l.state, \
+            case when l.cur_time >= date_sub(now(), interval 2 minute) then l.speed else 0 end as speed, \
+            l.mileage, la.enter_time, att.start_time, \
+            att.end_time, \
+            l.landmark_id, l.direction_mapper_id, l.landmark_dist \
+            from rt_location l, rt_location_area la, rt_att_vehicle att, dat_card c, dat_vehicle_extend v \
+            where l.card_id = c.card_id and l.card_id = la.card_id and l.card_id = att.card_id and l.card_id=v.card_id \
+            and c.state_id=0;";
+    std::string Error;
+    YADB::CDBResultSet DBRes;
+    sDBConnPool.Query(sql,DBRes,Error);
+    if(!Error.empty())
+        log_error("load_his_card_postion_vehicle列表 Error,%s",Error.c_str());
+    uint64_t nCount = DBRes.GetRecordCount( Error );
+    if (nCount > 0)
+    {
+        log_info( "load_his_card_postion_vehicle. The record count=%ld\n", nCount );
+
+        while ( DBRes.GetNextRecod(Error) )
+        {
+            std::string card_id  = "";
+            DBRes.GetField( "card_id",card_id, Error );
+
+            uint32_t id = tool_other::id64_to_id(card_id);
+            int type = tool_other::id64_to_type(card_id);
+
+            auto temp_ptr = card_list::instance()->get(card_list::to_id64(type, id));
+            if(!temp_ptr || !temp_ptr->is_vehicle())
+            {
+                log_error("全局卡列表中找不到卡,卡id=%d,卡type=%d", id, type);
+                continue;
+            }
+
+            auto card_ptr = static_cast<car*>(temp_ptr.get());
+
+            double x = 0;
+            DBRes.GetField( "x",x, Error );
+
+            double y = 0;
+            DBRes.GetField( "y",y, Error );
+
+            double z = 0;
+            DBRes.GetField( "z",z, Error );
+
+            int map_id  = 0;
+            DBRes.GetField( "map_id",map_id, Error );
+
+            int area_id  = 0;
+            DBRes.GetField( "area_id",area_id, Error );
+
+            int state  = 0;
+            DBRes.GetField( "state",state, Error );
+
+            double speed = 0;
+            DBRes.GetField( "speed",speed, Error );
+
+            std::string enter_time  = "";
+            DBRes.GetField( "enter_time",enter_time, Error );
+
+            std::string start_time  = "";
+            DBRes.GetField( "start_time",start_time, Error );
+
+            std::string end_time  = "";
+            DBRes.GetField( "end_time",end_time, Error );
+
+            int landmark_id  = 0;
+            DBRes.GetField( "landmark_id",landmark_id, Error );
+
+            int direction_mapper_id  = 0;
+            DBRes.GetField( "direction_mapper_id",direction_mapper_id, Error );
+
+            double landmark_dist = 0;
+            DBRes.GetField( "landmark_dist",landmark_dist, Error );
+
+            card_ptr->x = x;
+            card_ptr->y = y;
+            card_ptr->z = z;
+
+            auto area = area_list::instance()->get(area_id);
+            if(area == nullptr)
+            {
+                log_error("load_vehicle...area_list 找不到区域:区域id=%d", area_id);
+                continue;
+            }
+            area->m_vehicle_count++;
+
+            point pt = *card_ptr;
+            card_ptr->m_area_tool->m_area_hover = std::make_shared<area_hover>( area, pt,speed);
+            auto area_hover_ptr = card_ptr->get_area_hover();
+
+            auto e_t = tool_time::to_time_ex(enter_time);
+            area_hover_ptr->m_enter_time = std::chrono::system_clock::to_time_t(e_t);
+
+            //int map_id  = 0;
+            //int state  = 0;
+            card_ptr->m_speed = speed;
+
+            if(end_time.empty())
+            {
+                auto mine_tool_ptr = card_ptr->get_mine_tool();
+                mine_tool_ptr->m_attendance_start_time = tool_time::to_time_ex(start_time);
+                mine_tool_ptr->m_stat_attendance = AS_ATTENDANCE;
+            }
+
+            area_hover_ptr->landmark_id = landmark_id;
+            area_hover_ptr->landmark_dir = direction_mapper_id;
+            area_hover_ptr->landmark_dis = landmark_dist;
+
+            card_ptr->m_time = tool_time::now_to_ms();
+        }
+    }
+}
+
+void card_list::load_his_card_postion_staff()
+{
+    const char *sql = "select l.card_id, l.cur_time, l.x, l.y, l.z, l.map_id, la.area_id, l.state, \
+            case when l.cur_time >= date_sub(now(), interval 2 minute) then l.speed else 0 end as speed, \
+            l.mileage, la.enter_time, att.start_time, \
+            att.end_time, \
+            l.landmark_id, l.direction_mapper_id, l.landmark_dist \
+            from rt_location l, rt_location_area la, rt_att_staff att, dat_card c, dat_staff_extend s \
+            where l.card_id = c.card_id and l.card_id = la.card_id and l.card_id = att.card_id and l.card_id=s.card_id\
+            and c.state_id=0;";
+    std::string Error;
+    YADB::CDBResultSet DBRes;
+    sDBConnPool.Query(sql,DBRes,Error);
+    if(!Error.empty())
+        log_error("load_his_card_postion_vehicle列表 Error,%s",Error.c_str());
+    uint64_t nCount = DBRes.GetRecordCount( Error );
+    if (nCount > 0)
+    {
+        log_info( "load_his_card_postion_vehicle. The record count=%ld\n", nCount );
+
+        while ( DBRes.GetNextRecod(Error) )
+        {
+            std::string end_time  = "";
+            DBRes.GetField( "end_time",end_time, Error );
+            if(!end_time.empty()) // 已升井,不再读入
+            {
+                continue;
+            }
+
+            std::string card_id  = "";
+            DBRes.GetField( "card_id",card_id, Error );
+
+            uint32_t id = tool_other::id64_to_id(card_id);
+            int type = tool_other::id64_to_type(card_id);
+
+            auto temp_ptr = card_list::instance()->get(card_list::to_id64(type, id));
+            if(!temp_ptr || !temp_ptr->is_person())
+            {
+                log_error("全局卡列表中找不到卡,卡id=%d,卡type=%d", id, type);
+                continue;
+            }
+
+            auto card_ptr = static_cast<car*>(temp_ptr.get());
+
+            double x = 0;
+            DBRes.GetField( "x",x, Error );
+
+            double y = 0;
+            DBRes.GetField( "y",y, Error );
+
+            double z = 0;
+            DBRes.GetField( "z",z, Error );
+
+            int map_id  = 0;
+            DBRes.GetField( "map_id",map_id, Error );
+
+            int area_id  = 0;
+            DBRes.GetField( "area_id",area_id, Error );
+
+            int state  = 0;
+            DBRes.GetField( "state",state, Error );
+
+            double speed = 0;
+            DBRes.GetField( "speed",speed, Error );
+
+            std::string enter_time  = "";
+            DBRes.GetField( "enter_time",enter_time, Error );
+
+            std::string start_time  = "";
+            DBRes.GetField( "start_time",start_time, Error );
+
+            int landmark_id  = 0;
+            DBRes.GetField( "landmark_id",landmark_id, Error );
+
+            int direction_mapper_id  = 0;
+            DBRes.GetField( "direction_mapper_id",direction_mapper_id, Error );
+
+            double landmark_dist = 0;
+            DBRes.GetField( "landmark_dist",landmark_dist, Error );
+
+            card_ptr->x = x;
+            card_ptr->y = y;
+            card_ptr->z = z;
+
+            auto area = area_list::instance()->get(area_id);
+            if(area == nullptr)
+            {
+                log_error("area_list 找不到区域:区域id=%d", area_id);
+                continue;
+            }
+            area->m_person_count++;
+
+            point pt = *card_ptr;
+            card_ptr->m_area_tool->m_area_hover = std::make_shared<area_hover>(area,pt,speed);
+            auto area_hover_ptr = card_ptr->get_area_hover();
+
+            auto e_t = tool_time::to_time_ex(enter_time);
+            area_hover_ptr->m_enter_time = std::chrono::system_clock::to_time_t(e_t);
+			log_info("load_staff...%d,areaid:%d,mapid:%d",id,area->id(),area->mapid());
+
+            //int map_id  = 0;
+            //int state  = 0;
+            card_ptr->m_speed = speed;
+
+            if(end_time.empty())
+            {
+                auto mine_tool_ptr = card_ptr->get_mine_tool();
+                mine_tool_ptr->m_attendance_start_time = tool_time::to_time_ex(start_time);
+                mine_tool_ptr->m_stat_attendance = AS_ATTENDANCE;
+            }
+
+            area_hover_ptr->landmark_id = landmark_id;
+            area_hover_ptr->landmark_dir = direction_mapper_id;
+            area_hover_ptr->landmark_dis = landmark_dist;
+
+            card_ptr->m_time = tool_time::now_to_ms();
+        }
+    }
+}
+
 void card_list::on_message(zloop<task*> *loop,const message_locinfo&loc,bool is_history)
 {
 	//std::shared_ptr<card_location_base>c=get(loc.m_card_id);
@@ -539,11 +876,17 @@ void card_list::on_message(zloop<task*> *loop,const message_locinfo&loc,bool is_
 	c->on_message(loop,loc,is_history);
 }
 //-----------------card_location_base..
-card_location_base::card_location_base(std::string type,uint32_t id,uint16_t dis,int16_t t,int32_t deptid)
-	:card(id,dis,t,deptid)
+card_location_base::card_location_base(std::string type,uint32_t id,uint16_t dis,int16_t t,int32_t deptid,int32_t level_id)
+	:card(id,dis,t,deptid,level_id)
 {
     select_tool_manage::instance()->create_tool(type,m_sel_tool,m_smo_tool);
 }
+
+void card_location_base::do_status(STATUS_CARD st)
+{
+    module_mgr::do_status(st, m_id, m_type);
+}
+
 void card_location_base::on_location(const std::vector<point>&vp,const std::vector<loc_message> &lm )
 {
 	//ct timestamp;
@@ -558,7 +901,8 @@ void card_location_base::on_location(const std::vector<point>&vp,const std::vect
 		y = pt.y;
 
 		Msg m;
-		m.x=(int)x;m.y=(int)y;m.cmd=CMD_HANDLE;m.cardid=m_type<<32|m_id;
+
+		m.type=m_type;m.x=(int)x;m.y=(int)y;m.cmd=CMD_HANDLE;m.cardid=m_type<<32|m_id;
 		cardMgr::instance()->tryPut(m);
 
 		log_info("useful:card_id:%d,ct:%d,timestamp:%llu, loc_point,x:%.2f,y:%.2f ",m_id,m_ct,m_time,pt.x,pt.y);
@@ -588,21 +932,54 @@ void card_location_base::upt_card_pos(YA::_CARD_POS_ &cp,const point &pt)
 	cp.dept_id = m_deptid;
 	cp.display=m_display;
 	cp.rec_time=m_time;
+	cp.level_id = m_level_id;
 
 	swsTimerThrd.upt_card_pos(cp);
 }
+void card_location_base::del_card_pos()
+{
+	YA::_CARD_POS_ cp;
+	cp.ID = m_id;
+	cp.Type=m_type;
+	swsTimerThrd.del_card_pos(cp);
+}
 int  card_location_base::get_stat()
 {
 	//盲区>呼救>呼叫>超时>超速>正常
-	int status=STATUS_NORMAL;
-	if(false)
-		status = STATUS_CALL;
-	if(false)
-		status = STATUS_HELP;
-
-	uint64_t now = time(0)*1000;
-	status=(now-m_time>CARD_LOST_TIME_OUT)?STATUS_LOST:STATUS_NORMAL;
-	return status;
+    uint64_t now = time(0)*1000;
+    if(now-m_time>CARD_LOST_TIME_OUT)
+    {
+        return STATUS_LOST;
+    }
+    else if(auto ev_ptr = event_list::instance()->get_event_card(m_id, m_type, ET_CARD_HELP))
+    {
+        return  (ES_DEAL_HELP == ev_ptr->m_status) ?  STATUS_HELP_DEALED : STATUS_HELP;
+    }
+    else if(CALL_NONE != get_mine_tool()->m_status_call)
+    {
+        return  STATUS_CALL;
+    }
+    else if(event_list::instance()->get_event_card(m_id, m_type,
+                is_person()? ET_CARD_AREA_OVER_TIME_PERSON: ET_CARD_AREA_OVER_TIME_VEHICLE))
+    {
+        return  STATUS_AREA_OVER_TIME;
+    }
+    else if(event_list::instance()->get_event_card(m_id, m_type, ET_CARD_OVER_SPEED))
+    {
+        return  STATUS_OVER_SPEED;
+    }
+
+    return STATUS_NORMAL;
+}
+
+void  card_location_base::clear()
+{
+//	uint16_t m_display;			//1显示0不显示,往前端推送
+    m_speed=0;			//速度
+    m_is_attendance=0;	//井上井下状态  0初始状态 1 井上 2 井下
+    m_stat=0;			//运动静止状态
+    //m_ct;				//ct
+    m_time=0;			//时间戳
 }
 card_location_base::~card_location_base()
 {

+ 46 - 11
card.h

@@ -7,7 +7,9 @@
 #include "write-copy.h"
 #include "websocket/ws_common.h"
 #include "common.h"
-#include "ant.h"
+#include "area.h"
+#include "site_area.h"
+#include "loc_message.h"
 #define CARD_LOST_TIME_OUT (30*1000)
 
 struct task;
@@ -16,9 +18,10 @@ struct select_tool;
 struct smooth_tool;
 struct monkey_person;
 struct card_message_handle;
+struct mine_tool;
 struct card:point
 {
-	card(uint32_t id,uint16_t dis,uint64_t type,int32_t deptid)
+	card(uint32_t id,uint16_t dis,uint64_t type,int32_t deptid,int32_t level_id)
 		:m_id(id)
 		,m_type(type)
 		,m_display(dis)
@@ -28,6 +31,7 @@ struct card:point
 		,m_ct(0)
 		,m_time(0)
 		,m_deptid(deptid)
+		,m_level_id(level_id)
 	{}
 	uint64_t type_(){return m_type;}
 	uint64_t time_(){return m_time;}
@@ -38,8 +42,10 @@ struct card:point
 	int      m_is_attendance;	//井上井下状态  0初始状态 1 井上 2 井下
 	int		 m_stat;			//运动静止状态
 	uint16_t m_ct;				//ct
-	uint64_t m_time;			//时间戳
+    ///时间戳 ms
+    uint64_t m_time;
 	int32_t  m_deptid;			//部门编号
+	int32_t  m_level_id;		//部门级别
 };
 struct card_location_base:card
 {
@@ -50,24 +56,35 @@ struct card_location_base:card
     ev::timer m_timer;
 
     card_location_base()=default;
-    card_location_base(std::string type,uint32_t id,uint16_t dis,int16_t t,int32_t );
+    card_location_base(std::string type,uint32_t id,uint16_t dis,int16_t t,int32_t,int32_t );
 
 	virtual void do_business(const point &pt)=0;
 	virtual void set(ev::dynamic_loop * loop)=0;
 	virtual void site_hover(int sid)=0;
+    virtual std::shared_ptr<area_hover> get_area_hover()=0;
+    virtual std::shared_ptr<mine_tool> get_mine_tool()=0;
+    virtual std::shared_ptr<site_area_hover> get_site_area()=0;
+
+    virtual void clear();
+
 	virtual void reset(std::shared_ptr<monkey_person> mp){}
+    virtual int get_vehicle_type_id(){return  0;}
 
     void on_message(zloop<task*> * loop,const message_locinfo&loc,bool is_history);
     void on_location(const std::vector<point>&vp,const std::vector<loc_message> &lm );
-    void do_status(STA_TYPE st)
-    {
-        if(STATUS_HELP_==st)
-        {
-            //module_call_help::ins
-        }
-    }
+    void do_status(STATUS_CARD st);
 	void upt_card_pos(YA::_CARD_POS_ &,const point &pt);
+	void del_card_pos();
 	int get_stat();
+    bool is_person() const
+    {
+        return CT_PERSON == m_type;
+    }
+
+    bool is_vehicle() const
+    {
+        return CT_VEHICLE == m_type;
+    }
 	virtual ~card_location_base();
 };
 
@@ -78,6 +95,24 @@ struct card_list:single_base<card_list,uint64_t,std::shared_ptr<card_location_ba
     uint64_t getId(uint32_t cardid,uint64_t);
     void on_message(zloop<task*> *loop,const message_locinfo&loc,bool is_history);
     void init_card_from_db();
+
+    void load_his_card_postion_vehicle();
+    void load_his_card_postion_staff();
+    void load_his_card_postion_from_db();
+
+    /// (类型<<32)|卡号
+    static uint64_t to_id64(int32_t type, uint32_t id)
+    {
+        return (static_cast<uint64_t>(type)<<32)|id;
+    }
+
+    static std::string to_id64_str(int32_t type, uint32_t id)
+    {
+        char sql[15] = {'\0'};
+        sprintf(sql, "%03d%010d", type, id);
+
+        return std::string(sql);
+    }
     ~card_list(){}
 };
 

+ 4 - 2
cardMgr.cpp

@@ -1,5 +1,6 @@
 #include "cardMgr.h" 
 #include "bindmorecard.h"
+#include "common.h"
 
 cardMgr::cardMgr()
 :m_queue(2048)
@@ -37,7 +38,7 @@ void cardMgr::clear(uint64_t cardid)
 	auto v = m_cgraph.getcard(cardid);
 	for(const auto & cid:v)
 	{
-		uint64_t id=cid+cardid;
+		uint64_t id = MyHash{}(cardid,cid);
 		erase(id);
 		m_cgraph.remove_edge(cardid,cid);
 	}
@@ -45,8 +46,9 @@ void cardMgr::clear(uint64_t cardid)
 void cardMgr::handleMessage(const Msg &m)
 {
 	m_glist.update(m.x,m.y,m.cardid);
+	if(m.type==CT_VEHICLE) return;
 	std::vector<uint64_t> rc=m_glist.find_near(m.cardid,1);
-
+	
 	log_info("LemonHash+..%d,size:%d,(%d,%d)",m.cardid,rc.size(),m.x,m.y);
 	std::map<uint64_t,std::string> map1;
 	std::map<uint64_t,std::string> map2;

+ 10 - 4
cardMgr.h

@@ -14,33 +14,38 @@ struct card_graph
 {
 	typedef boost::adjacency_list<boost::vecS,boost::vecS,boost::bidirectionalS> myGraph_vv;
 	myGraph_vv m_g;
+	uint32_t _count=0;
 
 	void add_edge(uint32_t c1,uint32_t c2)
 	{
+		log_info("add_edge:%d,%d",c1,c2);
 		boost::add_edge(c1,c2,m_g);
 		boost::add_edge(c2,c1,m_g);
+		_count=boost::num_vertices(m_g);
 	}
 
 	void clear_vertex(uint32_t c)
 	{
-		if(c>boost::num_vertices(m_g)) return;
+		if(c>=_count) return;
 		boost::clear_vertex(c,m_g);
 	}
 	void remove_edge(uint32_t c1,uint32_t c2)
 	{
-		uint64_t count = boost::num_vertices(m_g);
-		if(c1>count || c2>count) return;
+		if(c1>=_count || c2>=_count) return;
 		boost::remove_edge(c1,c2,m_g);
 		boost::remove_edge(c2,c1,m_g);
 	}
 	std::vector<uint32_t> getcard(uint32_t c)
 	{
+		log_info("--------getcard---------num_edges:%d,%d",boost::num_edges(m_g),_count);
 		std::vector<uint32_t> tmp;
-		if(c>boost::num_vertices(m_g))return tmp;
+		if(c>=_count)return tmp;
 		boost::graph_traits<myGraph_vv>::adjacency_iterator ai_it, ai_it_end;
 		boost::tie(ai_it, ai_it_end) = boost::adjacent_vertices(c, m_g);
 		while(ai_it != ai_it_end)
 		{
+			log_info("get_card%d:",c);
+			log_info("get_card_%d:",*ai_it);
 			tmp.push_back(*ai_it);
 			ai_it++;
 		}
@@ -59,6 +64,7 @@ struct Msg
 	int				x;
 	int				y;
 	uint64_t        cardid;
+	int				type;
 };
 
 class CardFactory;

+ 18 - 0
common.h

@@ -1,6 +1,20 @@
 #ifndef COMMON_HPP__
 #define COMMON_HPP__
 
+#define LENGTH_SQL 2000
+#define SPEED_COUNT_LIMIT 5
+
+/**
+ * @brief 分站位置 1井上,2井下
+ */
+enum READER_TYPE_ID
+{
+    ///井上分站
+    READER_TYPE_ID_UP=1,
+    ///井下分站
+    READER_TYPE_ID_DOWN=2
+};
+
 enum STA_TYPE
 {
 	STATUS_HELP_=0,
@@ -9,12 +23,16 @@ enum STA_TYPE
 enum STATUS_CARD
 {
 	STATUS_NORMAL=0,
+    STATUS_POWER_LOWER_SERIOUS = 2, //电量极低
+    STATUS_POWER_NOMARL = 3,
 	STATUS_OVER_SPEED=8,
 	STATUS_AREA_OVER_TIME=16,
 	STATUS_HELP=128,
+    STATUS_HELP_DEALED = 256,		//呼救已处理
 	STATUS_CALL=512,
 	STATUS_LOST=1024
 };
+
 /**
  * @brief 0初始状态 1 没在考勤 2 考勤
  */

+ 454 - 0
common_tool.h

@@ -0,0 +1,454 @@
+#ifndef COMMON_TOOL_H
+#define COMMON_TOOL_H
+
+/**
+ * @brief 基楚的工具类
+ * @author 戴月腾
+ * @date 2018-09-15
+ */
+
+#include "common.h"
+#include "log.h"
+#include <chrono>
+#include <string>
+#include <sys/time.h>
+#include "db_api/CDBConnPool.h"
+#include "websocket/wsClientMgr.h"
+#include "card.h"
+#include "mine.h"
+
+class tool_time
+{
+public:
+    static uint32_t elapse_seconds(std::chrono::system_clock::time_point &start)
+    {
+        return static_cast<uint32_t>( std::chrono::duration_cast<std::chrono::seconds>
+                (std::chrono::system_clock::now() - start).count() );
+    }
+
+    static uint64_t elapse_ms(std::chrono::system_clock::time_point &start)
+    {
+        return static_cast<uint64_t>( std::chrono::duration_cast<std::chrono::milliseconds>
+                (std::chrono::system_clock::now() - start).count() );
+    }
+
+    static uint32_t now_to_seconds()
+    {
+        return static_cast<uint32_t>( std::chrono::duration_cast<std::chrono::seconds>
+                (std::chrono::system_clock::now().time_since_epoch()).count() );
+    }
+
+    static uint64_t now_to_ms()
+    {
+        return static_cast<uint64_t>( std::chrono::duration_cast<std::chrono::milliseconds>
+                (std::chrono::system_clock::now().time_since_epoch()).count() );
+    }
+
+    static uint64_t now_to_us()
+    {
+        return static_cast<uint64_t>( std::chrono::duration_cast<std::chrono::microseconds>
+                (std::chrono::system_clock::now().time_since_epoch()).count() );
+    }
+
+    static uint64_t to_ms(const std::chrono::system_clock::time_point &time)
+    {
+        return static_cast<uint64_t>( std::chrono::duration_cast<std::chrono::milliseconds>
+                (time.time_since_epoch()).count() );
+    }
+
+    static std::string to_str(const std::chrono::system_clock::time_point &time)
+    {
+        char _time[25] = {0};
+        time_t tt = std::chrono::system_clock::to_time_t(time);
+        struct tm local_time;
+        localtime_r(&tt, &local_time);
+        strftime(_time, 22, "%Y-%m-%d %H:%M:%S", &local_time);
+
+        return std::string(_time);
+    }
+	static uint64_t morning_of_today_ms()
+	{
+		std::time_t now = time(0);
+		struct tm * loc_t = localtime(&now);
+		loc_t->tm_hour=0;loc_t->tm_min=0;loc_t->tm_sec=0;
+		now = mktime(loc_t);
+		return now*1000;
+	}
+    //"%Y-%m-%d %H:%M:%S"
+    static time_t to_time(std::string str)
+    {
+        time_t t_;
+        tm tm_;
+        strptime(str.c_str(), "%Y-%m-%d %H:%M:%S", &tm_); //将字符串转换为tm时间
+        t_ = mktime(&tm_); //将tm时间转换为秒时间
+
+        return t_;
+    }
+
+    ////"%d-%02d-%02d %02d:%02d:%02d.%03d"
+    static std::chrono::system_clock::time_point to_time_ex(std::string str)
+    {
+        uint64_t pos = str.length()-3;
+
+        time_t t_;
+        tm tm_;
+        strptime(str.substr(0,pos).c_str(), "%Y-%m-%d %H:%M:%S", &tm_); //将字符串转换为tm时间
+        t_ = mktime(&tm_); //将tm时间转换为秒时间
+
+        int milli = std::stoi(str.substr(pos));
+
+        return std::chrono::system_clock::time_point(std::chrono::milliseconds(t_*1000 + milli));
+    }
+
+    //"%d-%02d-%02d %02d:%02d:%02d.%03d"
+    static std::string to_str_ex(uint64_t ms)
+    {
+        int32_t mill = ms%1000;
+
+        char _time[25] = {0};
+        time_t tt = ms/1000;
+        struct tm *local_time=localtime(&tt);
+        //strftime(_time, 22, "%Y-%m-%d %H:%M:%S", local_time);
+        sprintf(_time, "%d-%02d-%02d %02d:%02d:%02d.%03d", local_time->tm_year+1900,
+                local_time->tm_mon+1, local_time->tm_mday, local_time->tm_hour,
+                local_time->tm_min, local_time->tm_sec, mill);
+
+        return std::string(_time);
+    }
+
+    //"%d-%02d-%02d %02d:%02d:%02d.%03d"
+    static std::string to_str_ex(std::chrono::system_clock::time_point time)
+    {
+        return to_str_ex(to_ms(time));
+    }
+
+    static int elapse_seconds(time_t &start)
+    {
+        time_t now;
+        time(&now);
+        return static_cast<int>(std::difftime(now, start));
+    }
+
+    //"%Y-%m-%d %H:%M:%S"
+    static std::string to_str(const std::time_t &time)
+    {
+        char _time[25] = {0};
+        struct tm local_time;
+        localtime_r(&time, &local_time);
+        strftime(_time, 22, "%Y-%m-%d %H:%M:%S", &local_time);
+
+        return std::string(_time);
+    }
+};
+
+class tool_other
+{
+public:
+    static void send_json(const std::string& cmd, const std::string& data)
+    {
+        log_info("发送json: cmd=%s, data=%s\n", cmd.c_str(), data.c_str());
+        swsClientMgr.send(cmd, data);
+    }
+
+    static std::string to13str(std::string& str)
+    {
+        uint64_t tmp = std::stoull(str);
+        char ss[20]={0};
+        sprintf(ss, "%013ld", tmp);
+
+        return std::string(ss);
+    }
+
+    static uint32_t id64_to_id(std::string& str)
+    {
+        return static_cast<uint32_t>(std::stoul(to13str(str).substr(3)));
+    }
+
+    static int id64_to_type(std::string& str)
+    {
+        return std::stoi(to13str(str).substr(0, 3));
+    }
+};
+
+
+class tool_db
+{
+public:
+    static void PushAsync(char* sql)
+    {
+        if(!sDBConnPool.PushAsync(sql))
+        {
+            log_error( "PushAsync记录到队列中失败\n");
+        }
+    }
+
+    static void save_attendance(const std::shared_ptr<card_location_base>& card_ptr)
+    {
+        char sql[LENGTH_SQL] = {0};
+
+        std::string call("add_att_staff");
+        if(card_ptr->is_vehicle())//车卡
+        {
+            call="add_att_vehicle";
+        }
+
+        auto mine_tool_ptr = card_ptr->get_mine_tool();
+
+        auto start = mine_tool_ptr->m_attendance_start_time;
+        auto end = mine_tool_ptr->m_attendance_start_time;
+        if(!mine_tool_ptr->is_attendance())//考勤结束时间
+        {
+            end = std::chrono::system_clock::time_point(std::chrono::milliseconds(card_ptr->m_time));
+        }
+
+        std::string start_str = tool_time::to_str(start);
+        std::string end_str = tool_time::to_str(end);
+
+        int landmarkid = 0;
+        int landmarkdirect=0;
+        double landmarkdist=0;
+        auto area_hover_ptr = card_ptr->get_area_hover();
+        if(area_hover_ptr)
+        {
+            landmarkid = area_hover_ptr->landmark_id;
+            landmarkdirect = area_hover_ptr->landmark_dir;
+            landmarkdist = area_hover_ptr->landmark_dis;
+        }
+
+        sprintf(sql, "CALL %s(%s, %d, '%s', '%s', %d, %d, %.3f);", call.c_str(),
+                card_list::to_id64_str(card_ptr->m_type, card_ptr->m_id).c_str(),
+                card_ptr->m_id, start_str.c_str(), end_str.c_str(),
+                landmarkid, landmarkdirect, landmarkdist);
+
+        PushAsync(sql);
+    }
+};
+
+class tool_map
+{
+public:
+    static bool try_get_value(sio::message::ptr& out_data,
+                              const char* key, sio::message::ptr const& data)
+    {
+        auto map=data->get_map()[key];
+        if(map && sio::message::flag_object == map->get_flag())
+        {
+            out_data = map;
+            return true;
+        }
+
+        return false;
+    }
+
+    static bool try_get_value(int64_t& out_data, const char* key, sio::message::ptr const& data)
+    {
+        auto map=data->get_map()[key];
+        if(map && sio::message::flag_integer == map->get_flag())
+        {
+            out_data = map->get_int();
+            return true;
+        }
+
+        return false;
+    }
+
+    static bool try_get_value(uint32_t& out_data, const char* key, sio::message::ptr const& data)
+    {
+        auto map=data->get_map()[key];
+        if(map && sio::message::flag_integer == map->get_flag())
+        {
+            out_data = static_cast<uint32_t>(map->get_int());
+            return true;
+        }
+
+        return false;
+    }
+
+    static bool try_get_value(int& out_data, const char* key, sio::message::ptr const& data)
+    {
+        auto map=data->get_map()[key];
+        if(map && sio::message::flag_integer == map->get_flag())
+        {
+            out_data = static_cast<int>(map->get_int());
+            return true;
+        }
+
+        return false;
+    }
+
+    static bool try_get_value(std::string& out_data, const char* key, sio::message::ptr const& data)
+    {
+        auto map=data->get_map()[key];
+        if(map && sio::message::flag_string == map->get_flag())
+        {
+            out_data = map->get_string();
+            return true;
+        }
+
+        return false;
+    }
+
+    static bool try_get_value(double& out_data, const char* key, sio::message::ptr const& data)
+    {
+        auto map=data->get_map()[key];
+        if(map && sio::message::flag_double == map->get_flag())
+        {
+            out_data = map->get_double();
+            return true;
+        }
+
+        return false;
+    }
+
+    static bool try_get_value(std::vector<sio::message::ptr>& out_data,
+                               const char* key, sio::message::ptr const& data)
+    {
+        auto map=data->get_map()[key];
+        if(map && sio::message::flag_array == map->get_flag())
+        {
+            out_data = map->get_vector();
+            return true;
+        }
+
+        return false;
+    }
+};
+
+class tool_json
+{
+public:
+    static void add_member(rapidjson::Value& out_data, const char* key, std::string value,
+                              rapidjson::Document::AllocatorType& allocator)
+    {
+        rapidjson::Value name;
+        name.SetString(key, allocator);
+
+        rapidjson::Value data;
+        data.SetString(value.c_str(), allocator);
+
+        out_data.AddMember(name, data, allocator);
+    }
+
+    static void push_back(rapidjson::Value& out_data, std::string value,
+                              rapidjson::Document::AllocatorType& allocator)
+    {
+        rapidjson::Value data;
+        data.SetString(value.c_str(), allocator);
+
+        out_data.PushBack(data, allocator);
+    }
+
+    static bool try_get_iter(const char* key, const rapidjson::Value& node,
+                             rapidjson::Value::ConstMemberIterator& out_iter)
+    {
+        if(node.IsObject())
+        {
+            out_iter = node.FindMember(key);
+            if(node.MemberEnd() == out_iter)
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    static bool try_get_value(int& d, const char* key, const rapidjson::Value& node)
+    {
+        rapidjson::Value::ConstMemberIterator iter;
+        if(try_get_iter(key, node, iter))
+        {
+            if(iter->value.IsInt())
+            {
+                d = iter->value.GetInt();
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    static bool try_get_value(uint64_t& d, const char* key, const rapidjson::Value& node)
+    {
+        rapidjson::Value::ConstMemberIterator iter;
+        if(try_get_iter(key, node, iter))
+        {
+            if(iter->value.IsUint64())
+            {
+                d = iter->value.GetUint64();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static bool try_get_value(double& d, const char* key, const rapidjson::Value& node)
+    {
+        rapidjson::Value::ConstMemberIterator iter;
+        if(try_get_iter(key, node, iter))
+        {
+            if(iter->value.IsDouble())
+            {
+                d = iter->value.GetDouble();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static bool try_get_value(std::string& d, const char* key, const rapidjson::Value& node)
+    {
+        rapidjson::Value::ConstMemberIterator iter;
+        if(try_get_iter(key, node, iter))
+        {
+            if(iter->value.IsString())
+            {
+                d = iter->value.GetString();
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    static int get_value(const char* key, const int& default_data, const rapidjson::Value& node)
+    {
+        rapidjson::Value::ConstMemberIterator iter;
+        if(try_get_iter(key, node, iter))
+        {
+            if(iter->value.IsInt())
+            {
+                return  iter->value.GetInt();
+            }
+        }
+
+        return default_data;
+    }
+
+    static std::string get_value(const char* key, const std::string& default_data, const rapidjson::Value& node)
+    {
+        rapidjson::Value::ConstMemberIterator iter;
+        if(try_get_iter(key, node, iter))
+        {
+            if(iter->value.IsString())
+            {
+                return iter->value.GetString();
+            }
+        }
+
+        return default_data;
+    }
+
+    static std::string doc_to_json(rapidjson::Document& doc)
+    {
+        rapidjson::StringBuffer sb;
+        rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
+        doc.Accept(writer);
+
+        return sb.GetString();
+    }
+};
+
+#endif // COMMON_TOOL_H

+ 46 - 0
loc_message.h

@@ -0,0 +1,46 @@
+#ifndef __LOC_MESSAGE__HPP
+#define __LOC_MESSAGE__HPP
+#include "ant.h"
+struct loc_message
+{
+    site     m_sit;
+    uint64_t m_num_ticks; //tof时间片m_tof或tdoa相对root时间
+    uint64_t m_loc_time;
+    uint32_t m_card_id;
+    int32_t	 m_card_ct;
+    int8_t   m_card_type;
+    int8_t   m_ant_id;
+    int16_t  m_rav;
+    int16_t  m_acc;
+    uint16_t m_sync_ct;
+    uint16_t m_rssi;
+
+	loc_message()
+	 :m_num_ticks(0)
+	{
+	}
+	int tool_index()const
+	{
+		return m_sit.index();
+	}
+
+
+
+    loc_message(site s,uint64_t num_ticks,uint64_t timestamp,
+                uint32_t cardid,int32_t ct,int8_t type,int8_t antid,
+                int16_t rav,int16_t acc,uint16_t sync_ct,uint16_t rssi)
+        :m_sit(s)
+        ,m_num_ticks(num_ticks)
+        ,m_loc_time(timestamp)
+        ,m_card_id(cardid)
+        ,m_card_ct(ct)
+        ,m_card_type(type)
+        ,m_ant_id(antid)
+        ,m_rav(rav)
+        ,m_acc(acc)
+        ,m_sync_ct(sync_ct)
+        ,m_rssi(rssi)
+    {}
+};
+
+#endif

+ 1 - 0
loc_point.cpp

@@ -3,6 +3,7 @@
 #include "loc_point.h"
 #include "ant.h"
 #include "log.h"
+#include "loc_message.h"
 
 loc_point::loc_point()
     :m_time(0)

+ 1 - 1
loc_tool.h

@@ -1,6 +1,6 @@
 #ifndef __loc_tool_hpp__
 #define __loc_tool_hpp__
-
+#include "loc_message.h"
 struct ant;
 struct message_locinfo;
 /*

+ 13 - 8
main.cpp

@@ -11,6 +11,10 @@
 #include "card_path.h"
 #include "landmark.h"
 #include "special_area.h"
+#include "mine.h"
+#include "ya_event.h"
+#include"module_service/module_area.h"
+#include"module_service/module_mgr.h"
 
 #include <config_file.h>
 
@@ -55,8 +59,9 @@ struct Init_Setting
 		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);
-		
 
+        card_list::instance()->load_his_card_postion_from_db();
+        event_list::instance()->load_his_data_from_db();
 	}
 
 	void _mysql_init(YADB::_DB_POOL_SETTING_ &dps)
@@ -75,10 +80,9 @@ struct Init_Setting
 		std::map<std::string, YA::MSG_HANDLE_FUNC_TYPE> MsgFuncList;
 	
         //MsgFuncList.insert( std::make_pair( "req_all_data", On_req_all_data ) );
-		//MsgFuncList.insert( std::make_pair( "req_all_person_on_car", On_req_all_person_on_car ) );
-
-        //module_mgr::instance()->init(MsgFuncList);
+        //MsgFuncList.insert( std::make_pair( "req_all_person_on_car", On_req_all_person_on_car ) );
 
+        module_mgr::init(config, MsgFuncList);
 
 		swsClientMgr.Build( uri_list, MsgFuncList );
 	
@@ -104,6 +108,8 @@ struct Init_Setting
 
 void cleanup() 
 { 
+    module_mgr::stop();
+
 	ev_loop_destroy(ev_default_loop());
 }
 
@@ -117,12 +123,11 @@ int main()
 	
 	atexit(&cleanup);
 
-    //module_mgr::instance()->init();
-    //module_mgr::instance()->start();
-
 	card_path::init();
-	net_service mh;
 
+    module_mgr::start();
+
+	net_service mh;
 	int port=config.get("service.port",4000);
 	service_handle::instance(&mh)->run(port);
 

+ 21 - 0
mine.cpp

@@ -0,0 +1,21 @@
+#include "mine.h"
+#include <module_service/module_mine.h>
+#include "common_tool.h"
+
+void mine_tool::on_point(uint32_t card_id, int32_t type, int vehicle_category_id)
+{
+    module_mine::on_point(card_id, type, vehicle_category_id);
+}
+	uint64_t mine_tool::get_down_time()
+	{
+		return tool_time::to_ms(m_attendance_start_time);
+	}
+	uint64_t mine_tool::get_work_time()
+	{
+		return tool_time::elapse_ms(m_attendance_start_time)	;
+	}
+	int32_t mine_tool::is_on_duty()
+	{
+		return get_down_time()>tool_time::morning_of_today_ms();
+	}
+

+ 48 - 0
mine.h

@@ -0,0 +1,48 @@
+#ifndef MINE_H
+#define MINE_H
+
+/**
+ * @brief 矿井里相关的业务
+ * @author 戴月腾
+ * @date 2018-09-24
+ */
+
+#include <unordered_map>
+#include "db_api/CDBConnPool.h"
+#include <log.h>
+#include "common.h"
+struct mine_tool
+{
+    mine_tool():
+        m_over_speed_count(0)
+      ,m_normal_speed_count(0)
+      ,m_status_call(0)
+      ,m_stat_attendance(AS_INIT)
+      ,m_attendance_start_time(std::chrono::seconds(0))
+    {
+
+    }
+
+    int    m_over_speed_count;
+    int    m_normal_speed_count;
+    ///CALL_NONE(0):没有呼叫,CALL_ING(2):正在呼叫,CALL_SUCCESSED(1):呼叫成功
+    int m_status_call;
+
+    ///考勤状态  0初始状态 1 没在考勤 2 考勤;参看ATTENDANCE_STATUS
+    int m_stat_attendance;
+    ///考勤开始时间
+    std::chrono::system_clock::time_point m_attendance_start_time;
+
+    void on_point(uint32_t card_id, int32_t type, int vehicle_category_id);
+	uint64_t get_down_time();
+	uint64_t get_work_time();
+	int32_t is_on_duty();
+    bool is_attendance()
+    {
+        return AS_ATTENDANCE == m_stat_attendance;
+    }
+};
+
+
+
+#endif // MINE_H

+ 0 - 122
module_service/module_area.cpp

@@ -1,122 +0,0 @@
-#include "module_area.h"
-#include"module_area_overman.h"
-#include"module_area_timeout.h"
-#include"module_attendance_vehicle.h"
-#include"module_const.h"
-#include"module_area_over_speed.h"
-
-
-void module_area::on_enter(uint64_t card_id,std::shared_ptr<area_hover>&c,double speed)
-{
-    //与考勤,卡数统计,超员,超时无关的区域   直接返回
-    if(AT_OTHER == c->m_area->m_area_type)
-    {
-        return;
-    }
-
-    auto card_ptr=card_list::instance()->get(card_id);
-    if(!card_ptr)
-    {
-        log_error("卡不存在card_id=%d", card_id);
-        return;
-    }
-
-    std::lock_guard<std::mutex> lock(_mutex);
-
-    //c->m_enter_time = std::chrono::system_clock::now();
-
-    if(CT_PERSON == card_ptr->m_type)//统计人卡
-    {
-        c->m_area->m_person_count++;
-
-        //区域人卡超员
-        module_area_overman::instance()->on_enter(card_ptr, c, speed);
-        //区域人卡超时
-        module_area_timeout::instance()->on_enter(card_ptr, c, speed);
-    }
-
-    if(CT_VEHICLE == card_ptr->m_type)//统计车卡
-    {
-        c->m_area->m_vehicle_count++;
-
-        //区域车卡超速
-        module_area_over_speed::instance()->on_enter(card_ptr, c, speed);
-        //车卡考勤
-        module_attendance_vehicle::instance()->on_enter(card_ptr, c, speed);
-    }
-}
-
-void module_area::on_hover(uint64_t card_id,std::shared_ptr<area_hover>&c,double speed)
-{
-    //与考勤,卡数统计,超员,超时无关的区域   直接返回
-    if(AT_OTHER == c->m_area->m_area_type)
-    {
-        return;
-    }
-
-    auto card_ptr=card_list::instance()->get(card_id);
-    if(!card_ptr)
-    {
-        log_error("卡不存在card_id=%d", card_id);
-        return;
-    }
-
-    std::lock_guard<std::mutex> lock(_mutex);
-
-    if(CT_PERSON == card_ptr->m_type)//统计人卡
-    {
-        //区域人卡超员
-        module_area_overman::instance()->on_hover(card_ptr, c, speed, _map);
-        //区域人卡超时
-        module_area_timeout::instance()->on_hover(card_ptr, c, speed, _map);
-    }
-
-    if(CT_VEHICLE == card_ptr->m_type)//统计车卡
-    {
-        //区域车卡超速
-        module_area_over_speed::instance()->on_hover(card_ptr, c, speed, _map);
-        //车卡考勤
-        module_attendance_vehicle::instance()->on_hover(card_ptr, c, speed, _map);
-    }
-}
-
-void module_area::on_leave(uint64_t card_id,std::shared_ptr<area_hover>&c,double speed)
-{
-    //与考勤,卡数统计,超员,超时无关的区域   直接返回
-    if(AT_OTHER == c->m_area->m_area_type)
-    {
-        return;
-    }
-
-    auto card_ptr=card_list::instance()->get(card_id);
-    if(!card_ptr)
-    {
-        log_error("卡不存在card_id=%d", card_id);
-        return;
-    }
-
-    std::lock_guard<std::mutex> lock(_mutex);
-
-    if(CT_PERSON == card_ptr->m_type)//统计人卡
-    {
-        c->m_area->m_person_count--;
-
-        //区域人卡超员
-        module_area_overman::instance()->on_leave(card_ptr, c, speed);
-        //区域人卡超时
-        module_area_timeout::instance()->on_leave(card_ptr, c, speed);
-    }
-
-    if(CT_VEHICLE == card_ptr->m_type)//统计车卡
-    {
-        c->m_area->m_vehicle_count--;
-
-        //区域车卡超速
-        module_area_over_speed::instance()->on_leave(card_ptr, c, speed);
-        //车卡考勤
-        module_attendance_vehicle::instance()->on_leave(card_ptr, c, speed);
-    }
-}
-
-
-

+ 128 - 46
module_service/module_area.h

@@ -11,7 +11,11 @@
 #include"module_const.h"
 #include"module_web.h"
 
-class module_area:public i_thread, public singleton_base<module_area>
+#include"module_attendance_vehicle.h"
+#include"module_area_over_count.h"
+#include"module_area_timeout.h"
+
+class module_area: public singleton_base<module_area>
 {
 private:
     friend class singleton_base<module_area>;
@@ -20,68 +24,146 @@ private:
     }
 
 public:
-    void on_hover(uint64_t card_id,std::shared_ptr<area_hover>&c,double speed);
-    void on_enter(uint64_t card_id,std::shared_ptr<area_hover>&c,double speed);
-    void on_leave(uint64_t card_id,std::shared_ptr<area_hover>&c,double speed);
-
-    /**
-     * @brief 读取数据库中的告警,初始化告警列表
-     */
-    void init()
-    {}
-
-    /**
-     * @brief web前端有用户登录时,反馈给web所有信息
-     */
-    std::string response_login()
+    static void on_enter(uint32_t card_id,std::shared_ptr<area_hover>&c, int32_t type)
     {
-        std::vector<std::shared_ptr<ya_event>> arr;
-        get_all_events(arr);
+        if(0==c->id() || 0==c->mapid())
+        {
+            return;
+        }
+
+        auto card_ptr=card_list::instance()->get(card_list::to_id64(type, card_id));
+        if(!card_ptr)
+        {
+            log_error("卡不存在card_id=%d", card_id);
+            return;
+        }
+
+        c->m_enter_time = card_ptr->m_time/1000;
 
-        if(!arr.empty())//发送给web端
+        if(card_ptr->is_person())//统计人卡
         {
-            return tool_json::evs_to_json(arr);
+            c->m_area->m_person_count++;
         }
 
-        return "";
+        if(card_ptr->is_vehicle())//统计车卡
+        {
+            c->m_area->m_vehicle_count++;
+            //车卡考勤
+            module_attendance_vehicle::instance()->on_enter(card_ptr, c);
+        }
+
+        //区域超员
+        module_area_over_count::instance()->on_enter(card_ptr, c);
+        //区域超时
+        module_area_timeout::instance()->on_enter(card_ptr, c);
+
+        save_his_area_location_enter(card_ptr);
     }
-private:
-    /**
-     * @brief 线程函数
-     */
-    void run()
+
+    static void on_hover(uint32_t card_id,std::shared_ptr<area_hover>&c, int32_t type)
+    {
+        if(0==c->id() || 0==c->mapid())
+        {
+            return;
+        }
+
+        auto card_ptr=card_list::instance()->get(card_list::to_id64(type, card_id));
+        if(!card_ptr)
+        {
+            log_error("卡不存在card_id=%d", card_id);
+            return;
+        }
+
+        //        if(card_ptr->is_person())//人卡
+        //        {
+
+        //        }
+
+        //        if(card_ptr->is_vehicle())//车卡
+        //        {
+
+        //        }
+
+        //区域超时
+        module_area_timeout::instance()->on_hover(card_ptr, c);
+    }
+
+    static void on_leave(uint32_t card_id, std::shared_ptr<area_hover>&c, int32_t type)
     {
-        std::vector<std::shared_ptr<ya_event>> arr;
-        get_all_events(arr);
+        if(0==c->id() || 0==c->mapid())
+        {
+            return;
+        }
 
-        if(!arr.empty())//发送给web端
+        auto card_ptr=card_list::instance()->get(card_list::to_id64(type, card_id));
+        if(!card_ptr)
         {
-            swsClientMgr.send(JSON_CMD_VALUE_PUSH, tool_json::evs_to_json(arr));
+            log_error("卡不存在card_id=%d", card_id);
+            return;
         }
+
+        if(card_ptr->is_person())//统计人卡
+        {
+            c->m_area->m_person_count--;
+        }
+
+        if(card_ptr->is_vehicle())//统计车卡
+        {
+            c->m_area->m_vehicle_count--;
+        }
+
+        //区域超员
+        module_area_over_count::instance()->on_leave(card_ptr, c);
+        //区域超时
+        module_area_timeout::instance()->on_leave(card_ptr, c);
+
+        save_his_area_location_leave(card_ptr);
     }
 
-    /**
-     * @brief 获取所有的告警事件
-     * @param out_data
-     */
-    void get_all_events(std::vector<std::shared_ptr<ya_event>>& arr)
+    ///入库
+    static void save_his_area_location_enter(const std::shared_ptr<card_location_base> card_ptr)
     {
+        auto area_hover_ptr = card_ptr->get_area_hover();
+
+        char sql[LENGTH_SQL] = {0};
+
+        std::string call("add_area_staff");
+        if(card_ptr->is_vehicle())//车卡
         {
-            std::lock_guard<std::mutex> lock(_mutex);
-
-            auto it_map = _map.begin();
-            for(;it_map!=_map.end();++it_map)
-            {
-                arr.push_back(it_map->second);
-                if(ES_DEAL_HELP== it_map->second->m_status)//删除掉已经处理的
-                {
-                    _map.erase(it_map--);
-                }
-            }
+            call="add_area_vehicle";
         }
+
+        std::string start_str = tool_time::to_str_ex(static_cast<uint64_t>(area_hover_ptr->m_enter_time) *1000);
+
+        sprintf(sql, "CALL %s(%s, %d, %d, %d, '%s','%s');", call.c_str(),
+                card_list::to_id64_str(card_ptr->m_type, card_ptr->m_id).c_str(),
+                card_ptr->m_id, area_hover_ptr->id(), area_hover_ptr->mapid(), start_str.c_str(), start_str.c_str());
+
+        tool_db::PushAsync(sql);
     }
 
-    std::map<uint64_t, std::shared_ptr<ya_event>> _map;
+    ///入库
+    static void save_his_area_location_leave(const std::shared_ptr<card_location_base> card_ptr)
+    {
+        auto area_hover_ptr = card_ptr->get_area_hover();
+
+        char sql[LENGTH_SQL] = {0};
+
+        std::string call("add_area_staff");
+        if(card_ptr->is_vehicle())//车卡
+        {
+            call="add_area_vehicle";
+        }
+
+        std::string start_str = tool_time::to_str_ex(static_cast<uint64_t>(area_hover_ptr->m_enter_time) *1000);
+        std::string end_str = tool_time::to_str_ex(card_ptr->m_time);
+
+        sprintf(sql, "CALL %s(%s, %d, %d, %d, '%s','%s');", call.c_str(),
+                card_list::to_id64_str(card_ptr->m_type, card_ptr->m_id).c_str(),
+                card_ptr->m_id, area_hover_ptr->id(), area_hover_ptr->mapid(), start_str.c_str(), end_str.c_str());
+
+        tool_db::PushAsync(sql);
+    }
 };
 
 #endif // MODULE_AREA_H

+ 137 - 0
module_service/module_area_over_count.h

@@ -0,0 +1,137 @@
+#ifndef MODULE_AREA_OVER_COUNT_H
+#define MODULE_AREA_OVER_COUNT_H
+/**
+ * @brief 人员或车辆超员
+ * @author 戴月腾
+ * @date 2018-10-10
+ */
+
+#include <string>
+#include <memory>
+#include <atomic>
+#include <mutex>
+#include <map>
+#include "module_const.h"
+
+
+class module_area_over_count:public singleton_base<module_area_over_count>
+{
+private:
+    friend class singleton_base<module_area_over_count>;
+    module_area_over_count()
+    {
+    }
+
+public:
+
+    void on_enter(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c)
+    {
+        auto area_ptr = c->m_area;
+
+        int limit = area_ptr->m_limit_person_count;
+        EVENT_TYPE ev_type = ET_AREA_OVER_COUNT_PERSON;
+        int cur_value = area_ptr->m_person_count;
+        if(card_ptr->is_vehicle())
+        {
+            limit = area_ptr->m_limit_vehicle_count;
+            ev_type = ET_AREA_OVER_COUNT_VEHICLE;
+            cur_value = area_ptr->m_vehicle_count;
+        }
+
+        //超员配置是否为0,0则不会进行告警
+        if(0 == limit)
+        {
+            return;
+        }
+
+        if(limit <= cur_value)//超员
+        {
+            std::lock_guard<std::mutex> lock(__lock);
+
+            auto ev_ptr = event_list::instance()->get_event_area(area_ptr->id(), ev_type);
+            if(ev_ptr)
+            {
+                event_list::copy_event(card_ptr, ev_ptr);
+
+                ev_ptr->m_limit_value=limit;
+                ev_ptr->m_cur_value=cur_value;
+            }
+            else//从没有告警状态转化为告警状态
+            {
+                ev_ptr = event_list::create_event_area(area_ptr->id(), ev_type);
+
+                event_list::copy_event(card_ptr, ev_ptr);
+
+                ev_ptr->m_limit_value=limit;
+                ev_ptr->m_cur_value=cur_value;
+
+                //保存到数据库
+                event_list::save_event(ev_ptr);
+
+                event_list::instance()->add(ev_ptr->get_list_id(),ev_ptr);
+
+                log_info("区域超员开始:区域id=%d,区域门限=%d,当前卡数=%d, 卡类型=%d",
+                         area_ptr->id(), limit, cur_value, card_ptr->m_type);
+            }
+        }
+    }
+
+//    void on_hover(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c)
+//    {
+
+//    }
+
+    void on_leave(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c)
+    {
+        auto area_ptr = c->m_area;
+
+        int limit = area_ptr->m_limit_person_count;
+        EVENT_TYPE ev_type = ET_AREA_OVER_COUNT_PERSON;
+        int cur_value = area_ptr->m_person_count;
+        if(card_ptr->is_vehicle())
+        {
+            limit = area_ptr->m_limit_vehicle_count;
+            ev_type = ET_AREA_OVER_COUNT_VEHICLE;
+            cur_value = area_ptr->m_vehicle_count;
+        }
+
+        //超员配置是否为0,0则不会进行告警
+        if(0 == limit)
+        {
+            return;
+        }
+
+        if(limit > cur_value)//没有超员
+        {
+            //取消告警状态
+            auto ev_ptr = event_list::instance()->get_event_area(area_ptr->id(), ev_type);
+            if(ev_ptr && !ev_ptr->is_end())
+            {
+                std::lock_guard<std::mutex> lock(__lock);
+                if(ev_ptr->is_end())
+                {
+                    return;
+                }
+
+                event_list::copy_event(card_ptr, ev_ptr);
+
+                ev_ptr->m_limit_value=limit;
+                ev_ptr->m_cur_value=cur_value;
+
+                ev_ptr->m_status = ES_END;
+
+                //保存到数据库
+                event_list::save_event(ev_ptr);
+
+                log_info("区域超员结束:区域id=%d,区域门限=%d,当前卡数=%d, 卡类型=%d",
+                         area_ptr->id(), limit, cur_value, card_ptr->m_type);
+            }
+        }
+    }
+
+private:
+    std::mutex __lock;
+};
+
+
+#endif // MODULE_AREA_OVER_COUNT_H

+ 0 - 3
module_service/module_area_over_speed.cpp

@@ -1,3 +0,0 @@
-#include "module_area_over_speed.h"
-
-

+ 0 - 127
module_service/module_area_over_speed.h

@@ -1,127 +0,0 @@
-#ifndef MODULE_AREA_OVER_SPEED_H
-#define MODULE_AREA_OVER_SPEED_H
-
-/**
-  *@brief 区域超速模块
-  * 当某张车卡速度超过某个区域的最大速度时,发出告警
-  * @author 戴月腾
-  * @date 2018-08-08
-*/
-
-#include <mutex>
-#include <map>
-#include <chrono>
-#include <boost/thread.hpp>
-#include <boost/enable_shared_from_this.hpp>
-#include "module_const.h"
-
-/**
- * @brief 区域超速类。当某张车卡速度超过某个区域的最大速度时,发出告警, 单例
- */
-class module_area_over_speed:public singleton_base<module_area_over_speed>
-{
-private:
-    friend class singleton_base<module_area_over_speed>;
-    module_area_over_speed()
-    {
-    }
-
-public:
-
-    void on_enter(std::shared_ptr<card> card_ptr,std::shared_ptr<area_hover>&c,double speed)
-    {
-//        card_ptr->m_speed = speed;
-//        c->m_vehicle_area_over_speed_count=0;
-//        c->m_vehicle_area_normal_speed_count=0;
-//        c->m_is_area_over_speed_vehicle=false;
-
-//        auto area_ptr = c->m_area;
-//        if(area_ptr->m_limit_speed > speed)//速度正常
-//        {
-//            c->m_vehicle_area_normal_speed_count++;
-//        }
-//        else//超速
-//        {
-//            c->m_vehicle_area_over_speed_count++;
-//        }
-    }
-
-    void on_hover(std::shared_ptr<card> card_ptr,std::shared_ptr<area_hover>&c,double speed,
-                  std::map<uint64_t, std::shared_ptr<ya_event>>& ev_map)
-    {
-        card_ptr->m_speed = speed;
-
-//        auto area_ptr = c->m_area;
-//        if(area_ptr->m_limit_speed > speed)//速度正常
-//        {
-//            c->m_vehicle_area_normal_speed_count++;
-//        }
-//        else//超速
-//        {
-//            c->m_vehicle_area_over_speed_count++;
-//        }
-
-//        //确定超速
-//        if(global_constant::AREA_SPEED_COUNT_LIMIT <= c->m_vehicle_area_over_speed_count)
-//        {
-//            c->m_vehicle_area_over_speed_count=global_constant::AREA_SPEED_COUNT_LIMIT;
-
-//            auto ev_ptr = tool_other::find_event(card_ptr->m_id, ET_CARD_AREA_OVER_SPEED, ev_map);
-//            if(ev_ptr)
-//            {
-//                ev_ptr->m_limit_value=area_ptr->m_limit_speed;
-//                ev_ptr->m_cur_value=card_ptr->m_speed;
-//            }
-//            else//从没有告警状态转化为告警状态
-//            {
-//                c->m_is_area_over_speed_vehicle=true;
-//                c->m_vehicle_area_normal_speed_count=0;
-
-//                auto ev_ptr = tool_other::create_event(OT_CARD, card_ptr->m_id, ET_CARD_AREA_OVER_SPEED);
-
-//                tool_other::copy_event(card_ptr, ev_ptr);
-
-//                ev_ptr->m_limit_value = area_ptr->m_limit_speed;
-//                ev_ptr->m_cur_value = card_ptr->m_speed;
-
-//                //保存到数据库
-//                tool_db::save_event(ev_ptr);
-
-//                tool_other::insert_event(ev_ptr, ev_map);
-//            }
-//        }
-
-//        //确定速度正常
-//        if(global_constant::AREA_SPEED_COUNT_LIMIT <= c->m_vehicle_area_normal_speed_count)
-//        {
-//            c->m_vehicle_area_normal_speed_count=global_constant::AREA_SPEED_COUNT_LIMIT;
-
-//            if(c->m_is_area_over_speed_vehicle)
-//            {
-//                c->m_is_area_over_speed_vehicle = false;
-//                c->m_vehicle_area_over_speed_count=0;
-
-//                auto ev_ptr = tool_other::find_event(card_ptr->m_id, ET_CARD_AREA_OVER_SPEED, ev_map);
-//                if(ev_ptr)
-//                {
-//                    ev_ptr->m_status = ES_END;
-
-//                    ev_ptr->m_limit_value = area_ptr->m_limit_speed;
-//                    ev_ptr->m_cur_value = speed;
-//                    ev_ptr->m_cur_time = std::chrono::system_clock::now();
-
-//                    //保存到数据库
-//                    tool_db::save_event(ev_ptr);
-//                }
-//            }
-//        }
-    }
-
-    void on_leave(std::shared_ptr<card> card_ptr,std::shared_ptr<area_hover>&c,double speed)
-    {
-
-    }
-};
-typedef std::shared_ptr<module_area_over_speed> module_area_over_speed_ptr;
-
-#endif

+ 0 - 3
module_service/module_area_overman.cpp

@@ -1,3 +0,0 @@
-#include "module_area_overman.h"
-#include"module_const.h"
-

+ 0 - 92
module_service/module_area_overman.h

@@ -1,92 +0,0 @@
-#ifndef MODULE_AREA_OVERMAN_H
-#define MODULE_AREA_OVERMAN_H
-
-/**
-  *@brief 区域超员模块:当某个区域人数超过指定值时开始告警,当低于指定值时停止告警
-  *@author 戴月腾
-  *@date 2018-08-26
-*/
-
-#include <string>
-#include <memory>
-#include <atomic>
-#include <mutex>
-#include <map>
-#include "module_const.h"
-
-/**
- * @brief 区域超员模块:当某个区域人数超过指定值时开始告警,当低于指定值时停止告警
- */
-class module_area_overman:public singleton_base<module_area_overman>
-{
-private:
-    friend class singleton_base<module_area_overman>;
-    module_area_overman()
-    {
-    }
-
-public:
-
-    void on_enter(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed)
-    {
-
-    }
-
-    void on_hover(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed,
-                  std::map<uint64_t, std::shared_ptr<ya_event>>& ev_map)
-    {
-        auto area_ptr = c->m_area;
-        if(area_ptr->m_limit_person_count <= area_ptr->m_person_count)//超员
-        {
-            auto ev_ptr = tool_other::find_event(area_ptr->id(), ET_AREA_OVER_COUNT_PERSON,ev_map);
-            if(ev_ptr)
-            {
-                ev_ptr->m_limit_value=area_ptr->m_limit_person_count;
-                ev_ptr->m_cur_value=area_ptr->m_person_count;
-            }
-            else//从没有告警状态转化为告警状态
-            {
-                area_ptr->m_is_over_person = true;
-                auto ev_ptr = tool_other::create_event(OT_AREA, area_ptr->id(), ET_AREA_OVER_COUNT_PERSON);
-
-                tool_other::copy_event(card_ptr, ev_ptr);
-
-                ev_ptr->m_limit_value = area_ptr->m_limit_person_count;
-                ev_ptr->m_cur_value = area_ptr->m_person_count;
-
-                //保存到数据库
-                tool_db::save_event(ev_ptr);
-
-                tool_other::insert_event(ev_ptr, ev_map);
-            }
-        }
-        else//取消告警状态
-        {
-            if(area_ptr->m_is_over_person)
-            {
-                area_ptr->m_is_over_person = false;
-                auto ev_ptr = tool_other::find_event(area_ptr->id(), ET_AREA_OVER_COUNT_PERSON,ev_map);
-                if(ev_ptr)
-                {
-                    ev_ptr->m_status = ES_END;
-
-                    ev_ptr->m_limit_value=area_ptr->m_limit_person_count;
-                    ev_ptr->m_cur_value = area_ptr->m_person_count;
-                    ev_ptr->m_cur_time = std::chrono::system_clock::now();
-
-                    //保存到数据库
-                    tool_db::save_event(ev_ptr);
-                }
-            }
-        }
-    }
-
-    void on_leave(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed)
-    {
-
-    }
-};
-typedef std::shared_ptr<module_area_overman>  module_area_overman_ptr;
-
-
-#endif // MODULE_AREA_OVERMAN_H

+ 0 - 3
module_service/module_area_timeout.cpp

@@ -1,3 +0,0 @@
-#include "module_area_timeout.h"
-#include <boost/bind.hpp>
-

+ 84 - 60
module_service/module_area_timeout.h

@@ -1,12 +1,11 @@
 #ifndef MODULE_AREA_TIMEOUT_H
 #define MODULE_AREA_TIMEOUT_H
-
 /**
-  *@brief 区域超时模块 2018-08-26 戴月腾修改
-  * 当某张人卡在某个区域的时间超过指定值时,会发出区域超时告警
-  * @author 陈欧美
-  * @date 2018-08-05
-*/
+ * @brief 区域超时
+ * @author 戴月腾
+ * @date 2018-10-10
+ */
+
 
 #include <mutex>
 #include <map>
@@ -15,12 +14,8 @@
 #include <boost/enable_shared_from_this.hpp>
 #include "point.h"
 #include "module_const.h"
-#include"module_const.h"
 
 
-/**
- * @brief 当某张人卡在某个区域的时间超过指定值时,会发出区域超时告警
- */
 class module_area_timeout:public singleton_base<module_area_timeout>
 {
 private:
@@ -30,68 +25,97 @@ private:
     }
 
 public:
-    void on_enter(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed)
+    void on_enter(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c)
     {
-        //c->m_is_area_over_time_person=false;
-    }
+//        c->m_enter_time = card_ptr->m_time/1000;
 
-    void on_hover(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed,
-                  std::map<uint64_t, std::shared_ptr<ya_event>>& ev_map)
-    {
-        auto area_ptr = c->m_area;
-
-        //int seconds = tool_time::elapse_seconds(c->m_enter_time);
-
-//        if(seconds > area_ptr->m_limit_time_second)//发生告警
+//        EVENT_TYPE ev_type = card_ptr->is_person() ? ET_CARD_AREA_OVER_TIME_PERSON : ET_AREA_OVER_COUNT_VEHICLE;
+//        //中途服务器宕机处理
+//        if(auto ev_ptr = event_list::instance()->get(card_ptr->m_id, ev_type))
 //        {
-//            auto ev_ptr = tool_other::find_event(card_ptr->m_id, ET_CARD_AREA_OVER_TIME_PERSON, ev_map);
-//            if(ev_ptr)
-//            {
-//                ev_ptr->m_limit_value=area_ptr->m_limit_time_second;
-//                ev_ptr->m_cur_value=seconds;
-//            }
-//            else//从没有告警状态转化为告警状态
-//            {
-//                c->m_is_area_over_time_person=true;//发生告警
-//                auto ev_ptr = tool_other::create_event(OT_CARD, card_ptr->m_id, ET_CARD_AREA_OVER_TIME_PERSON);
-
-//                tool_other::copy_event(card_ptr, ev_ptr);
-
-//                ev_ptr->m_limit_value = area_ptr->m_limit_time_second;
-//                ev_ptr->m_cur_value = seconds;
-
-//                //保存到数据库
-//                tool_db::save_event(ev_ptr);
-
-//                tool_other::insert_event(ev_ptr, ev_map);
-//            }
+//            c->m_enter_time = std::chrono::system_clock::to_time_t(ev_ptr->m_cur_time);
 //        }
 //        else
 //        {
-//            if(c->m_is_area_over_time_person)
-//            {
-//                c->m_is_area_over_time_person = false;
-//                auto ev_ptr = tool_other::find_event(card_ptr->m_id, ET_CARD_AREA_OVER_TIME_PERSON, ev_map);
-//                if(ev_ptr)
-//                {
-//                    ev_ptr->m_status = ES_END;
-
-//                    ev_ptr->m_limit_value = area_ptr->m_limit_time_second;
-//                    ev_ptr->m_cur_value = seconds;
-//                    ev_ptr->m_cur_time = std::chrono::system_clock::now();
-
-//                    //保存到数据库
-//                    tool_db::save_event(ev_ptr);
-//                }
-//            }
+//            std::time(&c->m_enter_time);
 //        }
     }
 
-    void on_leave(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed)
+    void on_hover(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c)
     {
+        auto area_ptr = c->m_area;
+
+        int limit = area_ptr->m_limit_person_second;
+        EVENT_TYPE ev_type = ET_CARD_AREA_OVER_TIME_PERSON;
+        if(card_ptr->is_vehicle())
+        {
+            limit = area_ptr->m_limit_vehicle_second;
+            ev_type = ET_CARD_AREA_OVER_TIME_VEHICLE;
+        }
+
+        int seconds = tool_time::elapse_seconds(c->m_enter_time);
+
+        if(seconds > limit)//发生告警
+        {
+            auto ev_ptr = event_list::instance()->get_event_card(card_ptr->m_id, card_ptr->m_type, ev_type);
+            if(ev_ptr)
+            {
+                event_list::copy_event(card_ptr, ev_ptr);
+
+                ev_ptr->m_limit_value = limit;
+                ev_ptr->m_cur_value = seconds;
+            }
+            else//从没有告警状态转化为告警状态
+            {
+                ev_ptr = event_list::create_event_card(card_ptr->m_id, card_ptr->m_type, ev_type);
+
+                event_list::copy_event(card_ptr, ev_ptr);
+
+                ev_ptr->m_limit_value = limit;
+                ev_ptr->m_cur_value = seconds;
+
+                //保存到数据库
+                event_list::save_event(ev_ptr);
+
+                event_list::instance()->add(ev_ptr->get_list_id(),ev_ptr);
+
+                log_info("卡区域超时开始:卡id=%d,卡type=%d,区域id=%d,时间门限=%d,呆的时间长度=%d",
+                         card_ptr->m_id, card_ptr->m_type,
+                         area_ptr->id(), limit, seconds);
+            }
+        }
+    }
+
+    void on_leave(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c)
+    {
+        auto area_ptr = c->m_area;
+
+        int limit = area_ptr->m_limit_person_second;
+        EVENT_TYPE ev_type = ET_CARD_AREA_OVER_TIME_PERSON;
+        if(card_ptr->is_vehicle())
+        {
+            limit = area_ptr->m_limit_vehicle_second;
+            ev_type = ET_CARD_AREA_OVER_TIME_VEHICLE;
+        }
+
+        auto ev_ptr = event_list::instance()->get_event_card(card_ptr->m_id, card_ptr->m_type, ev_type);
+        if(ev_ptr && !ev_ptr->is_end())//有超时告警就删除
+        {
+            event_list::copy_event(card_ptr, ev_ptr);
+
+            ev_ptr->m_limit_value = limit;
+            ev_ptr->m_cur_value = tool_time::elapse_seconds(c->m_enter_time);
+
+            ev_ptr->m_status = ES_END;
+
+            //保存到数据库
+            event_list::save_event(ev_ptr);
 
+            log_info("卡区域超时结束:卡id=%d,卡type=%d,区域id=%d,时间门限=%d",
+                     card_ptr->m_id, card_ptr->m_type,
+                     area_ptr->id(), limit);
+        }
     }
 };
-typedef std::shared_ptr<module_area_timeout> module_area_timeout_ptr;
 
 #endif // MODULE_AREA_TIMEOUT_H

+ 0 - 9
module_service/module_attendance_person.cpp

@@ -1,9 +0,0 @@
-#include "module_attendance_person.h"
-#include "log.h"
-#include"module_const.h"
-#include <time.h>
-#include<chrono>
-#include<stdio.h>
-#include<db_api/CDBConnPool.h>
-
-

+ 186 - 77
module_service/module_attendance_person.h

@@ -8,6 +8,7 @@
   *@date 2018-08-03
 */
 
+#include"math.h"
 #include <memory>
 #include <mutex>
 #include <map>
@@ -19,6 +20,7 @@
 #include"area.h"
 #include"site_area.h"
 #include"module_const.h"
+#include"module_area.h"
 
 /**
  * @brief 主要是针对人卡进行考勤,人卡从井上切换到井下为考勤开始,人卡从井下切换到井上为考勤结束
@@ -34,113 +36,220 @@ private:
 public:
     /**
      * @brief 进入分站覆盖区域处理,考勤
-     * @param card_id
-     * @param enter_site
+     * @param card_ptr
+     * @param site_ptr
      */
-    void enter_site(uint64_t card_id,int enter_site,uint64_t type,
-                    const std::shared_ptr<area_hover> area_hover_ptr)
+    void enter_site(std::shared_ptr<card_location_base> card_ptr, std::shared_ptr<site> site_ptr)
     {
-        auto card_ptr=card_list::instance()->get(tool_other::to_uint64_cardid(type, card_id));
-        if(!card_ptr)
-        {
-            log_error("卡不存在card_id=%ld, type=%ld", card_id, type);
-            return;
-        }
-
-        auto site_ptr=sit_list::instance()->get(enter_site);
-        if(!site_ptr)
-        {
-            log_error("在分站列表中找不到分站,分站id=%d", enter_site);
-            return;
-        }
+        auto site_area_ptr = card_ptr->get_site_area();
+        auto mine_tool_ptr = card_ptr->get_mine_tool();
 
         // 从井下切换到井上为考勤结束
-        if(tool_other::is_up_site(site_ptr->m_reader_type_id))
+        if(site_ptr->is_up_site())
         {
-            if(tool_other::is_attendance(card_ptr->m_stat_attendance))
+            if(mine_tool_ptr->is_attendance())
             {
                 //考勤结束
-                card_ptr->m_stat_attendance=AS_NOT_ATTENDANCE;
+                mine_tool_ptr->m_stat_attendance=AS_NOT_ATTENDANCE;
 
                 //作为一条结束考勤记录保存到数据库
-                tool_db::save_attendance(card_ptr, area_hover_ptr);
+                tool_db::save_attendance(card_ptr);
 
-                log_debug("人卡考勤结束:site_id=%d,reader_type_id=%d,stat_attendance=%d",
-                          site_ptr->m_id,site_ptr->m_reader_type_id,card_ptr->m_stat_attendance);
+                person_card_up_mine(card_ptr);
+
+                log_info("人卡考勤结束:卡id=%d,卡type=%d,分站id=%d,分站reader_type_id=%d,stat_attendance=%d",
+                         card_ptr->m_id, card_ptr->m_type,
+                         site_ptr->m_id,site_ptr->m_reader_type_id,mine_tool_ptr->m_stat_attendance);
             }
         }
-
-        // 从井上切换到井下为考勤开始
-        if(!tool_other::is_up_site(site_ptr->m_reader_type_id))
+        else// 从井上切换到井下为考勤开始
         {
-            if(!tool_other::is_attendance(card_ptr->m_stat_attendance))
+            if(!mine_tool_ptr->is_attendance())
             {
                 //考勤开始
-                card_ptr->m_stat_attendance=AS_ATTENDANCE;
-                //card_ptr->m_attendance_start_time=std::chrono::system_clock::now();
-                std::time_t start= card_ptr->m_time/1000;
-                card_ptr->m_attendance_start_time=std::chrono::system_clock::from_time_t(start);
+                mine_tool_ptr->m_stat_attendance=AS_ATTENDANCE;
+
+                mine_tool_ptr->m_attendance_start_time=
+                        std::chrono::system_clock::time_point(std::chrono::milliseconds(card_ptr->m_time));
 
                 //作为一条开始考勤记录保存到数据库
-                tool_db::save_attendance(card_ptr, area_hover_ptr);
+                tool_db::save_attendance(card_ptr);
 
-                log_debug("人卡考勤开始:site_id=%d,reader_type_id=%d,stat_attendance=%d",
-                          site_ptr->m_id,site_ptr->m_reader_type_id,card_ptr->m_stat_attendance);
+                log_info("人卡考勤开始:卡id=%d,卡type=%d,分站id=%d,分站reader_type_id=%d,stat_attendance=%d",
+                         card_ptr->m_id, card_ptr->m_type,
+                         site_ptr->m_id,site_ptr->m_reader_type_id,mine_tool_ptr->m_stat_attendance);
             }
         }
     }
 
+//    /**
+//     * @brief 离开现有分站处理,记录现有分站的进出时间和地点
+//     * @param card_ptr
+//     * @param site_ptr
+//     */
+//    void leave_site(std::shared_ptr<card_location_base> card_ptr, std::shared_ptr<site> site_ptr)
+//    {
+
+//    }
+
     /**
-     * @brief 离开现有分站处理,记录现有分站的进出时间和地点
-     * @param card_id
-     * @param enter_site
+     * @brief 手工升井函数
      */
-    void leave_site(uint64_t card_id,int enter_site,uint64_t type,
-                    const std::shared_ptr<area_hover> area_hover_ptr)
+    void handle_up_mine(sio::message::ptr const& data)
     {
+        std::vector<sio::message::ptr> card_vec;
+        if(!tool_map::try_get_value(card_vec, JSON_ROOT_KEY_DATA, data) || card_vec.size() == 0)
+        {
+            log_error("手工升井,web发来的数据data字段为空 或者不是数组");
+            return;
+        }
+
+        std::vector<sio::message::ptr>::const_iterator it_card = card_vec.begin();
+        int type = 0;
+        std::string s_card_id;
+        for(; it_card != card_vec.end(); ++it_card)
+        {
+            if(!tool_map::try_get_value(s_card_id, JSON_KEY_CALL_CARD_CARD_ID, (*it_card))
+               ||!tool_map::try_get_value(type, JSON_KEY_CALL_CARD_CARD_TYPE_ID, (*it_card)))
+            {
+                log_error("手工升井,web发来的数据 card_id 或 card_type格式不对");
+                continue;
+            }
 
+            uint32_t id = tool_other::id64_to_id(s_card_id);
+            auto card_ptr = card_list::instance()->get(card_list::to_id64(type, id));
+            if(card_ptr && card_ptr->is_person())
+            {
+                std_debug("手工升井,处理,卡id=%d,卡type=%d", id, type);
+                log_info("手工升井,处理,卡id=%d,卡type=%d", id, type);
+
+                auto mine_tool_ptr = card_ptr->get_mine_tool();
+                if(mine_tool_ptr->is_attendance())
+                {
+                    //考勤结束
+                    mine_tool_ptr->m_stat_attendance=AS_NOT_ATTENDANCE;
+
+                    //作为一条结束考勤记录保存到数据库
+                    tool_db::save_attendance(card_ptr);
+                }
+
+                auto area_hover_ptr = card_ptr->get_area_hover();
+                if(0!=area_hover_ptr->id() && 0!=area_hover_ptr->mapid())
+                {
+                    module_area::save_his_area_location_leave(card_ptr);
+                }
+
+                person_card_up_mine(card_ptr);
+            }
+            else
+            {
+                log_error("手工升井,在全局列表中找不到卡,卡id=%d,卡type=%d", id, type);
+            }
+        }
     }
-    /**
-     * @brief 手工升井函数
-     */
-    void up_well(std::vector<std::string>& card_ids)
+
+private:
+    ///1.人卡升井要发送json串给前端。 具体看card_up_mine函数,
+    ///3.人卡升井要清除卡相关信息,区域相关,分站相关,考勤相关,清除定时器,
+    ///速度,状态 呼救 呼叫 告警相关。即保留基础信息,其他的重置。
+    static void person_card_up_mine(std::shared_ptr<card_location_base> card_ptr)
     {
-        //    std::chrono::system_clock::time_point time_current = std::chrono::system_clock::now();
-        //    std::vector<std::string> ids;
-
-        //    {
-        //        //std::lock_guard<std::mutex> lock(m_mutex);
-        //        for(auto iter = card_ids.begin(); iter != card_ids.end(); ++iter)
-        //        {
-        //            auto iter_card = g_card_map_ptr->find(*iter);
-        //            if(g_card_map_ptr->end() == iter_card)
-        //            {
-        //                continue;
-        //            }
-        //            if(!iter_card->second->is_attendance) // 该卡当前没在井下,不能形成考勤记录
-        //            {
-        //                // 该卡当前没在井下,不能形成考勤记录
-        //                continue;
-        //            }
-
-        ////            // 添加到考勤处理列表
-        ////            iter_card->second->last_status_well = enum_status_well::STATUS_WELL_UP;
-        ////            iter_card->second->time_end = time_current;
-        ////            attendances.push_back(iter_card->second);
-
-        //            ids.push_back(*iter);
-        //        }
-        //    }
-
-        //    // 插入考勤记录到数据库
-        //    for(auto iter = ids.begin(); iter != ids.end(); ++iter)
-        //    {
-        //        g_card_map_ptr->erase(*iter);
-
-        //        // 插入考勤记录到数据库
-        //    }
+        if (card_ptr->m_display)
+        {
+            std::string str = to_json_card_up(card_ptr);
+            if(!str.empty())
+            {
+                tool_other::send_json(JSON_CMD_VALUE_PUSH, str);
+            }
+        }
+		//删除
+		card_ptr->del_card_pos();
+
+        // 升井 删除所有报警信息
+        for(int i=0; i < CARD_EVENT_COUNT_MAX; i++ )
+        {
+            if (i == EVENT_TYPE::ET_CARD_LOW_POWER_SERIOUS)
+            {
+                continue;
+            }
+
+            auto ev_ptr = event_list::instance()->get_event_card(
+                        card_ptr->m_id, card_ptr->m_type, static_cast<EVENT_TYPE>(i));
+            if(ev_ptr && !ev_ptr->is_end()) //
+            {
+                event_list::copy_event(card_ptr, ev_ptr);
+
+                ev_ptr->m_status = ES_END;
+
+                event_list::save_event(ev_ptr);
+            }
+        }
+
+        card_ptr->clear();
     }
 
+    ///升井json发给web
+    static std::string to_json_card_up(std::shared_ptr<card_location_base> card_ptr)
+    {
+        auto site_area_ptr = card_ptr->get_site_area();
+        if(!site_area_ptr || site_area_ptr->is_invalid())
+        {
+            return "";
+        }
+
+        auto mine_tool_ptr = card_ptr->get_mine_tool();
+
+        rapidjson::Document doc(rapidjson::kObjectType);
+        rapidjson::Value data(rapidjson::kArrayType);
+        rapidjson::Document::AllocatorType& allocator=doc.GetAllocator();
+
+        //卡号
+        std::string id = card_list::to_id64_str(card_ptr->m_type, card_ptr->m_id);
+        tool_json::push_back(data, id, allocator);
+
+        //x,y坐标
+        data.PushBack(card_ptr->x, allocator);
+        data.PushBack(card_ptr->y, allocator); //CFunctions::round(card->y_offset_after(),2)
+
+        //入井时间戳
+        uint64_t t = tool_time::to_ms(mine_tool_ptr->m_attendance_start_time);	//转为ms
+        data.PushBack(t, allocator);
+
+        //进入区域时间戳
+        data.PushBack(0, allocator);
+
+        //接收时间戳
+        data.PushBack(0, allocator);
+        //工作时长
+        t = tool_time::now_to_ms() - tool_time::to_ms(mine_tool_ptr->m_attendance_start_time);	//转为ms
+        data.PushBack(t, allocator);
+
+        //地图编号
+        data.PushBack(0, allocator);
+        //区域编号
+        data.PushBack(0, allocator);
+        //部门编号
+        data.PushBack(card_ptr->m_deptid, allocator);
+
+        //状态
+        data.PushBack(0, allocator);
+        //运行状态
+        data.PushBack(card_ptr->m_stat, allocator);
+        //业务状态
+        data.PushBack(0, allocator);
+        //速度
+        data.PushBack(card_ptr->m_speed, allocator);
+
+        doc.AddMember(JSON_ROOT_KEY_CMD,JSON_CMD_VALUE_UP_MINE, allocator);
+        //doc.AddMember(JSON_ROOT_KEY_VERSION,INTERFACE_VERSION, allocator);
+        doc.AddMember(JSON_ROOT_KEY_DATA, data, allocator);
+
+        rapidjson::StringBuffer sb;
+        rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
+        doc.Accept(writer);
+
+        return sb.GetString();
+    }
 };
 
 #endif // MODULE_ATTENDANCE_PERSON_H

+ 0 - 2
module_service/module_attendance_vehicle.cpp

@@ -1,2 +0,0 @@
-#include "module_attendance_vehicle.h"
-

+ 86 - 30
module_service/module_attendance_vehicle.h

@@ -16,6 +16,7 @@
 #include <vector>
 #include <set>
 #include "module_const.h"
+#include "common_tool.h"
 
 /**
  * @brief 车辆进入某些特定区域,结束考勤;从特定区域进入其他区域,开始考勤, 单例
@@ -29,45 +30,100 @@ private:
     }
 
 public:
-    void on_enter(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed)
+    void on_enter(std::shared_ptr<card_location_base> card_ptr, std::shared_ptr<area_hover>&c)
     {
-        //card_ptr->m_attendance_start_time=std::chrono::system_clock::now();
+        auto mine_tool_ptr = card_ptr->get_mine_tool();
+
+        auto area_ptr = c->m_area;
+
+        //从考勤状态转换为结束考勤
+        if(is_attendance_area(area_ptr->m_id, card_ptr->get_vehicle_type_id()))
+        {
+            if(mine_tool_ptr->is_attendance())
+            {
+                //考勤结束
+                mine_tool_ptr->m_stat_attendance=AS_NOT_ATTENDANCE;
+
+                //作为一条结束考勤记录保存到数据库
+                tool_db::save_attendance(card_ptr);
+
+                log_info("车卡考勤结束:卡id=%d,卡type=%d,区域id=%d, stat_attendance=%d",
+                          card_ptr->m_id, card_ptr->m_type,
+                          area_ptr->m_id,mine_tool_ptr->m_stat_attendance);
+            }
+        }
+        else//没在考勤状态转换为考勤状态
+        {
+            if(!mine_tool_ptr->is_attendance())
+            {
+                //考勤开始
+                mine_tool_ptr->m_stat_attendance=AS_ATTENDANCE;
+                mine_tool_ptr->m_attendance_start_time=
+                        std::chrono::system_clock::time_point(std::chrono::milliseconds(card_ptr->m_time));
+
+                //作为一条开始考勤记录保存到数据库
+                tool_db::save_attendance(card_ptr);
+
+                log_info("车卡考勤开始:卡id=%d,卡type=%d,区域id=%d, stat_attendance=%d",
+                          card_ptr->m_id, card_ptr->m_type,
+                          area_ptr->m_id,mine_tool_ptr->m_stat_attendance);
+            }
+        }
     }
 
-    void on_hover(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed,
-                  event_map& ev_map)
+//    void on_hover(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c)
+//    {
+//    }
+
+
+//    void on_leave(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c)
+//    {
+//    }
+
+    void init_attendance_area_from_db()
     {
-//        auto area_ptr = c->m_area;
-
-//        //从考勤状态转换为结束考勤
-//        if(AT_NOT_ATTENDANCE == area_ptr->m_area_type)
-//        {
-//            if(AS_ATTENDANCE == card_ptr->m_stat_attendance)
-//            {
-//                card_ptr->m_stat_attendance = AS_NOT_ATTENDANCE;
-
-//                //作为一条结束考勤记录保存到数据库
-//                tool_db::save_attendance(card_ptr);
-//            }
-//        }
-//        else //没在考勤状态转换为考勤状态
-//        {
-//            if(AS_ATTENDANCE != card_ptr->m_stat_attendance)
-//            {
-//                card_ptr->m_stat_attendance = AS_ATTENDANCE;
-
-//                //作为一条考勤记录保存到数据库
-//                tool_db::save_attendance(card_ptr);
-//            }
-//        }
-    }
+        const char *sql = "select a.area_id, a.att_rule_id,  vt.vehicle_type_id \
+                from dat_att_rule_area a, dat_att_rule_vehicle_type  vt, dat_att_rule r\
+                where a.att_rule_id=vt.att_rule_id and a.att_rule_id=r.att_rule_id;";
+        std::string Error;
+        YADB::CDBResultSet DBRes;
+        sDBConnPool.Query(sql,DBRes,Error);
+        if(!Error.empty())
+            log_error("初始化attendance_area Error,%s",Error.c_str());
+        uint64_t nCount = DBRes.GetRecordCount( Error );
+        if (nCount > 0)
+        {
+            log_info( "init_attendance_area_from_db. The record count=%ld\n", nCount );
+
+            while ( DBRes.GetNextRecod(Error) )
+            {
+                int area_id  = 0;
+                DBRes.GetField( "area_id",area_id, Error );
+
+                int att_rule_id  = 0;
+                DBRes.GetField( "att_rule_id",att_rule_id, Error );
 
+                int vehicle_type_id  = 0;
+                DBRes.GetField( "vehicle_type_id",vehicle_type_id, Error );
+
+                m_map.insert(std::make_pair(to_list_id(area_id, vehicle_type_id), att_rule_id));
+            }
+        }
+    }
 
-    void on_leave(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed)
+private:
+    bool is_attendance_area(int area_id, int vehicle_type_id)
     {
+        return  m_map.end() != m_map.find(to_list_id(area_id, vehicle_type_id));
+    }
 
+    uint64_t to_list_id(int area_id, int vehicle_type_id)
+    {
+        return (static_cast<uint64_t>(area_id)<<32) | static_cast<uint64_t>(vehicle_type_id);
     }
+
+    ///area_id<<32| vehicle_type_id; att_rule_id
+    std::unordered_map<uint64_t, int> m_map;
 };
-typedef std::shared_ptr<module_attendance_vehicle>  module_attendance_vehicle_ptr;
 
 #endif // MODULE_ATTENDANCE_VEHICLE_H

+ 160 - 132
module_service/module_call.cpp

@@ -7,44 +7,6 @@
 #include <chrono>
 #include<algorithm>
 
-/**
- * @brief 呼叫类型 全员 定员
- */
-enum CALL_CARD_TYPE
-{
-    /// 全员呼叫
-    CCT_CALL_ALL = 0,
-    /// 定员
-    CCT_CALL_APOINT=1,
-};
-
-/**
- * @brief 呼叫等级 一般呼叫  紧急呼叫
- */
-enum CALL_CARD_LEVEL
-{
-    /// 呼叫等级: 1  一般呼叫
-    CALL_LEVEL_NORMAL=1,
-    /// 呼叫等级: 2  紧急呼叫
-    CALL_LEVEL_CRITICAL=2
-};
-
-/**
- * @brief 呼叫状态
- */
-enum CALL_STATE{
-    ///无呼叫信息
-    CALL_NONE = 0,
-    ///呼叫成功
-    CALL_SUCCESSED = 1,
-    ///呼叫中
-    CALL_ING = 2,
-    ///呼叫失败
-    CALL_FAILED = 3,
-
-    ///呼叫结束
-    CALL_END=100
-};
 
 void module_call::run()
 {
@@ -57,9 +19,21 @@ void module_call::run()
         return ;
     }
     //转发给web
-    swsClientMgr.send(JSON_CMD_VALUE_PUSH, to_call_card_list_json(arr));
+    tool_other::send_json(JSON_CMD_VALUE_PUSH, to_call_card_list_json(arr));
 
     //将呼叫命令发送给标识卡终端
+    call_site_map site_map;
+    get_site_map(arr, site_map);
+
+    if(!site_map.empty())
+    {
+        send_to_sites(site_map);
+    }
+}
+
+void module_call::rev_from_card_resp(std::shared_ptr<card_location_base> card_ptr)
+{
+    card_ptr->get_mine_tool()->m_status_call = CALL_SUCCESSED;
 }
 
 /*
@@ -77,28 +51,31 @@ web发给采集:发起呼叫
     }
 }
 */
-void module_call::accept_call(const rapidjson::Document& node_data)
+void module_call::accept_call(sio::message::ptr const& data)
 {
-    int call_type = -1, call_level = -1, call_time_out;
+    int call_type = -1, call_level = -1, call_time_interval=-1;
+    uint32_t call_time_out = 0;
     std::string user_name;
 
-    if(!tool_json::try_get_value(call_type, JSON_KEY_CALL_CARD_CALL_TYPE, node_data)
-            || !tool_json::try_get_value(call_level, JSON_KEY_CALL_CARD_CALL_LEVEL, node_data)
-            || !tool_json::try_get_value(call_time_out, JSON_KEY_CALL_CARD_CALL_TIME_OUT, node_data)
-            || !tool_json::try_get_value(user_name, JSON_KEY_CALL_CARD_USER_NAME, node_data)
+    if(!tool_map::try_get_value(call_type, JSON_KEY_CALL_CARD_CALL_TYPE, data)
+            || !tool_map::try_get_value(call_level, JSON_KEY_CALL_CARD_CALL_LEVEL, data)
+            || !tool_map::try_get_value(call_time_out, JSON_KEY_CALL_CARD_CALL_TIME_OUT, data)
+            || !tool_map::try_get_value(user_name, JSON_KEY_CALL_CARD_USER_NAME, data)
+            || !tool_map::try_get_value(call_time_interval, JSON_KEY_CALL_CARD_CALL_TIME, data)
             )
     {
-        log_error("收到的json不对,解析不出int call_type = -1, call_level = -1, call_time_out,user_name");
-        return;
+        log_error("发起呼叫: 收到的json不对,解析不出call_type = -1, call_level = -1, \
+                  call_time_out=-1, call_time_interval=-1,user_name");
+                return;
     }
 
     if(user_name.empty())
     {
-        log_error("user_name用户名为空");
+        log_error("发起呼叫: user_name用户名为空");
         return;
     }
 
-    std::vector<call_card_ptr> arr;//结果集
+    std::vector<call_card_ptr> result_arr;//结果集
 
     call_user_ptr user_ptr;
     if(CCT_CALL_ALL==call_type)// 全员
@@ -107,6 +84,7 @@ void module_call::accept_call(const rapidjson::Document& node_data)
 
         user_ptr->call_time=std::chrono::system_clock::now();
         user_ptr->call_time_out=call_time_out;
+        user_ptr->call_time_interval = call_time_interval;
         user_ptr->call_type_id=call_type;
         user_ptr->call_level_id=call_level;
         user_ptr->user_name=user_name;
@@ -114,11 +92,12 @@ void module_call::accept_call(const rapidjson::Document& node_data)
         call_card_ptr temp(new call_card());
         copy(user_ptr, temp);
         temp->cardid = CCT_CALL_ALL; //全员卡
+        temp->call_state = CALL_ING;
 
-        arr.push_back(temp);//增加到结果集中
+        result_arr.push_back(temp);//增加到结果集中
 
         //添加全员卡
-        user_ptr->cards.insert(std::make_pair(CCT_CALL_ALL, temp));
+        user_ptr->cards.insert(std::make_pair(temp->cardid, temp));
 
         //更新用户信息
         std::lock_guard<std::mutex> lock(_mutex);
@@ -129,7 +108,7 @@ void module_call::accept_call(const rapidjson::Document& node_data)
         std::lock_guard<std::mutex> lock(_mutex);
 
         auto user_map_ptr = _map.find(user_name);
-        if(user_map_ptr==_map.end())//没有这个用户就新建并加入
+        if(_map.end() == user_map_ptr)//没有这个用户就新建并加入
         {
             user_ptr=call_user_ptr(new call_user());
             _map[user_name]=user_ptr;
@@ -138,7 +117,8 @@ void module_call::accept_call(const rapidjson::Document& node_data)
         {
             user_ptr=user_map_ptr->second;
             // 如果有全员,定员不生效
-            if(user_ptr->cards.size()==1 && CCT_CALL_ALL == user_ptr->cards[CCT_CALL_ALL]->cardid)
+            auto card_temp = user_ptr->cards.find(CCT_CALL_ALL);
+            if(user_ptr->cards.end() != card_temp)
             {
                 return;
             }
@@ -147,33 +127,30 @@ void module_call::accept_call(const rapidjson::Document& node_data)
         //更新用户信息
         user_ptr->call_time=std::chrono::system_clock::now();
         user_ptr->call_time_out=call_time_out;
+        user_ptr->call_time_interval = call_time_interval;
         user_ptr->call_type_id=call_type;
         user_ptr->call_level_id=call_level;
         user_ptr->user_name=user_name;
 
-        auto node_cards_ptr = node_data.FindMember(JSON_KEY_CALL_CARD_CARDS);
-        if(node_data.MemberEnd()==node_cards_ptr)
-        {
-            return;
-        }
-        const rapidjson::Value& node_cards = node_cards_ptr->value;
-        if(!node_cards.IsArray())
+        std::vector<sio::message::ptr> card_vec;
+        if(!tool_map::try_get_value(card_vec, JSON_KEY_CALL_CARD_CARDS, data) || card_vec.size() == 0)
         {
+            log_error("发起呼叫,web发来的数据JSON_KEY_CALL_CARD_CARDS字段为空 或者不是数组");
             return;
         }
 
-        add_cards_to_user(call_level, node_cards, user_ptr);
+        add_cards_to_user(card_vec, user_ptr);
 
         for(auto& it:user_ptr->cards)//添加到结果集中
         {
-            arr.push_back(it.second);
+            result_arr.push_back(it.second);
         }
     }
 
     //组装json发送给web
-    if(!arr.empty())
+    if(!result_arr.empty())
     {
-        response_accept_call(arr);
+        response_accept_call(result_arr);
     }
 }
 
@@ -203,7 +180,7 @@ void module_call::response_accept_call(std::vector<call_card_ptr> cards)
     doc.AddMember(JSON_ROOT_KEY_VERSION, INTERFACE_VERSION, allocator);
     doc.AddMember(JSON_ROOT_KEY_DATA, node_cards, allocator);
 
-    swsClientMgr.send(JSON_CMD_VALUE_PUSH, tool_json::doc_to_json(doc));
+    tool_other::send_json(JSON_CMD_VALUE_PUSH, tool_json::doc_to_json(doc));
 }
 
 
@@ -218,29 +195,31 @@ void module_call::response_accept_call(std::vector<call_card_ptr> cards)
 //	  cards: this.cards // 取消呼叫卡  //旧代码为map格式 [{ stationid: 0 }]
 //	}
 //}
-void module_call::accept_cancel(const rapidjson::Document& node_data)
+void module_call::accept_cancel(sio::message::ptr const& node_data)
 {
-    int call_type = -1, call_level = -1;
+    int call_type = -1;//, call_level = -1;
     std::string user_name;
+    int64_t call_time;
 
-    if(!tool_json::try_get_value(call_type, JSON_KEY_CALL_CARD_CALL_TYPE, node_data)
-            || !tool_json::try_get_value(call_level, JSON_KEY_CALL_CARD_CALL_LEVEL, node_data)
-            || !tool_json::try_get_value(user_name, JSON_KEY_CALL_CARD_USER_NAME, node_data)
+    if(!tool_map::try_get_value(call_type, JSON_KEY_CALL_CARD_CALL_TYPE, node_data)
+            || !tool_map::try_get_value(call_time, JSON_KEY_CALL_CARD_CALL_TIME, node_data)
+            || !tool_map::try_get_value(user_name, JSON_KEY_CALL_CARD_USER_NAME, node_data)
             )
     {
-        log_error("收到的json不对,解析不出int call_type = -1, call_level = -1,user_name");
+        log_error("取消呼叫: 收到的json不对,解析不出int call_type = -1, call_level = -1,user_name");
         return;
     }
 
     if(user_name.empty())
     {
-        log_error("user_name用户名为空");
+        log_error("取消呼叫: user_name用户名为空");
         return;
     }
 
     call_user_ptr result_user_ptr(new call_user());
     result_user_ptr->call_type_id=call_type;
-    result_user_ptr->call_level_id=call_level;
+    //    result_user_ptr->call_level_id=call_level;
+    result_user_ptr->call_time = std::chrono::system_clock::time_point(std::chrono::milliseconds(call_time));
     result_user_ptr->user_name=user_name;
 
     //取消呼叫有两种:
@@ -254,14 +233,10 @@ void module_call::accept_cancel(const rapidjson::Document& node_data)
     }
     else// 取消定员呼叫
     {
-        auto node_cards_ptr = node_data.FindMember(JSON_KEY_CALL_CARD_CARDS);
-        if(node_data.MemberEnd()==node_cards_ptr)
-        {
-            return;
-        }
-        const rapidjson::Value& node_cards = node_cards_ptr->value;
-        if(!node_cards.IsArray())
+        std::vector<sio::message::ptr> card_vec;
+        if(!tool_map::try_get_value(card_vec, JSON_KEY_CALL_CARD_CARDS, node_data) || card_vec.size() == 0)
         {
+            log_error("取消呼叫: web发来的数据cards字段为空 或者不是数组");
             return;
         }
 
@@ -274,22 +249,28 @@ void module_call::accept_cancel(const rapidjson::Document& node_data)
             user_ptr=it_map->second;
         }
 
-        uint64_t id_card;
-        for(rapidjson::SizeType i = 0; i < node_cards.Size(); ++i)
+        std::vector<sio::message::ptr>::const_iterator it_card = card_vec.begin();
+        std::string s_card_id;
+        for(; it_card != card_vec.end(); ++it_card)
         {
-            if(!tool_json::try_get_value( id_card, JSON_KEY_CALL_CARD_CARD_ID, node_cards[i])
-                    || 0==id_card
-                    )
+            if(!tool_map::try_get_value(s_card_id, JSON_KEY_CALL_CARD_CARD_ID, (*it_card)))
             {
+                log_error("取消呼叫: web发来的数据 card_id 格式不对");
                 continue;
             }
 
+            uint32_t id = tool_other::id64_to_id(s_card_id);
+            int type= tool_other::id64_to_type(s_card_id);
+
+            log_info("取消呼叫: cardid=%d, cardtype=%d", id, type);
+
             call_card_ptr card_ptr(new call_card());
-            card_ptr->cardid = id_card;
+            card_ptr->cardid = id;
+            card_ptr->cardtype = type;
 
-            result_user_ptr->cards[id_card]=card_ptr;//增加到结果集中
+            result_user_ptr->cards[card_ptr->cardid]=card_ptr;//增加到结果集中
 
-            user_ptr->cards.erase(id_card);//删除这个卡
+            user_ptr->cards.erase(card_ptr->cardid);//删除这个卡
         }
 
         // 没有呼叫信息,删除该用户记录
@@ -302,8 +283,8 @@ void module_call::accept_cancel(const rapidjson::Document& node_data)
     //如果要取消呼叫的用户下没有卡,建一张CCT_CALL_ALL卡返回
     if(result_user_ptr->cards.empty())
     {
-        result_user_ptr->call_level_id=call_level;
-        result_user_ptr->call_time=std::chrono::system_clock::now();
+        //        result_user_ptr->call_level_id=call_level;
+        //result_user_ptr->call_time=std::chrono::system_clock::now();
         result_user_ptr->call_time_out=0;
         result_user_ptr->call_type_id=call_type;
         result_user_ptr->user_name=user_name;
@@ -333,8 +314,10 @@ void module_call::response_accept_cancel(const call_user_ptr user_ptr)
     auto& allocator = doc.GetAllocator();
     rapidjson::Value node_data(rapidjson::kObjectType);
 
-    node_data.AddMember(JSON_KEY_CALL_CARD_USER_NAME, rapidjson::StringRef(user_ptr->user_name.c_str()), allocator);
+    tool_json::add_member(node_data, JSON_KEY_CALL_CARD_USER_NAME, user_ptr->user_name, allocator);
+
     node_data.AddMember(JSON_KEY_CALL_CARD_CALL_TIME, tool_time::to_ms(user_ptr->call_time), allocator);
+    node_data.AddMember(JSON_KEY_CALL_CARD_CALL_TYPE, user_ptr->call_type_id, allocator);
 
     rapidjson::Value node_cards(rapidjson::kArrayType);
 
@@ -343,7 +326,9 @@ void module_call::response_accept_cancel(const call_user_ptr user_ptr)
     for(;iter != user_ptr->cards.end();++iter)
     {
         rapidjson::Value node_card(rapidjson::kObjectType);
-        node_card.AddMember(JSON_KEY_CALL_CARD_CARD_ID,iter->second->cardid, allocator);
+
+        tool_json::add_member(node_card, JSON_KEY_CALL_CARD_CARD_ID, iter->second->to_id64_str(), allocator);
+        node_card.AddMember(JSON_KEY_CALL_CARD_CARD_TYPE_ID,iter->second->cardtype, allocator);
 
         node_cards.PushBack(node_card,allocator);
     }
@@ -355,30 +340,9 @@ void module_call::response_accept_cancel(const call_user_ptr user_ptr)
     doc.AddMember(JSON_ROOT_KEY_DATA, node_data, allocator);
 
     //转发给web
-    swsClientMgr.send(JSON_CMD_VALUE_PUSH, tool_json::doc_to_json(doc));
+    tool_other::send_json(JSON_CMD_VALUE_PUSH, tool_json::doc_to_json(doc));
 }
 
-//void module_call::get_cancel_user_info(const call_user_ptr user_ptr,
-//                                       const rapidjson::Value& node_cards, call_user_ptr& result_user_ptr)
-//{
-//    copy(user_ptr, result_user_ptr);
-
-//    uint16_t cardid;
-//    for(rapidjson::SizeType i = 0; i < node_cards.Size(); ++i)
-//    {
-//        call_card_ptr card_ptr;
-//        const rapidjson::Value& node = node_cards[i];
-//        if(!node.IsUint64() || !find_card(user_ptr, cardid=node.GetUint64(), card_ptr))
-//        {
-//            continue;
-//        }
-
-//        user_ptr->cards.erase(cardid);//从呼叫用户卡中删除
-
-//        result_user_ptr->cards[cardid]=card_ptr;
-//    }
-//}
-
 /*
 登陆时,采集发送web:井下所有呼叫
 {"cmd":"callcardlist","data":[
@@ -420,20 +384,27 @@ std::string module_call::to_call_card_list_json(std::vector<call_card_ptr> arr)
     return tool_json::doc_to_json(doc);
 }
 
-void module_call::add_cards_to_user(int call_level, const rapidjson::Value& node_cards, call_user_ptr user_ptr)
+void module_call::add_cards_to_user(const std::vector<sio::message::ptr>& card_vec, call_user_ptr user_ptr)
 {
-    uint64_t id_card;
-    for(rapidjson::SizeType i = 0; i < node_cards.Size(); ++i)
+    std::vector<sio::message::ptr>::const_iterator it_card = card_vec.begin();
+    for(; it_card != card_vec.end(); ++it_card)
     {
-        if(!tool_json::try_get_value( id_card, JSON_KEY_CALL_CARD_CARD_ID, node_cards[i])
-                || 0==id_card
-                )
+        std::string s_card_id;
+        if(!tool_map::try_get_value(s_card_id, JSON_KEY_CALL_CARD_CARD_ID, (*it_card))
+                ||s_card_id.empty())
         {
+            log_error("发起呼叫,web发来的数据 card_id 格式不对 或为空");
             continue;
         }
 
+        uint32_t id = tool_other::id64_to_id(s_card_id);
+        int type= tool_other::id64_to_type(s_card_id);
+
+        log_info("发起呼叫 cardid=%d, cardtype=%d", id, type);
+
         call_card_ptr card_ptr(new call_card());
-        card_ptr->cardid = id_card;
+        card_ptr->cardid = id;
+        card_ptr->cardtype = type;
         copy(user_ptr, card_ptr);
 
         card_ptr->call_state = CALL_ING;
@@ -443,17 +414,20 @@ void module_call::add_cards_to_user(int call_level, const rapidjson::Value& node
 }
 
 void module_call::get_user_all_call_cards(call_user_ptr& user_ptr,
-                    const std::unordered_map<uint64_t,std::shared_ptr<card_location_base>>& cardlist,
-                    std::vector<call_card_ptr>& out_data)
+                                          const std::unordered_map<uint64_t,std::shared_ptr<card_location_base>>& cardlist,
+                                          std::vector<call_card_ptr>& out_data)
 {
     auto& cards=user_ptr->cards;
     int status = CALL_ING;
+
     //如果是全员呼叫,增加所有卡
-    if(cards.size()==1 && CCT_CALL_ALL == cards[0]->cardid)
+    auto card_it = cards.find(CCT_CALL_ALL);
+    if(cards.end()!=card_it)
     {
-        uint32_t seconds = tool_time::elapse_seconds(user_ptr->call_time);
-        if(seconds > user_ptr->call_time_out*60)//呼叫超时, 清空全员卡, 并设置呼叫状态为结束
+        if(user_ptr->is_timeout())//呼叫超时, 清空全员卡, 并设置呼叫状态为结束
         {
+            log_info("全员呼叫发送线程:呼叫用户超时,用户名=%s", user_ptr->user_name.c_str());
+
             cards.clear();
             status=CALL_END;
         }
@@ -461,12 +435,34 @@ void module_call::get_user_all_call_cards(call_user_ptr& user_ptr,
         auto g_it=cardlist.begin();
         for(;g_it!=cardlist.end();++g_it)//如果是全员呼叫,增加所有卡
         {
+            auto site_ptr = g_it->second->get_site_area();
+            if(!site_ptr || site_ptr->is_invalid())
+            {
+                continue;
+            }
+
             call_card_ptr card_ptr(new call_card());
             copy(user_ptr, card_ptr);
             card_ptr->cardid = g_it->second->m_id;
-            //card_ptr->stationid=g_it->second->m_site_id;
+            card_ptr->cardtype = g_it->second->m_type;
+
+            card_ptr->stationid=site_ptr->site_id();
 
             card_ptr->call_state=status;
+            if(CALL_SUCCESSED == g_it->second->get_mine_tool()->m_status_call)
+            {
+                card_ptr->call_state = CALL_SUCCESSED;
+            }
+            else
+            {
+                g_it->second->get_mine_tool()->m_status_call = CALL_ING;
+            }
+
+            if(card_ptr->is_timeout())
+            {
+                g_it->second->get_mine_tool()->m_status_call = 0;
+            }
+            card_ptr->is_display = g_it->second->m_display;
 
             out_data.push_back(card_ptr);
         }
@@ -474,29 +470,61 @@ void module_call::get_user_all_call_cards(call_user_ptr& user_ptr,
         return;
     }
 
+    //定员呼叫
     auto iter_card = cards.begin();
     for(;iter_card!=cards.end();++iter_card)
     {
         //增加到结果集中
         out_data.push_back(iter_card->second);
 
-        auto g_card = cardlist.find(iter_card->second->cardid);
+        auto g_card = cardlist.find(iter_card->second->to_id64());
         if(cardlist.end()==g_card)//在全局卡列表中没有这张卡,
         {
+            log_error("定员呼叫发送线程:全局卡列表中没有这张卡,卡id=%d,卡类型=%d",
+                      iter_card->second->cardid, iter_card->second->cardtype);
+
             iter_card->second->call_state = CALL_FAILED;
+            cards.erase(iter_card--); //在用户下删除这张卡
+
+            continue;
+        }
+
+        auto site_ptr = g_card->second->get_site_area();
+        if(!site_ptr || site_ptr->is_invalid())
+        {
+            log_error("定员呼叫发送线程:全局卡列表中这张卡已经上井或无效,卡id=%d,卡类型=%d",
+                      iter_card->second->cardid, iter_card->second->cardtype);
 
+            iter_card->second->call_state = CALL_FAILED;
             cards.erase(iter_card--); //在用户下删除这张卡
+
             continue;
         }
 
         //更新卡的分站id
-        //iter_card->second->stationid = g_card->second->m_site_id;
+        iter_card->second->stationid = site_ptr->site_id();
 
-        uint32_t seconds = tool_time::elapse_seconds(iter_card->second->call_time);
-        if(seconds > iter_card->second->call_time_out*60)//呼叫超时
+        if(CALL_SUCCESSED == g_card->second->get_mine_tool()->m_status_call)
         {
-            iter_card->second->call_state = CALL_END;
+            iter_card->second->call_state = CALL_SUCCESSED;
+        }
+        else
+        {
+            g_card->second->get_mine_tool()->m_status_call = CALL_ING;
+        }
+
+        if(iter_card->second->is_timeout())//呼叫超时
+        {
+            log_info("定员呼叫发送线程:呼叫卡超时,用户名=%s,卡id=%d,卡类型=%d",
+                     iter_card->second->user_name.c_str(),
+                     iter_card->second->cardid, iter_card->second->cardtype);
 
+            iter_card->second->call_state = CALL_END;
+            if(CALL_SUCCESSED == g_card->second->get_mine_tool()->m_status_call)
+            {
+                iter_card->second->call_state = CALL_SUCCESSED;
+                g_card->second->get_mine_tool()->m_status_call = 0;
+            }
             cards.erase(iter_card--);//在用户下删除这张卡
         }
     }

+ 284 - 49
module_service/module_call.h

@@ -19,6 +19,45 @@
 #include"module_const.h"
 #include"module_web.h"
 
+/**
+ * @brief 呼叫类型 全员 定员
+ */
+enum CALL_CARD_TYPE
+{
+    /// 全员呼叫
+    CCT_CALL_ALL = 0,
+    /// 定员
+    CCT_CALL_APOINT=1,
+};
+
+/**
+ * @brief 呼叫等级 一般呼叫  紧急呼叫
+ */
+enum CALL_CARD_LEVEL
+{
+    /// 呼叫等级: 1  一般呼叫
+    CALL_LEVEL_NORMAL=1,
+    /// 呼叫等级: 2  紧急呼叫
+    CALL_LEVEL_CRITICAL=2
+};
+
+/**
+ * @brief 呼叫状态
+ */
+enum CALL_STATE{
+    ///无呼叫信息
+    CALL_NONE = 0,
+    ///呼叫成功
+    CALL_SUCCESSED = 1,
+    ///呼叫中
+    CALL_ING = 2,
+    ///呼叫失败
+    CALL_FAILED = 3,
+
+    ///呼叫结束
+    CALL_END=100
+};
+
 /**
  * @brief 呼叫模块
  */
@@ -38,21 +77,49 @@ private:
     {
         /// 呼叫卡号 0为全员
         uint32_t cardid;
+        int32_t cardtype;
         /// 分站号  0为全员
         int stationid;
+        ///呼叫类型 全员0, 定员1   CALL_CARD_TYPE
+        int call_type_id;
         /// 呼叫类型:一般1,紧急2  CALL_CARD_LEVEL
         int call_level_id;
         /// 呼叫时长,单位分钟
-        int call_time_out;
+        uint32_t call_time_out;
+
+        int call_time_interval;
         /// 呼叫开始时间
         std::chrono::system_clock::time_point call_time;
         /// 呼叫状态,正在呼叫、呼叫成功
         int call_state;
         ///呼叫人
         std::string user_name;
+
+        bool is_display = true;
+
+        bool is_call_all()
+        {
+            return CCT_CALL_ALL == call_type_id;
+        }
+
+        uint64_t to_id64()
+        {
+            return card_list::to_id64(cardtype, cardid);
+        }
+
+        std::string to_id64_str()
+        {
+            return card_list::to_id64_str(cardtype, cardid);
+        }
+
+        bool is_timeout()
+        {
+            uint32_t seconds = tool_time::elapse_seconds(call_time);
+            return (seconds >= call_time_out*60);
+        }
     };
     typedef std::shared_ptr<call_card>  call_card_ptr;
-    typedef std::map<uint64_t,call_card_ptr>  call_card_map;
+    typedef std::map<int64_t,call_card_ptr>  call_card_map;
 
     /**
      * @brief 呼叫用户信息
@@ -66,34 +133,73 @@ private:
         /// 呼叫等级:一般1,紧急2  CALL_CARD_LEVEL
         int call_level_id;
         /// 呼叫时长,单位分钟
-        int call_time_out;
+        uint32_t call_time_out;
+
+        int call_time_interval;
         /// 呼叫开始时间
         std::chrono::system_clock::time_point call_time;
         ///呼叫卡列表
         call_card_map cards;
+
+        bool is_timeout()
+        {
+            uint32_t seconds = tool_time::elapse_seconds(call_time);
+            return (seconds >= call_time_out*60);
+        }
+
+        bool is_call_all()
+        {
+            return CCT_CALL_ALL == call_type_id;
+        }
     };
     typedef std::shared_ptr<call_user>  call_user_ptr;
     typedef std::map<std::string, call_user_ptr> call_user_map;
 
-public:
+    struct call_site
+    {
+        int32_t site_id;
+        ///呼叫类型 全员0, 定员1   CALL_CARD_TYPE
+        int call_type_id;
+        /// 呼叫等级:一般1,紧急2  CALL_CARD_LEVEL
+        int call_level_id;
+
+        call_card_map cards;
+
+        bool is_call_all()
+        {
+            return CCT_CALL_ALL == call_type_id;
+        }
+    };
+    typedef std::shared_ptr<call_site>  call_site_ptr;
+    typedef std::map<int32_t, call_site_ptr> call_site_map;
 
+public:
     /**
      * @brief web发给采集:发起呼叫
      * @param node_data
      */
-    void accept_call(const rapidjson::Document& node_data);
+    void accept_call(sio::message::ptr const& data);
 
     /**
      * @brief web发给采集:取消呼叫
      * @param node_data
      */
-    void accept_cancel(const rapidjson::Document& node_data);
+    void accept_cancel(sio::message::ptr const& data);
 
     /**
      * @brief 登陆时,采集发送web:请求井下所有呼叫
      */
     std::string accept_login();
 
+    void rev_from_card_resp(std::shared_ptr<card_location_base> card_ptr);
+    /**
+     * @brief
+     */
+    void init(config_file& config)
+    {
+        sleep_ms = std::stoi(config.get("service.send_call_interval","5000"));
+    }
+
 private:
     /**
      * @brief 采集回复web发起呼叫
@@ -107,9 +213,8 @@ private:
      */
     void response_accept_cancel(const call_user_ptr user_ptr);
 
-
-
-    void add_cards_to_user(int call_level, const rapidjson::Value& node_cards, call_user_ptr user_ptr);
+    void add_cards_to_user(const std::vector<sio::message::ptr>& card_vec,
+                           call_user_ptr user_ptr);
 
     /**
      * @brief 线程函数
@@ -132,8 +237,10 @@ private:
         des->call_time = src->call_time;
         des->call_time_out = src->call_time_out;
         des->cardid = src->cardid;
+        des->cardtype = src->cardtype;
         des->user_name = src->user_name;
         des->stationid = src->stationid;
+        des->call_type_id = src->call_type_id;
     }
 
     void copy(const call_user_ptr src, call_card_ptr des)
@@ -142,8 +249,10 @@ private:
         //des->call_state = src->call_state;
         des->call_time = src->call_time;
         des->call_time_out = src->call_time_out;
+        des->call_time_interval = src->call_time_interval;
         //des->cardid = src->cardid;
         des->user_name = src->user_name;
+        des->call_type_id = src->call_type_id;
     }
 
     /**
@@ -153,8 +262,8 @@ private:
      * @param out_data
      */
     void get_user_all_call_cards(call_user_ptr& user_ptr,
-                        const std::unordered_map<uint64_t,std::shared_ptr<card_location_base>>& cardlist,
-                        std::vector<call_card_ptr>& out_data);
+                                 const std::unordered_map<uint64_t,std::shared_ptr<card_location_base>>& cardlist,
+                                 std::vector<call_card_ptr>& out_data);
 
     /**
      * @brief 获取所有的呼叫卡
@@ -163,8 +272,8 @@ private:
      * @param out_data
      */
     void get_all_call_cards(call_user_map& user_map,
-                        const std::unordered_map<uint64_t,std::shared_ptr<card_location_base>>& cardlist,
-                        std::vector<call_card_ptr>& out_data)
+                            const std::unordered_map<uint64_t,std::shared_ptr<card_location_base>>& cardlist,
+                            std::vector<call_card_ptr>& out_data)
     {
         auto iter_m_map=user_map.begin();
         for(;iter_m_map!=user_map.end();++iter_m_map)
@@ -204,28 +313,32 @@ private:
      * ]
     */
     static void to_node_element(rapidjson::Value& out_elemet,
-                                           const std::shared_ptr<call_card> card_ptr,
-                                           rapidjson::Document::AllocatorType& allocator)
+                                const std::shared_ptr<call_card> card_ptr,
+                                rapidjson::Document::AllocatorType& allocator)
     {
-
-        out_elemet.PushBack(rapidjson::StringRef(card_ptr->user_name.c_str()), allocator);
-        out_elemet.PushBack(card_ptr->cardid, allocator);
+        tool_json::push_back(out_elemet, card_ptr->user_name, allocator);
+        tool_json::push_back(out_elemet, card_ptr->to_id64_str(), allocator);
 
         out_elemet.PushBack(card_ptr->stationid, allocator);
-        out_elemet.PushBack(tool_time::to_ms(card_ptr->call_time), allocator);
+        out_elemet.PushBack(card_ptr->call_time_interval, allocator);
 
-        out_elemet.PushBack(0, allocator);
+        out_elemet.PushBack(card_ptr->call_type_id, allocator);
         out_elemet.PushBack(card_ptr->call_state, allocator);
     }
 
     static void to_node_array(rapidjson::Value& out_array,
-                                                    const std::vector<std::shared_ptr<call_card>> cards,
-                                                    rapidjson::Document::AllocatorType& allocator)
+                              const std::vector<std::shared_ptr<call_card>> cards,
+                              rapidjson::Document::AllocatorType& allocator)
     {
         std::vector<std::shared_ptr<call_card>>::size_type i;
 
         for(i=0; i<cards.size(); i++)
         {
+            if(!cards[i]->is_display)
+            {
+                continue;
+            }
+
             rapidjson::Value node_card(rapidjson::kArrayType);
 
             to_node_element(node_card, cards[i], allocator);
@@ -241,33 +354,155 @@ private:
      */
     std::string to_call_card_list_json(std::vector<call_card_ptr> cards);
 
-//    /**
-//     * @brief 获取取消用户的信息,主要包括用户下要取消呼叫的卡信息
-//     * @param user_ptr
-//     * @param node_cards
-//     * @param result_user_ptr
-//     */
-//    void get_cancel_user_info(const call_user_ptr user_ptr,
-//                              const rapidjson::Value& node_cards, call_user_ptr& result_user_ptr);
-
-//    /**
-//     * @brief 根据卡id在用户下查找是否有此卡
-//     * @param user_ptr
-//     * @param cardid
-//     * @param card_ptr
-//     * @return
-//     */
-//    bool find_card(const call_user_ptr user_ptr, const uint64_t cardid, call_card_ptr& card_ptr)
-//    {
-//        auto it = user_ptr->cards.find(cardid);
-//        if(it!=user_ptr->cards.end())
-//        {
-//            card_ptr = it->second;
-//            return true;
-//        }
-
-//        return false;
-//    }
+    void get_site_map(const std::vector<call_card_ptr>& arr, call_site_map& out_site_map)
+    {
+        auto card_ptr = arr.begin();
+        for(;card_ptr!=arr.end();++card_ptr)
+        {
+            if((*card_ptr)->stationid<1)
+            {
+                continue;
+            }
+
+            auto iter = out_site_map.find((*card_ptr)->stationid);
+            if(out_site_map.end()==iter)
+            {
+                call_site_ptr site_ptr(new call_site());
+                site_ptr->site_id = (*card_ptr)->stationid;
+                site_ptr->call_type_id = (*card_ptr)->call_type_id;
+                site_ptr->call_level_id = (*card_ptr)->call_level_id;
+
+                out_site_map.insert(std::make_pair(site_ptr->site_id, site_ptr));
+
+                iter = out_site_map.find((*card_ptr)->stationid);
+            }
+
+            if(iter->second->is_call_all())
+            {
+                continue;
+            }
+
+            if((*card_ptr)->is_call_all())
+            {
+
+                iter->second->call_type_id = (*card_ptr)->call_type_id;
+                iter->second->cards.clear();
+                continue;
+            }
+
+            iter->second->cards[(*card_ptr)->cardid]=(*card_ptr);
+        }
+    }
+
+    ///发呼叫的报文数据给分站
+    void send_to_sites(call_site_map& site_map)
+    {
+        auto iter_site = site_map.begin();
+
+        for(; iter_site != site_map.end(); ++iter_site)
+        {
+            if(iter_site->second->cards.size() > 254)
+            {
+                log_error("呼叫:分站下卡数量过多:分站id=%d, 卡数=%d",
+                          iter_site->first, iter_site->second->cards.size());
+                continue;
+            }
+
+            std::vector<char> arr;
+
+            //分站地址 4字节,支持大小分站呼叫协议;added by zhuyf 2018/06/04
+            //大小分站的全员呼叫,分站id要求4字节全为FF
+            uint32_t anchor_id = (iter_site->second->is_call_all()? 0xffffffff : static_cast<uint32_t>(iter_site->first));
+            memcpy_uint32(arr,anchor_id);
+
+            //卡数
+            arr.push_back(static_cast<char>(iter_site->second->cards.size()));
+            //呼叫类型
+            arr.push_back(static_cast<char>(iter_site->second->call_type_id));
+
+            if(!iter_site->second->is_call_all())
+            {
+                //循环添加卡信息
+                auto it_card = iter_site->second->cards.begin();
+                for(; it_card != iter_site->second->cards.end(); ++it_card)
+                {
+                    //呼叫类型
+                    arr.push_back(static_cast<char>(it_card->second->call_level_id));
+                    //卡类型
+                    arr.push_back(static_cast<char>(it_card->second->cardtype));
+                    //卡ID长度
+                    int id_len = 4;
+                    arr.push_back(static_cast<char>(id_len));
+                    //卡ID
+                    memcpy_uint32(arr, it_card->second->cardid);
+                }
+            }
+
+            auto sit_ptr = sit_list::instance()->get(iter_site->first);
+            if(!sit_ptr || !sit_ptr->m_clt)
+            {
+                log_error("在全局分站列表中找不到分站 或者sit_ptr->m_clt==null:分站id=%d", iter_site->first);
+                continue;
+            }
+
+            //std::vector<char> arr2 = arr;
+            sit_ptr->m_clt->send(std::move(arr));
+
+            //print_test(std::move(arr2), iter_site->first);
+        }
+    }
+
+    static void print_test(std::vector<char>&& arr, int siteid)
+    {
+        std::string str("呼叫发送的数据帧,分站号=");
+        str.append(std::to_string(siteid));
+        str.append(":");
+
+        char a[4]={0};
+        for(std::vector<char>::size_type i=0; i<arr.size(); i++)
+        {
+            sprintf(a, "%02X ", static_cast<unsigned char>(arr[i]));
+
+            str.append(std::string(a));
+        }
+
+        log_info("%s", str.c_str());
+    }
+
+    void static memcpy_uint32(std::vector<char>& arr, uint32_t dwSrc)
+    {
+        char bt = HIBYTE(HIWORD(dwSrc));
+        arr.push_back(bt);
+
+        bt = LOBYTE(HIWORD(dwSrc));
+        arr.push_back(bt);
+
+        bt = HIBYTE(LOWORD(dwSrc));
+        arr.push_back(bt);
+
+        bt = LOBYTE(LOWORD(dwSrc));
+        arr.push_back(bt);
+    }
+
+    static char HIBYTE(uint16_t dwSrc)
+    {
+        return static_cast<char>(dwSrc>>8);
+    }
+
+    static char LOBYTE(uint16_t dwSrc)
+    {
+        return static_cast<char>(dwSrc);
+    }
+
+    static uint16_t HIWORD(uint32_t dwSrc)
+    {
+        return static_cast<uint16_t>(dwSrc>>16);
+    }
+
+    static uint16_t LOWORD(uint32_t dwSrc)
+    {
+        return static_cast<uint16_t>(dwSrc);
+    }
 
 private:
     /// 呼叫用户列表

+ 0 - 8
module_service/module_call_help.cpp

@@ -1,8 +0,0 @@
-#include "module_call_help.h"
-#include "log.h"
-#include <boost/bind.hpp>
-
-
-
-
-

+ 80 - 85
module_service/module_call_help.h

@@ -20,7 +20,7 @@
  * @brief 呼救类
  * 把呼救消息保存到数据库,同时推送给web, 单例
  */
-class module_call_help : public i_thread, public singleton_base<module_call_help>
+class module_call_help : public singleton_base<module_call_help>
 {
 private:
     friend class singleton_base<module_call_help>;
@@ -30,119 +30,114 @@ private:
 
 public:
     /**
-     * @brief 接收到呼救请求
+     * @brief //1.如果已经有呼救告警
+    //2.web取消告警。status_help && status_help_cancel 置为status_help_dealed
+    //3.如果底层已经没有呼救则,取消后,不会再次进行呼救。因为status_help已经不会置为status_error。
+    //4.如果底层还在呼救。这时候不管status_help是何种状态,极大的可能是error.status_help_cancel的存在都会取消。
+    //并且还要保证等待线程把json传送到前端
      */
-    void rev_help(std::shared_ptr<card> card_ptr)
+    void rev_from_card_help(std::shared_ptr<card_location_base> card_ptr)
     {
-//        if(ES_START != card_ptr->m_stat_call_help)
-//        {
-//            card_ptr->m_stat_call_help = ES_START;
-//            //保存到数据库
-//            auto ev_ptr = tool_other::create_event(OT_CARD, card_ptr->m_id, ET_CARD_HELP);
-
-//            tool_other::copy_event(card_ptr, ev_ptr);
+        auto ev_ptr = event_list::instance()->get_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_HELP);
+        if(!ev_ptr)
+        {
+            auto ev_ptr = event_list::create_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_HELP);
 
-////            ev_ptr->status = ES_START;
-////            ev_ptr->cur_time = std::chrono::system_clock::now();
+            event_list::copy_event(card_ptr, ev_ptr);
 
-//            //保存到数据库
-//            tool_db::save_event(ev_ptr);
-//            //转发给web
-//            swsClientMgr.send(JSON_CMD_VALUE_PUSH, tool_json::ev_to_json(ev_ptr));
+            //保存到数据库
+            event_list::save_event(ev_ptr);
 
-//            std::lock_guard<std::mutex> lock(_mutex);
-//            tool_other::insert_event(ev_ptr, _map);
-//        }
+            event_list::instance()->add(ev_ptr->get_list_id(), ev_ptr);
+        }
     }
 
     /**
      * @brief 接收到web端发来的处理呼救请求
      * @param data_map
      */
-    void accept_deal_help(std::map<std::string, sio::message::ptr> data_map)
+    void accept_web_deal_help(sio::message::ptr const& data)
     {
-//        uint32_t cardid = data_map[JSON_KEY_ID]->get_int();
-//        //uint64_t ev_id = data_map[JSON_KEY_EVENT_EVENT_ID]->get_int();
-
-//        auto card_ptr = card_list::instance()->get(tool_other::to_uint64_cardid(CT_PERSON, cardid));
-//        if(card_ptr)
-//        {
-//            card_ptr->m_stat_call_help = ES_DEAL_HELP;
-
-//            std::lock_guard<std::mutex> lock(_mutex);
-//            auto ev_ptr = tool_other::find_event(cardid, ET_CARD_HELP, _map);
-//            if(ev_ptr)
-//            {
-//                ev_ptr->m_status = ES_DEAL_HELP;
-//                tool_db::save_event(ev_ptr);
-//            }
-//        }
-////        else
-////        {
-////            std::lock_guard<std::mutex> lock(_mutex);
-////            _map.erase(ev_id);
-////        }
-    }
+        int64_t ev_id = 0;
+        std::string s_card_id;
+        if(!tool_map::try_get_value(s_card_id, JSON_KEY_ID, data)
+                ||!tool_map::try_get_value(ev_id, JSON_KEY_EVENT_EVENT_ID, data))
+        {
+            log_error("处理呼救,web发来的数据 card_id 或 ev_id格式不对");
+            return;
+        }
 
-    /**
-     * @brief web前端有用户登录时,反馈给web所有信息
-     */
-    std::string response_login()
-    {
-        std::vector<std::shared_ptr<ya_event>> arr;
-        get_all_events(arr);
+        uint32_t id = tool_other::id64_to_id(s_card_id);
+        int type = tool_other::id64_to_type(s_card_id);
 
-        if(!arr.empty())//发送给web端
+        auto card_ptr = card_list::instance()->get(card_list::to_id64(type, id));
+        if(card_ptr)
         {
-            return tool_json::evs_to_json(arr);
-        }
+            log_info("处理呼救,card_id=%d, type=%d,  ev_id=%d", id, type, ev_id);
 
-        return "";
-    }
+            auto ev_ptr = event_list::instance()->get_event_card(id, type, ET_CARD_HELP);
+            if(ev_ptr && ES_DEAL_HELP != ev_ptr->m_status)
+            {
+                event_list::copy_event(card_ptr, ev_ptr);
 
-    /**
-     * @brief 读取数据库中的告警,初始化告警列表
-     */
-    void init()
-    {}
+                ev_ptr->m_status = ES_DEAL_HELP;
 
-private:
-    /**
-     * @brief 线程函数
-     */
-    void run()
-    {
-        std::vector<std::shared_ptr<ya_event>> arr;
-        get_all_events(arr);
+                event_list::save_event(ev_ptr);
 
-        if(!arr.empty())//发送给web端
+                //删除
+                //event_list::instance()->remove(ev_ptr->get_list_id(), ev_ptr);
+            }
+        }
+        else
         {
-            swsClientMgr.send(JSON_CMD_VALUE_PUSH, tool_json::evs_to_json(arr));
+            log_error("处理呼救,在全局列表中找不到卡,卡id=%d,卡type=%d", id, type);
         }
     }
 
-    /**
-     * @brief 获取所有的告警事件
-     * @param out_data
-     */
-    void get_all_events(std::vector<std::shared_ptr<ya_event>>& arr)
+    static std::string get_json_help()
     {
-        {
-            std::lock_guard<std::mutex> lock(_mutex);
+        rapidjson::Document doc(rapidjson::kObjectType);
+        rapidjson::Value data(rapidjson::kArrayType);
+        rapidjson::Document::AllocatorType& allocator=doc.GetAllocator();
 
-            auto it_map = _map.begin();
-            for(;it_map!=_map.end();++it_map)
+        auto tmp = event_list::instance()->m_map;
+        auto it_ev=tmp.begin();
+        for(;it_ev!=tmp.end();++it_ev)
+        {
+            if(!it_ev->second->m_is_display || ET_CARD_HELP != it_ev->second->m_ev_type)
             {
-                arr.push_back(it_map->second);
-                if(ES_DEAL_HELP== it_map->second->m_status)//删除掉已经处理的
-                {
-                    _map.erase(it_map--);
-                }
+                continue;
             }
+
+            std::string obj_id = it_ev->second->m_obj_id;
+            int type= tool_other::id64_to_type(obj_id);
+
+            rapidjson::Value alarm(rapidjson::kObjectType);
+
+            tool_json::add_member(alarm, JSON_KEY_CARD_ID,it_ev->second->m_obj_id, allocator);
+            alarm.AddMember(JSON_KEY_CARD_TYPE_ID,type, allocator);
+
+            std::string time = tool_time::to_str(it_ev->second->m_cur_time);
+            tool_json::add_member(alarm, "start_time",time, allocator);
+
+            data.PushBack(alarm, allocator);
         }
-    }
 
-    std::map<uint64_t, std::shared_ptr<ya_event>> _map;
+        if(!data.Size())
+        {
+            return "";
+        }
+
+        doc.AddMember(JSON_ROOT_KEY_CMD,"helpme_req", allocator);
+        doc.AddMember(JSON_ROOT_KEY_VERSION,INTERFACE_VERSION, allocator);
+        doc.AddMember(JSON_ROOT_KEY_DATA,data, allocator);
+
+        rapidjson::StringBuffer sb;
+        rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
+        doc.Accept(writer);
+
+        return sb.GetString();
+    }
 };
 
 

+ 0 - 6
module_service/module_const.cpp

@@ -1,6 +0,0 @@
-#include "module_const.h"
-
-
-int global_constant::AREA_SPEED_COUNT_LIMIT=0;
-
-

+ 22 - 535
module_service/module_const.h

@@ -18,534 +18,11 @@
 #include<rapidjson/stringbuffer.h>
 #include<websocket/wsClientMgr.h>
 #include<thread>
-
+#include "websocket/constdef.h"
 #include"card.h"
 #include"area.h"
-#include"constdef.h"
-
-#define LENGTH_SQL 2000
-
-///全局常量
-class global_constant
-{
-public:
-//    ///区域超速最小次数门限
-//    static int AREA_SPEED_COUNT_MIN;
-    ///区域超速最大次数门限
-    static int AREA_SPEED_COUNT_LIMIT;
-//    ///区域超速最小时间门限
-//    static int AREA_SPEED_TIME_MIN;
-//    ///区域超速最大时间门限
-//    static int AREA_SPEED_TIME_MAX;
-
-//    ///车辆考勤最小次数门限
-//    static int ATTENDANCE_VEHICLE_COUNT_MIN;
-    ///车辆考勤最大次数门限
-    static int ATTENDANCE_VEHICLE_COUNT_LIMIT;
-//    ///车辆考勤最小时间门限
-//    static int ATTENDANCE_VEHICLE_TIME_MIN;
-//    ///车辆考勤最大时间门限
-//    static int ATTENDANCE_VEHICLE_TIME_MAX;
-};
-
-/**
- * @brief 事件状态
- */
-enum EVENT_STATUS
-{
-    ///事件开始
-    ES_START = 0,
-    ///呼救已处理状态
-    ES_DEAL_HELP = 1,
-    ///事件结束
-    ES_END = 100
-};
-
-//enum STATUS_CARD
-//{
-//    STATUS_NORMAL = 0,				//正常
-//    STATUS_ERROR = 1,
-//    STATUS_ERROR_SERIOUS = 2,
-
-//    STATUS_POWER_LOWER = 1,			//电量低
-//    STATUS_POWER_LOWER_SERIOUS = 2, //电量极低
-//    STATUS_OVER_TIME = 4,			//超时
-//    //STATUS_OVER_COUNT = 1,
-//    STATUS_OVER_SPEED = 8,			//超速
-//    STATUS_AREA_OVER_TIME = 16,		//区域超时
-//    //STATUS_AREA_OVER_COUNT = 1,
-//    STATUS_AREA_OVER_SPEED = 32,	//区域超速
-//    STATUS_AREA_FORBIDDEN = 64,		//进入限制区域
-//    ////STATUS_HELP = 128,				//呼救
-//    STATUS_HELP_DEALED = 256,		//呼救已处理
-//    STATUS_CALL = 512,				//呼叫
-//    STATUS_LOST = 1024				//进入盲区
-//    //STATUS_ERROR_DEALED,
-//};
-
-
-enum EVENT_TYPE{ // 事件类型
-    ET_UNKNOWN = 0,
-    ET_OVER_COUNT_PERSON = 1, // 井下人员超员mp_card_list_over_count_person
-    ET_OVER_COUNT_VEHICLE = 2,    // 井下车辆超员mp_card_list_over_count_person
-
-    ET_AREA_OVER_COUNT_PERSON = 3,	// 区域人员超员
-    ET_AREA_OVER_COUNT_VEHICLE = 4,	// 区域车辆超员
-
-    ET_SECTION_OVER_COUNT = 5, // 路段拥堵
-
-    ET_READER_ERROR = 6, // 分站通信异常
-    ET_ctrl_reader_ERROR = 7, // 控制分站异常
-    ET_LIGHT_ERROR = 8, // 交通灯异常
-    ET_READER_CALL = 9, // 分站呼叫标识卡
-    ET_READER_CALL_CANCEL = 10, // 取消呼叫分站
-
-    ET_CARD_LOW_POWER = 11, // 电量低
-    ET_CARD_LOW_POWER_SERIOUS = 12, // 电量极低
-
-    ET_CARD_OVER_TIME_PERSON = 13, // 人员井下超时mp_card_list_over_time_person
-    ET_CARD_OVER_TIME_VEHICLE = 14, // 车辆井下超时mp_card_list_over_time_vehicle
-    ET_CARD_AREA_OVER_TIME_PERSON = 15, // 人员区域超时
-    ET_CARD_AREA_OVER_TIME_VEHICLE = 16, // 车辆区域超时
-    ET_CARD_AREA_LIMIT_PERSON = 17, // 人员进入限制区域
-    ET_CARD_AREA_LIMIT_VEHICLE = 18, // 车辆进入限制区域
-    ET_CARD_AREA_FORBIDDEN_PERSON = 19,  // 人员进入禁止区域
-    ET_CARD_AREA_FORBIDDEN_VEHICLE = 20, // 车辆进入禁止区域
-    ET_CARD_OVER_SPEED = 21, // 车辆超速
-    ET_CARD_AREA_OVER_SPEED = 22, // 车辆区域超速
-    ET_CARD_RUN_THE_RED_LIGHT = 23, // 车辆闯红灯
-    ET_CARD_HELP = 24, // 人员呼救
-    ET_CARD_CALLED = 25, // 人员已被呼叫
-    ET_CARD_PATROL_ERROR = 26, // 人员巡检异常
-    ET_CARD_LOST = 27, // 标识卡信号丢失
-    ET_CARD_DRIVINGFACE_WARNING_AREA = 28,  // 掘进面靠近预警区域告警
-    ET_CARD_NEAR_DRIVINGFACE_VEHICLE=29,// 人员靠近掘进机告警
-    ET_CARD_NEAR_DRIVINGFACE_OVERCOUNT=30,//掘进机附近人员超员
-    ET_UWB_MORE_CARD = 31,
-    ET_CARD_MOTIONLESS=32,
-    CARD_EVENT_COUNT_MAX,
-};
-
-/**
- * @brief 对象类型
- */
-enum OBJECT_TYPE
-{
-    ///矿井
-    OT_MINE = 1,
-    ///区域
-    OT_AREA = 2,
-    ///路段
-    OT_SECTION = 3,
-    ///分站
-    OT_DEVICE_READER = 4,
-    ///交通灯
-    OT_DEVICE_LIGHT = 5,
-    ///控制分站
-    OT_DEVICE_ctrl_reader = 6,
-    ///led屏
-    OT_DEVICE_LED = 7,
-    ///防爆音箱
-    OT_DEVICE_SPEAKER = 8,
-    ///标识卡,包括人员、车辆、自组网等
-    OT_CARD = 9,
-    ///
-    OT_DRIVINGFACE_AREA=10,
-    ///
-    OT_UWB_MORE_CARD=11,
-};
-
-/**
- * @brief 告警事件
- */
-class ya_event
-{
-private:
-    uint64_t m_ev_id;
-public:
-    ya_event(uint64_t e_id):m_cur_time(std::chrono::system_clock::now())
-    {
-        m_ev_id = e_id;
-
-        m_obj_id = 0;
-        m_map_id = 0;
-        m_area_id = 0;
-        x = 0;
-        y = 0;
-        m_limit_value = 0;
-        m_cur_value = 0;
-        m_desc = "";
-        m_landmarkid = 0;
-        m_landmarkdirect = 0;
-        m_landmarkdist = 0;
-
-        m_status=ES_START;
-    }
-    ~ya_event(){}
-public:
-    ///告警状态,开始、结束
-    EVENT_STATUS m_status;
-
-    ///告警类型
-    EVENT_TYPE m_ev_type;
-    ///告警对象类型
-    OBJECT_TYPE m_obj_type;
-    /// 告警对象编号,与告警对象类型对应,如告警对象类型为分站,此字段为分站编号
-    uint64_t m_obj_id;
-    ///当前时间,为告警事件的触发时间,如果状态为开始,则表示开始时间,否则为结束时间
-    std::chrono::system_clock::time_point m_cur_time;
-
-    ///告警所在地图
-    int m_map_id;
-    ///告警所在区域
-    int m_area_id;
-    ///位置
-    double x;
-    ///位置
-    double y;
-    ///告警阈值
-    double m_limit_value;
-    ///当前值
-    double m_cur_value;
-    ///描述
-    std::string m_desc;
-
-    /// 地标信息
-    int m_landmarkid;
-    /// 与地标的距离
-    double m_landmarkdist;
-    /// 所处地标的方向
-    int m_landmarkdirect;
-
-    ///作为事件map列表的id,方便查找;(obj_type<<32| obj_id)
-    uint64_t m_list_id;
-
-    uint64_t get_id(){return m_ev_id;}
-};
-typedef std::shared_ptr<ya_event> event_ptr;
-typedef std::map<uint64_t, std::shared_ptr<ya_event>> event_map;
-typedef std::shared_ptr<event_map> event_map_ptr;
-
-class tool_time
-{
-public:
-    static uint32_t elapse_seconds(std::chrono::system_clock::time_point &start)
-    {
-        return std::chrono::duration_cast<std::chrono::seconds>
-                     (std::chrono::system_clock::now() - start).count();
-    }
-
-    static uint64_t elapse_ms(std::chrono::system_clock::time_point &start)
-    {
-        return std::chrono::duration_cast<std::chrono::milliseconds>
-                     (std::chrono::system_clock::now() - start).count();
-    }
-
-    static uint32_t now_to_seconds()
-    {
-        return std::chrono::duration_cast<std::chrono::seconds>
-                     (std::chrono::system_clock::now().time_since_epoch()).count();
-    }
-
-    static uint64_t now_to_ms()
-    {
-        return std::chrono::duration_cast<std::chrono::milliseconds>
-                     (std::chrono::system_clock::now().time_since_epoch()).count();
-    }
-
-    static uint64_t to_ms(const std::chrono::system_clock::time_point &time)
-    {
-        return std::chrono::duration_cast<std::chrono::milliseconds>
-                     (time.time_since_epoch()).count();
-    }
-
-    static std::string to_str(const std::chrono::system_clock::time_point &time)
-    {
-        char _time[25] = {0};
-        time_t tt = std::chrono::system_clock::to_time_t(time);
-        struct tm *local_time=localtime(&tt);
-        strftime(_time, 22, "%Y-%m-%d %H:%M:%S", local_time);
-
-        return std::string(_time);
-    }
-
-    ///"%u-%u-%u %u:%u:%u.%u"
-    static std::string to_str_ex(const std::chrono::system_clock::time_point &time)
-    {
-        uint64_t mill = std::chrono::duration_cast<std::chrono::milliseconds>(time.time_since_epoch()).count()
-                -std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count()*1000;
-
-        char _time[25] = {0};
-        time_t tt = std::chrono::system_clock::to_time_t(time);
-        struct tm *local_time=localtime(&tt);
-        //strftime(_time, 22, "%Y-%m-%d %H:%M:%S", local_time);
-        sprintf(_time, "%d-%02d-%02d %02d:%02d:%02d.%d", local_time->tm_year+1900,
-                local_time->tm_mon+1, local_time->tm_mday, local_time->tm_hour,
-                local_time->tm_min, local_time->tm_sec, mill);
-
-        return std::string(_time);
-    }
-};
-
-
-class tool_other
-{
-public:
-
-    static bool is_person(int32_t type)
-    {
-        return CT_PERSON == type;
-    }
-
-    static bool is_vehicle(int32_t type)
-    {
-        return CT_VEHICLE == type;
-    }
-
-    static bool is_up_site(int32_t reader_type_id)
-    {
-        return READER_TYPE_ID_UP == reader_type_id;
-    }
-
-    static bool is_attendance(int32_t stat_attendance)
-    {
-        return AS_ATTENDANCE == stat_attendance;
-    }
-
-    static uint64_t to_uint64_cardid(uint64_t type, uint64_t id)
-    {
-        return (type<<32)|id; ////// (类型<<32)|卡号
-    }
-
-    static uint64_t to_event_list_id(int obj_id, EVENT_TYPE ev_type)
-    {
-        return (static_cast<uint64_t>(ev_type)<<32)|static_cast<uint64_t>(obj_id);
-    }
-
-    static event_ptr create_event(OBJECT_TYPE obj_type, int obj_id, EVENT_TYPE ev_type)
-    {
-        auto ev_ptr = std::make_shared<ya_event>(tool_time::now_to_ms());
-
-        ev_ptr->m_ev_type = ev_type;
-        ev_ptr->m_obj_type = obj_type;
-        ev_ptr->m_obj_id = static_cast<OBJECT_TYPE>(obj_id);
-
-        ev_ptr->m_list_id = to_event_list_id(obj_id, ev_type);
-
-        return ev_ptr;
-    }
-
-    static void insert_event(const event_ptr ev_ptr, event_map& out_ev_map)
-    {
-        out_ev_map.insert(std::make_pair(ev_ptr->m_list_id, ev_ptr));
-    }
-
-    static void copy_event(const std::shared_ptr<card> card_ptr, event_ptr ev_ptr)
-    {
-        ev_ptr->x = card_ptr->x;
-        ev_ptr->y = card_ptr->y;
-
-//        if(nullptr!=card_ptr->m_area_hover)
-//        {
-//           ev_ptr->m_area_id =  card_ptr->m_area_hover->m_area->id();
-//        }
-
-//        ev_ptr->m_landmarkid = card_ptr->m_landmarkid;
-//        ev_ptr->m_landmarkdist = card_ptr->m_landmarkdist;
-//        ev_ptr->m_landmarkdirect = card_ptr->m_landmarkdirect;
-    }
-
-    static event_ptr find_event(int obj_id, EVENT_TYPE ev_type, const event_map& ev_map)
-    {
-        auto it = ev_map.find(to_event_list_id(obj_id, ev_type));
-        if(ev_map.end() == it)
-        {
-            return nullptr;
-        }
-
-        return it->second;
-    }
-};
-
-
-class tool_db
-{
-private:
-    //void CYAServerDlg::load_his_event_data()
-    //load_alarm_reader()
-
-    static void PushAsync(char* sql)
-    {
-        log_debug("PushAsync记录到队列中:%s\n", sql);
-
-        if(!sDBConnPool.PushAsync(sql))
-        {
-            log_error( "PushAsync记录到队列中失败\n");
-        }
-    }
-
-public:
-    static void save_event(const event_ptr ev_ptr)
-    {
-        char sql[LENGTH_SQL] = {'\0'};
-
-        std::string _time = tool_time::to_str(ev_ptr->m_cur_time);
-
-        sprintf(sql,
-                "INSERT IGNORE INTO his_event_data(event_id, stat, event_type_id, obj_type_id, obj_id, \
-                map_id, area_id, limit_value, cur_value, x, y, cur_time, description, \
-                landmark_id, landmark_dist,direction_mapper_id )\
-                VALUES(%ld, %d, %d, %d, %ld, %d, %d, %.2f, %.2f, %f, %f, '%s', '%s', %d, %d, %10.3f);",
-        ev_ptr->get_id(), ev_ptr->m_status, ev_ptr->m_ev_type, ev_ptr->m_obj_type, ev_ptr->m_obj_id,
-                ev_ptr->m_map_id, ev_ptr->m_area_id, ev_ptr->m_limit_value, ev_ptr->m_cur_value, ev_ptr->x, ev_ptr->y,
-                _time.c_str(), ev_ptr->m_desc.c_str(),
-                ev_ptr->m_landmarkid, ev_ptr->m_landmarkdirect, ev_ptr->m_landmarkdist);
-
-        PushAsync(sql);
-    }
-
-    static void save_attendance(const std::shared_ptr<card_location_base> card_ptr,
-                                const std::shared_ptr<area_hover> area_hover_ptr)
-    {
-        char sql[LENGTH_SQL] = {0};
-
-        std::string call("add_att_staff");
-        if(tool_other::is_vehicle(card_ptr->m_type))//车卡
-        {
-            call="add_att_vehicle";
-        }
-
-        auto start = card_ptr->m_attendance_start_time;
-        auto end = card_ptr->m_attendance_start_time;
-        if(!tool_other::is_attendance(card_ptr->m_stat_attendance))//考勤结束时间
-        {
-            std::time_t end_t= card_ptr->m_time/1000;
-            end = std::chrono::system_clock::from_time_t(end_t);
-        }
-
-        std::string start_str = tool_time::to_str(start);
-        std::string end_str = tool_time::to_str(end);
-
-        int landmarkid = 0;
-        int landmarkdirect=0;
-        double landmarkdist=0;
-        if(area_hover_ptr)
-        {
-            landmarkid = area_hover_ptr->landmark_id;
-            landmarkdirect = area_hover_ptr->landmark_dir;
-            landmarkdist = area_hover_ptr->landmark_dis;
-        }
-
-        sprintf(sql, "CALL %s(%d, %d, '%s', '%s', %d, %d, %.3f);", call.c_str(),
-                card_ptr->m_id, card_ptr->m_type, start_str.c_str(), end_str.c_str(),
-                landmarkid, landmarkdirect, landmarkdist);
-
-        PushAsync(sql);
-    }
-
-    static void save_his_raw_data(const std::shared_ptr<card> card_ptr)
-    {
-//        char sql[LENGTH_SQL] = {0};
-//        std::string _time = tool_time::to_str(card_ptr->m_deal_time);
-
-//        sprintf(sql,
-//                "INSERT IGNORE INTO his_raw_data(card_id, reader_id, antenna_id, reader_stamp, card_stamp, \
-//                fly_time, distance, ranging_type, power_state, accelerate, his_time, rec_time ) \
-//                VALUES(%d, %d, %d, %d, %d, %ld, %4.f, %d, %d, %d, '%s', '%s');",
-//                card_ptr->m_id, card_ptr->m_site_id, card_ptr->m_antenna_id,
-//                card_ptr->m_reader_tickcount, card_ptr->m_time_stamp,
-//                card_ptr->m_flying_time, card_ptr->m_distance, card_ptr->m_ranging_type, card_ptr->m_power_state,
-//                card_ptr->m_accelerate_state,
-//                card_ptr->m_str_his_time.c_str(), card_ptr->m_str_rec_time.c_str());
-    }
-
-
-    static void save_his_location(const std::shared_ptr<card_location_base> card_ptr)
-    {
-//        sprintf_s(_time,
-//            STR_LEN_TIME,
-//            "%u-%u-%u %u:%u:%u.%u",
-//            card->deal_time.wYear,card->deal_time.wMonth,card->deal_time.wDay,
-//            card->deal_time.wHour,card->deal_time.wMinute,card->deal_time.wSecond,card->deal_time.wMilliseconds);
-
-//        if(card->map_id != 0 && card->area_id != 0){
-//            b_exec = true;
-//            switch (card->card_type)
-//            {
-//            case CT_PERSON:
-//                sprintf_s(sql, LENGTH_SQL,
-//                    "INSERT IGNORE INTO his_location_staff(card_id, staff_id, cur_time, x, y, z, map_id, area_id, state,speed,mileage, landmark_id, direction_mapper_id, landmark_dist) VALUES(%s, %d, '%s', %.3f, %.3f, %.3f, %d, %d, %d,%.3f,%.4f, %d, %d, %.4f);",
-//                    card->card_id.c_str(), card->id, _time, card->x_offset_after(), card->y_offset_after(), card->z_offset_after(), card->map_id, card->area_id, card->state,card->get_speed(),card->mileage, card->landmark_id, card->landmark_direction, card->landmark_dis);
-//                break;
-//            case CT_VEHICLE:
-//                sprintf_s(sql, LENGTH_SQL,
-//                    "INSERT IGNORE INTO his_location_vehicle(card_id, vehicle_id, cur_time, x, y, z, map_id, area_id, state,speed,mileage, landmark_id, direction_mapper_id, landmark_dist) VALUES(%s, %d, '%s', %.3f, %.3f, %.3f, %d, %d, %d,%.3f,%.4f, %d, %d, %.4f);",
-//                    card->card_id.c_str(), card->id, _time, card->x_offset_after(), card->y_offset_after(), card->z_offset_after(), card->map_id, card->area_id, card->state,card->get_speed(),card->mileage, card->landmark_id, card->landmark_direction, card->landmark_dis);
-//                break;
-//            }
-//        }
-    }
-
-    static void save_his_area_location_enter(const std::shared_ptr<card_location_base> card_ptr)
-    {
-//        sprintf_s(_time,
-//            STR_LEN_TIME,
-//            "%u-%u-%u %u:%u:%u.%u",
-//            card->deal_time.wYear,card->deal_time.wMonth,card->deal_time.wDay,
-//            card->deal_time.wHour,card->deal_time.wMinute,card->deal_time.wSecond,card->deal_time.wMilliseconds);
-
-//        if(card->map_id != 0 && card->area_id != 0){
-//            b_exec = true;
-//            switch (card->card_type)
-//            {
-//            case CT_PERSON:
-//                sprintf_s(sql, LENGTH_SQL,
-//                    "call add_area_staff(%s, %d, %d, %d, '%s','%s');",
-//                    card->card_id.c_str(), card->id, card->area_id, card->map_id, _time, _time);
-//                break;
-//            case CT_VEHICLE:
-//                sprintf_s(sql, LENGTH_SQL,
-//                    "call add_area_vehicle(%s, %d, %d, %d, '%s','%s');",
-//                    card->card_id.c_str(), card->id, card->area_id, card->map_id, _time, _time);
-//                break;
-//            }
-//        }
-    }
-
-    static void save_his_area_location_leave(const std::shared_ptr<card_location_base> card_ptr)
-    {
-//        sprintf_s(_time,
-//            STR_LEN_TIME,
-//            "%u-%u-%u %u:%u:%u.%u",
-//            card->deal_time.wYear,card->deal_time.wMonth,card->deal_time.wDay,
-//            card->deal_time.wHour,card->deal_time.wMinute,card->deal_time.wSecond,card->deal_time.wMilliseconds);
-
-//        if(card->map_id != 0 && card->area_id != 0){
-//            b_exec = true;
-//            sprintf_s(_time_ex,
-//                STR_LEN_TIME,
-//                "%u-%u-%u %u:%u:%u.%u",
-//                card->enter_area_time.wYear,card->enter_area_time.wMonth,card->enter_area_time.wDay,
-//                card->enter_area_time.wHour,card->enter_area_time.wMinute,card->enter_area_time.wSecond,card->enter_area_time.wMilliseconds);
-
-//            switch (card->card_type)
-//            {
-//            case CT_PERSON:
-//                sprintf_s(sql, LENGTH_SQL,
-//                    "call add_area_staff(%s, %d, %d, %d, '%s','%s');",
-//                    card->card_id.c_str(), card->id, card->area_id, card->map_id, _time_ex, _time);
-//                break;
-//            case CT_VEHICLE:
-//                sprintf_s(sql, LENGTH_SQL,
-//                    "call add_area_vehicle(%s, %d, %d, %d, '%s','%s');",
-//                    card->card_id.c_str(), card->id, card->area_id, card->map_id, _time_ex, _time);
-//                break;
-//            }
-//        }
-    }
-};
-
-
+#include"ya_event.h"
+#include"config_file.h"
 
 /**
  * @brief 线程接口类,重写run函数,改变睡眠时间 sleep_ms
@@ -555,7 +32,7 @@ class i_thread
 public:
     i_thread()
     {
-        sleep_ms=10*1000;
+        sleep_ms=5*1000;
     }
 
     virtual ~i_thread(){}
@@ -567,7 +44,7 @@ public:
     {
         _thread_flag=true;
 
-        _thread_handler=std::thread(&i_thread::thread_proc, this);
+        _thread_handler=boost::thread(&i_thread::thread_proc, this);
     }
 
     /**
@@ -576,7 +53,7 @@ public:
     void stop()
     {
         _thread_flag=false;
-        _thread_handler.join();
+        _thread_handler.interrupt();
     }
 
     ///线程睡眠时间 毫秒
@@ -593,7 +70,7 @@ protected:
 
 private:
     /// 线程句柄
-    std::thread _thread_handler;
+    boost::thread _thread_handler;
     /// 线程标志
     std::atomic<bool> _thread_flag;
 
@@ -601,9 +78,19 @@ private:
     {
         while(_thread_flag)
         {
-            run();
+            try
+            {
+                run();
 
-            std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
+                boost::this_thread::sleep_for(boost::chrono::milliseconds(sleep_ms));
+            }
+            catch (boost::thread_interrupted&)
+            {
+            }
+            catch(std::exception&)
+            {
+                log_error("thread_proc exception 结束线程 i_thread");
+            }
         }
     }
 };
@@ -632,11 +119,11 @@ public:
 protected:
     //使继承者无法public构造函数和析构函数
     singleton_base(){}
-    virtual ~singleton_base(){}
+    //virtual ~singleton_base(){}
 private:
     //禁止拷贝构造和赋值运算符
-    singleton_base(const singleton_base& src){}
-    singleton_base &operator=(const singleton_base& src){}
+    singleton_base(const singleton_base&){}
+    singleton_base &operator=(const singleton_base&){}
 
     //它的唯一工作就是在析构函数中析构Singleton的实例,所以private
     class Garbo

+ 0 - 2
module_service/module_mgr.cpp

@@ -1,2 +0,0 @@
-#include "module_mgr.h"
-

+ 87 - 11
module_service/module_mgr.h

@@ -13,6 +13,9 @@
 #include"module_web.h"
 #include"module_area.h"
 #include"module_call_help.h"
+#include"module_call.h"
+#include"module_over_speed_vehicle.h"
+#include"module_other_alarm.h"
 
 class module_mgr: public singleton_base<module_mgr>
 {
@@ -24,32 +27,105 @@ private:
 
 public:
     /**
-     * @brief 注册web回调函数,读数据库初始化事件列表
+     * @brief 注册web回调函数,读配置文件,启动向web发送线程
      */
-    void init(std::map<std::string, YA::MSG_HANDLE_FUNC_TYPE>& MsgFuncList)
+    static void init(config_file& config, std::map<std::string, YA::MSG_HANDLE_FUNC_TYPE>& MsgFuncList)
     {
-        module_web::instance()->init(MsgFuncList);
-        module_area::instance()->init();
-        module_call_help::instance()->init();
+        module_web::instance()->init(config, MsgFuncList);
+        module_call::instance()->init(config);
     }
 
     /**
      * @brief 启动线程start:向web发送事件
      */
-    void start()
+    static void start()
     {
-        module_area::instance()->start();
-        module_call_help::instance()->start();
+        module_over_speed_vehicle::instance()->init_vehicle_category_from_db();
+        //init_attendance_from_db();
+        module_attendance_vehicle::instance()->init_attendance_area_from_db();
+
+        module_web::instance()->start();
+        module_call::instance()->start();
     }
 
     /**
      * @brief 结束线程stop
      */
-    void stop()
+    static void stop()
+    {
+        module_web::instance()->stop();
+        module_call::instance()->stop();
+    }
+
+    static void do_status(STATUS_CARD st, uint32_t card_id, int32_t type)
     {
-        module_area::instance()->stop();
-        module_call_help::instance()->stop();
+        auto card_ptr=card_list::instance()->get(card_list::to_id64(type, card_id));
+        if(!card_ptr)
+        {
+            log_error("卡不存在card_id=%d", card_id);
+            return;
+        }
+
+        if(STATUS_HELP == st)
+        {
+            module_call_help::instance()->rev_from_card_help(card_ptr);
+        }
+        if(STATUS_CALL == st)
+        {
+            module_call::instance()->rev_from_card_resp(card_ptr);
+        }
+        if(STATUS_POWER_LOWER_SERIOUS == st)
+        {
+            module_other_alarm::power_lower_serious(card_ptr);
+        }
+        if(STATUS_POWER_NOMARL == st)
+        {
+            module_other_alarm::power_nomarl(card_ptr);
+        }
     }
+
+//private:
+//    static void init_attendance_from_db()
+//    {
+//        const char *sql = "select card_id, start_time, end_time from rt_att_staff;";
+//        std::string Error;
+//        YADB::CDBResultSet DBRes;
+//        sDBConnPool.Query(sql,DBRes,Error);
+//        uint64_t nCount = DBRes.GetRecordCount( Error );
+//        if (nCount > 0)
+//        {
+//            log_info( "init_attendance. The record count=%d\n", nCount );
+
+//            while ( DBRes.GetNextRecod(Error) )
+//            {
+//                std::string card_id;
+//                DBRes.GetField( "card_id",card_id, Error );
+
+//                std::string end_time;
+//                DBRes.GetField( "end_time",end_time, Error );
+
+//                if(end_time.empty())
+//                {
+//                    uint32_t id = tool_other::id64_to_id(card_id);
+//                    int32_t type = tool_other::id64_to_type(card_id);
+
+//                    auto card_ptr = card_list::instance()->get(card_list::to_id64(type, id));
+//                    if(card_ptr)
+//                    {
+//                        std::string start_time;
+//                        DBRes.GetField( "start_time",start_time, Error );
+
+//                        auto mine_tool_ptr = card_ptr->get_mine_tool();
+
+//                        mine_tool_ptr->m_attendance_start_time = tool_time::to_time_ex(start_time);
+//                        mine_tool_ptr->m_stat_attendance = AS_ATTENDANCE;
+//                        //std_debug("%s",
+//                        //   tool_time::to_str_ex(tool_time::to_ms(site_area_ptr->m_attendance_start_time)).c_str());
+//                    }
+//                }
+//            }
+//        }
+//    }
 };
 
 #endif // MODULE_MGR_H

+ 44 - 0
module_service/module_mine.h

@@ -0,0 +1,44 @@
+#ifndef MODULE_MINE_H
+#define MODULE_MINE_H
+/**
+ * @brief 简要说明
+ * @author 戴月腾
+ * @date 2018-09-21
+ */
+
+#include "module_const.h"
+#include "module_over_speed_vehicle.h"
+
+class module_mine: public singleton_base<module_mine>
+{
+private:
+    friend class singleton_base<module_mine>;
+    module_mine()
+    {
+    }
+
+public:
+    static void on_point(uint32_t card_id,int32_t type, int vehicle_category_id)
+    {
+        auto card_ptr=card_list::instance()->get(card_list::to_id64(type, card_id));
+        if(!card_ptr)
+        {
+            log_error("卡不存在card_id=%d", card_id);
+            return;
+        }
+
+        if(card_ptr->is_person())//人卡
+        {
+
+        }
+
+        if(card_ptr->is_vehicle())//车卡
+        {
+            //区域车卡超速
+            module_over_speed_vehicle::instance()->on_hover(card_ptr, vehicle_category_id);
+        }
+    }
+};
+
+
+#endif // MODULE_MINE_H

+ 65 - 0
module_service/module_other_alarm.h

@@ -0,0 +1,65 @@
+#ifndef MODULE_OTHER_ALARM_H
+#define MODULE_OTHER_ALARM_H
+/**
+ * @brief 简要说明
+ * @author 戴月腾
+ * @date 2018-10-11
+ */
+
+#include <string>
+#include <memory>
+#include <atomic>
+#include <mutex>
+#include <map>
+#include "module_const.h"
+
+
+class module_other_alarm:public singleton_base<module_other_alarm>
+{
+private:
+    friend class singleton_base<module_other_alarm>;
+    module_other_alarm()
+    {
+    }
+
+public:
+    static void power_lower_serious(std::shared_ptr<card_location_base> card_ptr)
+    {
+        auto ev_ptr = event_list::instance()->get_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_LOW_POWER_SERIOUS);
+        if(ev_ptr)
+        {
+            event_list::copy_event(card_ptr, ev_ptr);
+        }
+        else//从没有告警状态转化为告警状态
+        {
+            ev_ptr = event_list::create_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_LOW_POWER_SERIOUS);
+
+            event_list::copy_event(card_ptr, ev_ptr);
+
+            //保存到数据库
+            event_list::save_event(ev_ptr);
+
+            event_list::instance()->add(ev_ptr->get_list_id(),ev_ptr);
+
+            log_info("电量极低告警开始:卡id=%d,卡type=%d", card_ptr->m_id, card_ptr->m_type);
+        }
+    }
+
+    static void power_nomarl(std::shared_ptr<card_location_base> card_ptr)
+    {
+        auto ev_ptr = event_list::instance()->get_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_LOW_POWER_SERIOUS);
+        if(ev_ptr  && !ev_ptr->is_end())
+        {
+            event_list::copy_event(card_ptr, ev_ptr);
+
+            ev_ptr->m_status = ES_END;
+
+            //保存到数据库
+            event_list::save_event(ev_ptr);
+
+            log_info("电量极低告警结束:卡id=%d,卡type=%d", card_ptr->m_id, card_ptr->m_type);
+        }
+    }
+};
+
+#endif // MODULE_OTHER_ALARM_H

+ 159 - 0
module_service/module_over_speed_vehicle.h

@@ -0,0 +1,159 @@
+#ifndef MODULE_OVER_SPEED_VEHICLE_H
+#define MODULE_OVER_SPEED_VEHICLE_H
+/**
+  *@brief 车卡超速模块
+  * @author 戴月腾
+  * @date 2018-08-08
+*/
+
+#include <mutex>
+#include <map>
+#include <chrono>
+#include <boost/thread.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include "module_const.h"
+
+/**
+ * @brief 区域超速类。当某张车卡速度超过某个区域的最大速度时,发出告警, 单例
+ */
+class module_over_speed_vehicle:public singleton_base<module_over_speed_vehicle>
+{
+private:
+    friend class singleton_base<module_over_speed_vehicle>;
+    module_over_speed_vehicle()
+    {
+    }
+
+public:
+    void on_hover(std::shared_ptr<card_location_base> card_ptr, int vehicle_category_id)
+    {
+        auto mine_tool_ptr = card_ptr->get_mine_tool();
+
+        if(is_over_speed(vehicle_category_id, card_ptr->m_speed))//超速
+        {
+            mine_tool_ptr->m_over_speed_count++;
+        }
+        else//速度正常
+        {
+            mine_tool_ptr->m_normal_speed_count++;
+        }
+
+        //确定超速
+        if(SPEED_COUNT_LIMIT <= mine_tool_ptr->m_over_speed_count)
+        {
+            mine_tool_ptr->m_over_speed_count=SPEED_COUNT_LIMIT;
+
+            auto ev_ptr = event_list::instance()->get_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_OVER_SPEED);
+            if(ev_ptr)
+            {
+                event_list::copy_event(card_ptr, ev_ptr);
+
+                ev_ptr->m_limit_value=limit_speed(vehicle_category_id);
+                ev_ptr->m_cur_value=card_ptr->m_speed;
+            }
+            else//从没有告警状态转化为告警状态
+            {
+                mine_tool_ptr->m_normal_speed_count=0;
+
+                auto ev_ptr = event_list::create_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_OVER_SPEED);
+
+                event_list::copy_event(card_ptr, ev_ptr);
+
+                ev_ptr->m_limit_value = limit_speed(vehicle_category_id);
+                ev_ptr->m_cur_value = card_ptr->m_speed;
+
+                //保存到数据库
+                event_list::save_event(ev_ptr);
+
+                event_list::instance()->add(ev_ptr->get_list_id(),ev_ptr);
+
+                log_info("车卡矿井内超速开始:卡id=%d,卡type=%d,卡速=%f,卡category_id=%d,卡速门限=%f",
+                         card_ptr->m_id, card_ptr->m_type,card_ptr->m_speed,vehicle_category_id,
+                         limit_speed(vehicle_category_id));
+            }
+        }
+
+        //确定速度正常
+        if(SPEED_COUNT_LIMIT <= mine_tool_ptr->m_normal_speed_count)
+        {
+            mine_tool_ptr->m_normal_speed_count=SPEED_COUNT_LIMIT;
+
+            auto ev_ptr = event_list::instance()->get_event_card(card_ptr->m_id, card_ptr->m_type, ET_CARD_OVER_SPEED);
+            if(ev_ptr && !ev_ptr->is_end())
+            {
+                mine_tool_ptr->m_over_speed_count=0;
+
+                event_list::copy_event(card_ptr, ev_ptr);
+
+                ev_ptr->m_limit_value = limit_speed(vehicle_category_id);
+                ev_ptr->m_cur_value = card_ptr->m_speed;
+
+                ev_ptr->m_status = ES_END;
+
+                //保存到数据库
+                event_list::save_event(ev_ptr);
+
+                log_info("车卡矿井内超速结束:卡id=%d,卡type=%d,卡速=%f,卡category_id=%d,卡速门限=%f",
+                         card_ptr->m_id, card_ptr->m_type,card_ptr->m_speed,vehicle_category_id,
+                         limit_speed(vehicle_category_id));
+            }
+        }
+    }
+
+    void init_vehicle_category_from_db()
+    {
+        const char *sql = "SELECT vehicle_category_id, over_speed FROM dat_vehicle_category;";
+        std::string Error;
+        YADB::CDBResultSet DBRes;
+        sDBConnPool.Query(sql,DBRes,Error);
+        if(!Error.empty())
+            log_error("init_vehicle_category Error,%s",Error.c_str());
+        uint64_t nCount = DBRes.GetRecordCount( Error );
+        if (nCount > 0)
+        {
+            log_info( "init_vehicle_category. The record count=%ld\n", nCount );
+
+            while ( DBRes.GetNextRecod(Error) )
+            {
+                int vehicle_category_id  = 0;
+                DBRes.GetField( "vehicle_category_id",vehicle_category_id, Error );
+
+                double over_speed = 0;
+                DBRes.GetField( "over_speed",over_speed, Error );
+
+                _vehicle_category_map.insert({vehicle_category_id,over_speed});
+            }
+
+            for(const auto &p : _vehicle_category_map)
+                std_debug("dat_vehicle_category:category_id:%d--over_speed:%.2f",p.first,p.second);
+        }
+    }
+
+private:
+    bool is_over_speed(int category_id, double speed)
+    {
+        auto serch = _vehicle_category_map.find(category_id);
+        if(serch == _vehicle_category_map.end())
+        {
+            return false;
+        }
+
+        return serch->second <= speed;
+    }
+
+    double limit_speed(int category_id) const
+    {
+        auto serch = _vehicle_category_map.find(category_id);
+        if(serch == _vehicle_category_map.end())
+        {
+            return 0;
+        }
+
+        return serch->second;
+    }
+
+private:
+    std::unordered_map<int,double> _vehicle_category_map;
+};
+
+#endif // MODULE_OVER_SPEED_VEHICLE_H

+ 92 - 0
module_service/module_site.h

@@ -0,0 +1,92 @@
+#ifndef MODULE_SITE_H
+#define MODULE_SITE_H
+
+#include"math.h"
+#include <memory>
+#include <mutex>
+#include <map>
+#include <string>
+#include <chrono>
+#include <vector>
+#include<card.h>
+#include"ant.h"
+#include"area.h"
+#include"site_area.h"
+#include"module_const.h"
+#include"module_attendance_person.h"
+
+class module_site : public singleton_base<module_site>
+{
+private:
+    friend class singleton_base<module_site>;
+    module_site()
+    {
+    }
+
+public:
+    /**
+     * @brief 进入分站覆盖区域处理,考勤
+     * @param card_id
+     * @param enter_site
+     */
+    static void enter_site(uint32_t card_id,int enter_site,int32_t type)
+    {
+        auto card_ptr=card_list::instance()->get(card_list::to_id64(type, card_id));
+        if(!card_ptr)
+        {
+            log_error("卡不存在card_id=%ld, type=%ld", card_id, type);
+            return;
+        }
+
+        auto site_ptr=sit_list::instance()->get(enter_site);
+        if(!site_ptr)
+        {
+            log_error("[enter site]%d,%d在分站列表中找不到分站,分站id=%d",card_id, type,enter_site);
+            return;
+        }
+
+        if(card_ptr->is_person())
+        {
+            module_attendance_person::instance()->enter_site(card_ptr, site_ptr);
+        }
+
+        if(card_ptr->is_vehicle())
+        {
+
+        }
+    }
+
+    /**
+     * @brief 离开现有分站处理,记录现有分站的进出时间和地点
+     * @param card_id
+     * @param enter_site
+     */
+    static void leave_site(uint32_t card_id,int enter_site, int32_t type)
+    {
+        auto card_ptr=card_list::instance()->get(card_list::to_id64(type, card_id));
+        if(!card_ptr)
+        {
+            log_error("卡不存在card_id=%ld, type=%ld", card_id, type);
+            return;
+        }
+
+        auto site_ptr=sit_list::instance()->get(enter_site);
+        if(!site_ptr)
+        {
+            log_error("[leave site]%d,%d在分站列表中找不到分站,分站id=%d",card_id,type, enter_site);
+            return;
+        }
+
+        if(card_ptr->is_person())
+        {
+
+        }
+
+        if(card_ptr->is_vehicle())
+        {
+
+        }
+    }
+};
+
+#endif // MODULE_SITE_H

+ 48 - 36
module_service/module_web.cpp

@@ -3,61 +3,58 @@
 #include"module_call_help.h"
 #include"module_call.h"
 #include"module_area.h"
-
-
+#include"module_attendance_person.h"
 
 void module_web::accept( int ID, std::string const& name,
                          sio::message::ptr const& data, bool need_ack, sio::message::list &ack_resp )
 {
-    log_debug("收到web发来的数据 ");
-
     if(data->get_flag() != sio::message::flag_object)
     {
-        log_error("发来的数据不是对象");
+        log_error("web发来的数据不是对象");
         return;
     }
 
-    std::string cmd = data->get_map()[JSON_ROOT_KEY_CMD]->get_string();
-    if(cmd.empty())
+    std::string cmd = "";
+    if(!tool_map::try_get_value(cmd, JSON_ROOT_KEY_CMD, data) || cmd.empty())
     {
-        log_error("cmd字段为空");
+        log_error("web发来的数据cmd字段为空");
         return;
     }
 
-    log_info(data->get_map()[JSON_ROOT_KEY_DATA]->get_string().c_str());
+    log_info("web发来的数据 cmd=%s", cmd.c_str());
 
-    if (JSON_CMD_VALUE_REQUEST_ALL_DATA == cmd)//web登录请求所有信息
+    if(JSON_CMD_VALUE_CLEAR_CARD == cmd)//手动升井
     {
-        module_web::instance()->response_login();
+        module_attendance_person::instance()->handle_up_mine(data);
     }
-    else if(JSON_CMD_VALUE_DEAL_HELP == cmd) // 处理呼救信息
+    else if (JSON_CMD_VALUE_REQUEST_ALL_DATA == cmd)//web登录请求所有信息
     {
-        module_call_help::instance()->accept_deal_help(data->get_map()[JSON_ROOT_KEY_DATA]->get_map());
+        module_web::instance()->response_login();
     }
     else
     {
-        std::string json=data->get_map()[JSON_ROOT_KEY_DATA]->get_string();
-        rapidjson::Document doc;
-        doc.Parse(json.c_str());
-
-        if(doc.HasParseError())
+        sio::message::ptr data_value;
+        if(!tool_map::try_get_value(data_value, JSON_ROOT_KEY_DATA, data))
         {
-            log_error("发来的data字段数据有错误");
+            log_error("web发来的数据data字段格式不对, 不是map");
             return;
         }
 
-        if(JSON_CMD_VALUE_CALL_CARD_REQUEST == cmd)//呼叫
+        if(JSON_CMD_VALUE_DEAL_HELP == cmd) // 处理呼救信息
         {
-            module_call::instance()->accept_call(doc);
+            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(doc);
+            module_call::instance()->accept_cancel(data_value);
         }
     }
 }
 
-
 void module_web::response_login()
 {
     rapidjson::Document doc(rapidjson::kObjectType);
@@ -68,21 +65,15 @@ void module_web::response_login()
     std::string str=module_call::instance()->accept_login();
     if(!str.empty())
     {
-        nodes.PushBack(rapidjson::StringRef(str.c_str()), allocator);
-    }
-
-    //所有的呼救信息
-    str=module_call_help::instance()->response_login();
-    if(!str.empty())
-    {
-        nodes.PushBack(rapidjson::StringRef(str.c_str()), allocator);
+        tool_json::push_back(nodes, str, allocator);
     }
 
-    //所有其他告警
-    str=module_area::instance()->response_login();
-    if(!str.empty())
+    //所有告警
+    std::vector<std::shared_ptr<ya_event>> arr;
+    get_all_events(arr);
+    if(!arr.empty())
     {
-        nodes.PushBack(rapidjson::StringRef(str.c_str()), allocator);
+        tool_json::push_back(nodes, event_list::evs_to_json(arr), allocator);
     }
 
     if(nodes.Size()>0)
@@ -91,10 +82,31 @@ void module_web::response_login()
         doc.AddMember(JSON_ROOT_KEY_VERSION, INTERFACE_VERSION, allocator);
         doc.AddMember(JSON_ROOT_KEY_DATA, nodes, allocator);
 
-        swsClientMgr.send(JSON_CMD_VALUE_PUSH, tool_json::doc_to_json(doc));
+        tool_other::send_json(JSON_CMD_VALUE_PUSH, tool_json::doc_to_json(doc));
     }
 }
 
+void module_web::run()
+{
+    std::vector<std::shared_ptr<ya_event>> arr;
+    get_all_events(arr);
+
+    if(!arr.empty())//发送给web端
+    {
+        delete_end(arr);
+
+        tool_other::send_json(JSON_CMD_VALUE_PUSH, event_list::evs_to_json(arr));
+    }
+
+    std::string help = module_call_help::get_json_help();
+    if(!help.empty())
+    {
+        tool_other::send_json(JSON_CMD_VALUE_PUSH, help);
+    }
+}
+
+
+
 
 
 

+ 27 - 274
module_service/module_web.h

@@ -13,121 +13,9 @@
 
 #include "rapidjson/prettywriter.h"
 #include "rapidjson/document.h"
-
 #include "websocket/wsClientMgr.h"
 
-//#define JSON_ROOT_KEY_CMD "cmd"
-//#define JSON_ROOT_KEY_VERSION "version"
-//#define INTERFACE_VERSION "1.0.0.2"
-//#define JSON_ROOT_KEY_DATA "data"
-
-////呼叫命令
-//#define JSON_CMD_VALUE_CALL_CARD_REQUEST "call_card_req"
-//#define JSON_CMD_VALUE_CALL_CARD_RESPONSE "call_card_resp"
-//#define JSON_CMD_VALUE_CALL_CARD_CANCEL_REQUEST "call_card_cancel_req"
-//#define JSON_CMD_VALUE_CALL_CARD_CANCEL_RESPONSE "call_card_cancel_resp"
-//#define JSON_CMD_VALUE_CALL_CARD_LIST "callcardlist"
-
-//#define JSON_KEY_CALL_CARD_CALL_TYPE "call_type_id"
-//#define JSON_KEY_CALL_CARD_CALL_TIME_OUT "call_time_out"
-//#define JSON_KEY_CALL_CARD_CALL_TIME "call_time"
-//#define JSON_KEY_CALL_CARD_CALL_LEVEL "call_level_id"
-//#define JSON_KEY_CALL_CARD_USER_NAME "user_name"
-//#define JSON_KEY_CALL_CARD_STATIONS "stations"
-//#define JSON_KEY_CALL_CARD_STATION_ID "stationid"
-//#define JSON_KEY_CALL_CARD_CARDS "cards"
-//#define JSON_KEY_CALL_CARD_CARD_ID "cardid"
-//#define JSON_KEY_CALL_CARD_CARD_TYPE_ID "cardtype"
-
-//#define JSON_KEY_CALL_LIGHT_TASK_ID "task_id"
-//#define JSON_KEY_CALL_LIGHT_OBJ_TYPE "obj_type"
-//#define JSON_KEY_CALL_LIGHT_CTRL_TYPE "ctrl_type"
-//#define JSON_KEY_CALL_LIGHT_LIGHT_STATE "light_state"
-//#define JSON_KEY_CALL_LIGHT_USER_ID "user_id"
-//#define JSON_KEY_CALL_LIGHT_LIGHTS "lights"
-//#define JSON_KEY_CALL_LIGHT_ID "id"
-
-//#define JSON_KEY_ID "id"
-//#define JSON_KEY_OP_TYPE "op_type"
-//#define JSON_KEY_OP_TYPE_INSERT "INSERT"
-//#define JSON_KEY_OP_TYPE_UPDATE "UPDATE"
-//#define JSON_KEY_OP_TYPE_DELETE "DELETE"
-
-//// 采集端接收接口
-//#define JSON_CMD_VALUE_CLEAR_CARD "clear_card"
-//#define JSON_CMD_VALUE_DEAL_HELP "helpme_done"   //deal_help
-//#define JSON_CMD_VALUE_DEAL_HELP_RESPONSE "helpme_done_rsp"   //deal_help
-//#define JSON_CMD_VALUE_REQUEST_ALL_POSTION "request_all_postion"
-//#define JSON_CMD_VALUE_REQUEST_ALL_DATA "req_all_data"
-//#define JSON_CMD_VALUE_RESPONSE_ALL_DATA "resp_all_data"
-//#define JSON_CMD_VALUE_CALL_CARD_START "call_card_start"
-//#define JSON_CMD_VALUE_CALL_CARD_CANCEL "call_card_cancel"
-//#define  JSON_CMD_VALUE_LEADER_ARRANGE "leader_arrange"
-////呼叫命令
-//#define JSON_CMD_VALUE_CALL_CARD_REQUEST "call_card_req"
-//#define JSON_CMD_VALUE_CALL_CARD_RESPONSE "call_card_resp"
-//#define JSON_CMD_VALUE_CALL_CARD_CANCEL_REQUEST "call_card_cancel_req"
-//#define JSON_CMD_VALUE_CALL_CARD_CANCEL_RESPONSE "call_card_cancel_resp"
-//#define JSON_CMD_VALUE_CALL_CARD_LIST "callcardlist"
-
-//#define JSON_CMD_VALUE_META_DATA_CHANGED "meta_data_changed"
-//#define JSON_CMD_VALUE_LIGHTS_CTRL_REQUEST "light_control"
-//#define JSON_CMD_VALUE_LIGHTS_CTRL_RESPONSE "lights_ctrl_res"
-//#define JSON_CMD_VALUE_HAND_UP_RESPONSE "deal_hand_up_res"
-
-//// id, name, type, map_id
-//#define JSON_KEY_AREA_ID "area_id" // "区域编号"
-//#define JSON_KEY_AREA_IS_SPECIAL "is_special_area" // "区域名称"
-//// down_mine,up_mine
-//#define JSON_CMD_VALUE_DOWN_MINE "down_mine"
-//#define JSON_CMD_VALUE_UP_MINE "up_mine"
-//#define JSON_CMD_VALUE_SPECIAL_AREA_UP_MINE "special_area_up_mine"
-//#define JSON_CMD_VALUE_DEV_STATE "device_state"
-//#define JSON_CMD_VALUE_EVENT "event"
-//#define JSON_CMD_VALUE_CALL "CALL"
-//#define JSON_CMD_VALUE_PUSH "PUSH"
-//#define JSON_CMD_VALUE_USER "USER"
-//#define JSON_CMD_DRIVING_FACE_STATE "tunneller_stat"
-
-
-//#define JSON_ROOT_KEY_TOTAL "total"
-//#define JSON_ROOT_KEY_STATISTIC_VEHICLE_DATA "v"
-//#define JSON_ROOT_KEY_STATISTIC_STAFF_DATA "s"
-//#define JSON_ROOT_KEY_STATISTIC_STAT "stat"
-//#define JSON_ROOT_KEY_STATISTIC_DETAIL "detail"
-//#define JSON_ROOT_KEY_STATISTIC_GLOBAL "glbl"
-//#define JSON_ROOT_KEY_STATISTIC_DEPT "dept"
-//#define JSON_ROOT_KEY_STATISTIC_SUM "sum"
-//#define JSON_ROOT_KEY_STATISTIC_AREA "area"
-//#define JSON_ROOT_KEY_STATISTIC_LEVEL "occupation_level"
-
-//// 告警事件
-//#define JSON_KEY_EVENT_EVENT_ID "event_id"
-//#define JSON_KEY_EVENT_STATUS "status"
-//#define JSON_KEY_EVENT_TYPE_ID "type_id"
-//#define JSON_KEY_EVENT_OBJ_TYPE_ID "obj_type_id"
-//#define JSON_KEY_EVENT_OBJ_ID "obj_id"
-//#define JSON_KEY_EVENT_MAP_ID "map_id"
-//#define JSON_KEY_EVENT_AREA_ID "area_id"
-//#define JSON_KEY_EVENT_X "x"
-//#define JSON_KEY_EVENT_Y "y"
-//#define JSON_KEY_EVENT_LIMIT_VALUE "limit_value"
-//#define JSON_KEY_EVENT_CUR_VALUE "cur_value"
-//#define JSON_KEY_EVENT_CUR_TIME "cur_time"
-//#define JSON_KEY_EVENT_LANDMARK_ID "lmid"
-//#define JSON_KEY_EVENT_LANDMARK_DIRECTION "lmdirect"
-//#define JSON_KEY_EVENT_LANDMARK_DISTANCE "lmdistance"
-//#define JSON_KEY_EVENT_READER_POS_CHANGE    "reader_pos_change"
-
-//// alarm
-//#define JSON_KEY_ALARM_OVER_COUNT_PERSON "over_count_person"
-//#define JSON_KEY_ALARM_OVER_COUNT_VEHICLE "over_count_vehicle"
-//#define JSON_KEY_ALARM_OVER_TIME_PERSON "over_time_person"
-//#define JSON_KEY_ALARM_OVER_TIME_VEHICLE "over_time_vehicle"
-//#define JSON_KEY_ALARM_OVER_SPEED_VEHICLE "over_speed_vehicle"
-
-
-class module_web : public singleton_base<module_web>
+class module_web : public i_thread, public singleton_base<module_web>
 {
 private:
     friend class singleton_base<module_web>;
@@ -151,192 +39,57 @@ public:
      * @brief 注册web请求回调函数
      * @param MsgFuncList
      */
-    void init(std::map<std::string, YA::MSG_HANDLE_FUNC_TYPE>& MsgFuncList)
+    void init(config_file& config, std::map<std::string, YA::MSG_HANDLE_FUNC_TYPE>& MsgFuncList)
     {
+        sleep_ms = std::stoi(config.get("service.interval_send_json_alarm","10000"));
+
         MsgFuncList.insert( std::make_pair( JSON_CMD_VALUE_REQUEST_ALL_DATA, &module_web::accept ) );
         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 ) );//手动升井
     }
 
     /// web前端有用户登录时,反馈给web所有信息
     void response_login();
-};
-
-class tool_json
-{
-public:
-    static bool try_get_iter(const char* key, const rapidjson::Value& node,
-                             rapidjson::Value::ConstMemberIterator& out_iter)
-    {
-        if(node.IsObject())
-        {
-            out_iter = node.FindMember(key);
-            if(node.MemberEnd() == out_iter)
-            {
-                return false;
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-    static bool try_get_value(int& d, const char* key, const rapidjson::Value& node)
-    {
-        rapidjson::Value::ConstMemberIterator iter;
-        if(try_get_iter(key, node, iter))
-        {
-            if(iter->value.IsInt())
-            {
-                d = iter->value.GetInt();
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    static bool try_get_value(uint64_t& d, const char* key, const rapidjson::Value& node)
-    {
-        rapidjson::Value::ConstMemberIterator iter;
-        if(try_get_iter(key, node, iter))
-        {
-            if(iter->value.IsUint64())
-            {
-                d = iter->value.GetUint64();
-                return true;
-            }
-        }
-        return false;
-    }
-
-    static bool try_get_value(double& d, const char* key, const rapidjson::Value& node)
-    {
-        rapidjson::Value::ConstMemberIterator iter;
-        if(try_get_iter(key, node, iter))
-        {
-            if(iter->value.IsDouble())
-            {
-                d = iter->value.GetDouble();
-                return true;
-            }
-        }
-        return false;
-    }
-
-    static bool try_get_value(std::string& d, const char* key, const rapidjson::Value& node)
-    {
-        rapidjson::Value::ConstMemberIterator iter;
-        if(try_get_iter(key, node, iter))
-        {
-            if(iter->value.IsString())
-            {
-                d = iter->value.GetString();
-                return true;
-            }
-        }
 
-        return false;
-    }
+private:
+    /**
+     * @brief 线程函数
+     */
+    void run();
 
-    static int get_value(const char* key, const int& default_data, const rapidjson::Value& node)
+    ///获取所有的告警事件
+    void get_all_events(std::vector<std::shared_ptr<ya_event>>& arr)
     {
-        rapidjson::Value::ConstMemberIterator iter;
-        if(try_get_iter(key, node, iter))
+        auto _map = event_list::instance()->m_map;
+        auto it_map = _map.begin();
+        for(;it_map!=_map.end();++it_map)
         {
-            if(iter->value.IsInt())
-            {
-                return  iter->value.GetInt();
-            }
+            arr.push_back(it_map->second);
         }
-
-        return default_data;
     }
 
-    static std::string get_value(const char* key, const std::string& default_data, const rapidjson::Value& node)
+    ///在全局列表中删除已经处理或结束了的告警
+    void delete_end(std::vector<std::shared_ptr<ya_event>>& arr)
     {
-        rapidjson::Value::ConstMemberIterator iter;
-        if(try_get_iter(key, node, iter))
+        std::vector<uint64_t> todelete;
+        auto arr_iter = arr.begin();
+        for(;arr_iter!=arr.end();++arr_iter)
         {
-            if(iter->value.IsString())
+            if((*arr_iter)->is_end())//删除掉已经处理的
             {
-                return iter->value.GetString();
+                todelete.push_back((*arr_iter)->get_list_id());
             }
         }
 
-        return default_data;
-    }
-
-    static std::string doc_to_json(rapidjson::Document& doc)
-    {
-        rapidjson::StringBuffer sb;
-        rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
-        doc.Accept(writer);
-
-        return sb.GetString();
-    }
-
-    static std::string ev_to_json(std::shared_ptr<ya_event> ev_ptr)
-    {
-        std::vector<std::shared_ptr<ya_event>> evs;
-        evs.push_back(ev_ptr);
-        return evs_to_json(evs);
-    }
-
-    static std::string evs_to_json(std::vector<std::shared_ptr<ya_event>> evs)
-    {
-        rapidjson::Document doc(rapidjson::kObjectType);
-        rapidjson::Value data(rapidjson::kArrayType);
-        rapidjson::Document::AllocatorType& allocator=doc.GetAllocator();
-
-        auto it=evs.begin();
-        for(;it!=evs.end();++it)
+        if(todelete.size())
         {
-            ev_to_node(*it, allocator, data);
+            event_list::instance()->remove(todelete);
         }
-
-        doc.AddMember(JSON_ROOT_KEY_CMD,JSON_CMD_VALUE_EVENT, allocator);
-        doc.AddMember(JSON_ROOT_KEY_VERSION,INTERFACE_VERSION, allocator);
-        doc.AddMember(JSON_ROOT_KEY_DATA,data, allocator);
-
-        rapidjson::StringBuffer sb;
-        rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
-        doc.Accept(writer);
-
-        return sb.GetString();
     }
-
-private:
-    static void ev_to_node(std::shared_ptr<ya_event> ev_ptr,
-                                        rapidjson::Document::AllocatorType& allocator,
-                                        rapidjson::Value& out_data)
-    {
-        rapidjson::Value ev(rapidjson::kObjectType);
-
-        ev.AddMember(JSON_KEY_EVENT_EVENT_ID,ev_ptr->get_id(), allocator);
-        ev.AddMember(JSON_KEY_EVENT_STATUS,ev_ptr->m_status, allocator);
-
-        ev.AddMember(JSON_KEY_EVENT_TYPE_ID,ev_ptr->m_ev_type, allocator);
-        ev.AddMember(JSON_KEY_EVENT_OBJ_TYPE_ID,ev_ptr->m_obj_type, allocator);
-        ev.AddMember(JSON_KEY_EVENT_OBJ_ID,ev_ptr->m_obj_id, allocator);
-        ev.AddMember(JSON_KEY_EVENT_MAP_ID,ev_ptr->m_map_id, allocator);
-        ev.AddMember(JSON_KEY_EVENT_AREA_ID,ev_ptr->m_area_id, allocator);
-        ev.AddMember(JSON_KEY_EVENT_X,ev_ptr->x, allocator);
-        ev.AddMember(JSON_KEY_EVENT_Y,ev_ptr->y, allocator);
-
-        ev.AddMember(JSON_KEY_EVENT_LIMIT_VALUE,ev_ptr->m_limit_value, allocator);
-        ev.AddMember(JSON_KEY_EVENT_CUR_VALUE,ev_ptr->m_cur_value, allocator);
-        ev.AddMember(JSON_KEY_EVENT_CUR_TIME,tool_time::to_ms(ev_ptr->m_cur_time), allocator);
-
-        ev.AddMember(JSON_KEY_EVENT_LANDMARK_ID,ev_ptr->m_landmarkid, allocator);
-        ev.AddMember(JSON_KEY_EVENT_LANDMARK_DIRECTION,ev_ptr->m_landmarkdirect, allocator);
-        ev.AddMember(JSON_KEY_EVENT_LANDMARK_DISTANCE,ev_ptr->m_landmarkdist, allocator);
-
-        out_data.PushBack(ev, allocator);
-    }
-
 };
 
+
 #endif // MODULE_WEB_H

+ 8 - 7
net-service.cpp

@@ -43,13 +43,14 @@ void net_service::on_message(std::shared_ptr<client> clt,const char*data,size_t
 			{
 				uint32_t site_id;
 				is>>site_id>>skip(12);
-				const auto sit_=sit_list::instance()->get(site_id);
-				if(sit_==nullptr)
-				{
-				  log_error("site is not exist...");
-				  break;
-				}
-				sit_->set_client(clt);
+               auto site_ptr = sit_list::instance()->get(static_cast<int32_t>(site_id));
+                if(!site_ptr)
+                {
+                    log_error("在全局分站列表中找不到分站:分站id=%d", site_id);
+                    break;
+                }
+                site_ptr->set_client(clt);
+
 				struct timeval tv;
 				gettimeofday(&tv,NULL);
 				uint64_t t = tv.tv_sec*1000 + tv.tv_usec/1000;

+ 1 - 2
select_tool.h

@@ -6,8 +6,7 @@
 #include <memory>
 #include "ant.h"
 #include "card_path.h"
-class loc_message;
-
+#include "loc_message.h"
 struct solpoint:point
 {
 	solpoint()

+ 16 - 22
site_area.cpp

@@ -1,19 +1,13 @@
 
 #include "site_area.h"
-
 #include "card.h"
+#include "module_service/module_site.h"
 
 //每张卡包含这样一个对象,保存最后一个分站区域
 //1、记录卡进出分站的时间,地点
 //2、用于考勤
-site_area_hover::site_area_hover()
-	:m_site_id(-1)
-	,m_enter_time(0)
-	,m_last_time(0)
-{
-}
 
-void site_area_hover::on_point(uint64_t card_id,int site_id,const point*pt)
+void site_area_hover::on_point(uint32_t card_id,int site_id,const point*pt,int32_t type)
 {
 	if(pt!=nullptr)
 	{
@@ -26,30 +20,30 @@ void site_area_hover::on_point(uint64_t card_id,int site_id,const point*pt)
 	{
 		if(m_site_id==site_id) 
 			return;
+        int last_id = m_site_id;
+        m_site_id = site_id;
 
-		//离开现有分站处理,记录现有分站的进出时间和地点
-        leave_site(card_id,m_site_id);
+        //离开现有分站处理,记录现有分站的进出时间和地点
+        leave_site(card_id,last_id,type);
 
-		//进入分站覆盖区域处理,考勤
-		enter_site(card_id,site_id);
+        //进入分站覆盖区域处理,考勤
+        enter_site(card_id,site_id,type);
 
-		m_site_id=site_id;
-		m_enter_time=m_last_time=time(nullptr);
-		m_enter_point.set(0,0);
-		m_last_point.set(0,0);
+        //m_site_id=site_id;
+        m_enter_time=m_last_time=time(nullptr);
+        m_enter_point.set(0,0);
+        m_last_point.set(0,0);
 	}
 }
 
-void site_area_hover::enter_site(uint64_t card_id,int enter_site)
+void site_area_hover::enter_site(uint32_t card_id,int enter_site,int32_t type)
 {
-
-
+    module_site::enter_site(card_id, enter_site, type);
 }
 
-void site_area_hover::leave_site(uint64_t card_id,int enter_site)
+void site_area_hover::leave_site(uint32_t card_id,int enter_site,int32_t type)
 {
-
-
+    module_site::leave_site(card_id, enter_site, type);
 }
 
 

+ 25 - 5
site_area.h

@@ -1,23 +1,43 @@
 #ifndef __SITE_AREA_HOVER_HPP__
 #define __SITE_AREA_HOVER_HPP__
 #include <point.h>
+#include<chrono>
+#include "common.h"
+
 //每张卡包含这样一个对象,保存最后一个分站区域;只有tof一维有这个需求
 //1、记录卡进出分站的时间,地点
 //2、用于考勤
 struct site_area_hover
 {
-	site_area_hover();
+    site_area_hover()
+        :m_site_id(-1)
+        ,m_enter_time(0)
+        ,m_last_time(0)
+    {
+    }
 	//调用时机:
 	//1、tof一维收到第一个数据点时,以pt=0调用
 	//2、数据点解析完毕之后调用
-    void on_point(uint64_t card_id,int site_id,const point*pt);
+    void on_point(uint32_t card_id,int site_id,const point*pt,int32_t type);
 private:
-    void enter_site(uint64_t card_id,int enter_site);
-    void leave_site(uint64_t card_id,int enter_site);
+    void enter_site(uint32_t card_id,int enter_site,int32_t type);
+    void leave_site(uint32_t card_id,int enter_site,int32_t type);
 
-	int    m_site_id;
+private:
+    int    m_site_id;
 	time_t m_enter_time,m_last_time;
 	point  m_enter_point,m_last_point;
+
+public:
+    int site_id() const
+    {
+        return m_site_id;
+    }
+
+    bool is_invalid()
+    {
+        return -1==m_site_id;
+    }
 };
 #endif
 

+ 2 - 2
websocket/jsonBuilder.cpp

@@ -357,7 +357,7 @@ namespace YA
 		return sb.GetString();
 	}
 
-	std::string jsonBuilder::BuildCardPos( const std::map<int, _CARD_POS_>& CardPosList )
+	std::string jsonBuilder::BuildCardPos( const std::map<uint64_t, _CARD_POS_>& CardPosList )
 	{
 		rapidjson::StringBuffer sb;
 		rapidjson::Writer<rapidjson::StringBuffer> writer( sb );
@@ -378,7 +378,7 @@ namespace YA
 		std::map<int, _STAT_DEPT_ITEM_> v_dept_map;
 		_STAT_DEPT_ITEM_ s_glbl_item;
 		_STAT_DEPT_ITEM_ v_glbl_item;
-		std::map<int, _CARD_POS_>::const_iterator mit_card;
+		std::map<uint64_t, _CARD_POS_>::const_iterator mit_card;
 		for ( mit_card = CardPosList.begin(); mit_card != CardPosList.end(); mit_card++ )
 		{
 			//不显示的卡不往前端推送

+ 1 - 1
websocket/jsonBuilder.h

@@ -244,7 +244,7 @@ namespace YA
 		* @bug
 
 		*/
-		std::string BuildCardPos( const std::map<int, _CARD_POS_>& CardPosList );
+		std::string BuildCardPos( const std::map<uint64_t, _CARD_POS_>& CardPosList );
 		/**
 		* @brief
 		生成车辆进入特殊区域jason函数。

+ 12 - 6
websocket/wsTimerThread.cpp

@@ -3,6 +3,7 @@
 
 #include "wsClientMgr.h"
 #include "constdef.h"
+#include "log.h"
 
 namespace YA
 {
@@ -61,14 +62,15 @@ namespace YA
 
 	void wsTimerThread::__SendCardPos()
 	{
-		std::map<int, _CARD_POS_> CardPosList;
+		std::map<uint64_t, _CARD_POS_> CardPosList;
 		__CardPosList.copy( CardPosList );
 		std::string jsCardPos = __jsBuilder.BuildCardPos( CardPosList );
+		log_info("[pos_map]%s",jsCardPos.c_str());
 		swsClientMgr.send( JSON_CMD_VALUE_PUSH, jsCardPos );
 	}
 
 	void wsTimerThread::_ThreadFunc( wsTimerThread * pOwner )
-	{
+	{	
 		while ( pOwner->__Enable )
 		{
 			std::tm *Now;
@@ -98,18 +100,22 @@ namespace YA
 	void wsTimerThread::upt_card_pos( const _CARD_POS_ & pos )
 	{
 		//如果已存在就更新,否则插入
-		if ( __CardPosList.seek( pos.ID ) )
+		uint64_t type = pos.Type;
+		uint64_t id=type<<32|pos.ID;
+		if ( __CardPosList.seek( id  ) )
 		{
-			__CardPosList.update( pos.ID, pos );
+			__CardPosList.update( id, pos );
 		}
 		else
 		{
-			__CardPosList.insert( pos.ID, pos );
+			__CardPosList.insert( id, pos );
 		}
 	}
 
 	void wsTimerThread::del_card_pos( const _CARD_POS_ & pos )
 	{
-		__CardPosList.erase( pos.ID );
+		uint64_t type = pos.Type;
+		uint64_t id=type<<32|pos.ID;
+		__CardPosList.erase( id );
 	}
 }

+ 2 - 2
websocket/wsTimerThread.h

@@ -46,7 +46,7 @@ namespace YA
 		boost::condition_variable_any __ExitCond;//条件变量
 		boost::mutex __ExitMutex;//锁(配合__ExitCond)
 		_THREAD_CONFIG_ __Config;//线程配置
-		thread_safe_map<int, _CARD_POS_> __CardPosList;//卡位置列表
+		thread_safe_map<uint64_t, _CARD_POS_> __CardPosList;//卡位置列表
 		std::tm __LastSendTime;//上一次发送的时间
 		jsonBuilder __jsBuilder;//json构造器类
 	private:
@@ -204,4 +204,4 @@ namespace YA
 //单件定义
 typedef boost::serialization::singleton<YA::wsTimerThread> singleton_wsTimerThread;
 #define swsTimerThrd singleton_wsTimerThread::get_mutable_instance()
-#define swsTimerThrd_const singleton_wsTimerThread::get_const_instance()
+#define swsTimerThrd_const singleton_wsTimerThread::get_const_instance()

+ 7 - 1
write-copy.h

@@ -86,7 +86,7 @@ private:
 
 	void _remove(const std::vector<K>& v)
 	{
-		for(K&k:v)
+        for(K k:v)
 		{
 			m_map.erase(k);
 		}
@@ -136,6 +136,12 @@ struct single_base:write_copy_base<T,K,V>
 		std::lock_guard<std::mutex> lock(m_mutex);
 		m_instance=std::move(base::clone_remove(c));
 	}
+
+    void remove(const std::vector<K>&list)
+    {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        m_instance=std::move(base::clone_remove(list));
+    }
 };
 
 #endif

+ 108 - 0
ya_event.cpp

@@ -0,0 +1,108 @@
+#include "ya_event.h"
+
+
+uint64_t ya_event::get_list_id()
+{
+    return event_list::to_list_id(m_ev_type, m_obj_type,
+           tool_other::id64_to_type(m_obj_id), tool_other::id64_to_id(m_obj_id));
+}
+
+void event_list::load_his_data_from_db()
+{
+    const char *sql = "SELECT event_id, stat,event_type_id,obj_type_id,obj_id,map_id,area_id,\
+            limit_value,cur_value,x,y, cur_time FROM his_event_data \
+            WHERE event_id IN (SELECT MAX(event_id) FROM his_event_data \
+                               WHERE cur_time > (CASE obj_type_id \
+                                                 WHEN 1 THEN DATE_SUB(NOW(),INTERVAL 2 DAY) \
+                                                 WHEN 2 THEN DATE_SUB(NOW(),INTERVAL 2 DAY)\
+                                                 WHEN 4 THEN DATE_SUB(NOW(),INTERVAL 1 MONTH)\
+                                                 WHEN 9 THEN DATE_SUB(NOW(),INTERVAL 2 DAY) \
+                                                 WHEN 10 THEN DATE_SUB(NOW(),INTERVAL 2 DAY) \
+                                                 END) \
+                               AND cur_time < NOW()\
+                               GROUP BY event_type_id, obj_id) \
+            AND  event_id NOT IN ( SELECT event_id FROM (SELECT * FROM his_event_data WHERE  stat=100) s);";
+    std::string Error;
+    YADB::CDBResultSet DBRes;
+    sDBConnPool.Query(sql,DBRes,Error);
+    if(!Error.empty())
+        log_error("初始化事件列表 Error,%s",Error.c_str());
+    uint64_t nCount = DBRes.GetRecordCount( Error );
+    if (nCount > 0)
+    {
+        log_info( "init_vehicle_category. The record count=%ld\n", nCount );
+
+        while ( DBRes.GetNextRecod(Error) )
+        {
+            long long event_id  = 0;
+            DBRes.GetField( "event_id",event_id, Error );
+
+            int event_type_id  = 0;
+            DBRes.GetField( "event_type_id",event_type_id, Error );
+
+            int obj_type_id  = 0;
+            DBRes.GetField( "obj_type_id",obj_type_id, Error );
+
+            std::string obj_id  = "";
+            DBRes.GetField( "obj_id",obj_id, Error );
+
+            int map_id  = 0;
+            DBRes.GetField( "map_id",map_id, Error );
+
+            int area_id  = 0;
+            DBRes.GetField( "area_id",area_id, Error );
+
+            double limit_value = 0;
+            DBRes.GetField( "limit_value",limit_value, Error );
+
+            double cur_value = 0;
+            DBRes.GetField( "cur_value",cur_value, Error );
+
+            double x = 0;
+            DBRes.GetField( "x",x, Error );
+
+            double y = 0;
+            DBRes.GetField( "y",y, Error );
+
+            std::string cur_time  = "";
+            DBRes.GetField( "cur_time",cur_time, Error );
+
+            int stat  = 0;
+            DBRes.GetField( "stat",stat, Error );
+
+
+            std::shared_ptr<ya_event> ev = std::make_shared<ya_event>(event_id);
+            ev->m_status = static_cast<EVENT_STATUS>(stat);
+            ev->m_ev_type = static_cast<EVENT_TYPE>(event_type_id);
+
+            ev->m_obj_type = static_cast<OBJECT_TYPE>(obj_type_id);
+            ev->m_obj_id = tool_other::to13str(obj_id);
+            ev->m_cur_time = tool_time::to_time_ex(cur_time);
+
+            ev->m_cur_value = cur_value;
+            ev->m_limit_value = limit_value;
+
+            ev->m_map_id = map_id;
+            ev->m_area_id = area_id;
+            ev->x = x;
+            ev->y = y;
+
+            m_map.insert(std::make_pair(ev->get_list_id(), ev));
+        }
+
+        for(auto&iter: m_map)
+        {
+            auto ev = iter.second;
+            log_info("event list %lld,%d,%d,%d,%s,%d,%d,%f,%f,%f,%f,%s"
+                     , ev->get_id(),ev->m_status,ev->m_ev_type,ev->m_obj_type,ev->m_obj_id.c_str()
+                     ,ev->m_map_id,ev->m_area_id,ev->m_limit_value,ev->m_cur_value
+                     ,ev->x,ev->y
+                     ,tool_time::to_str_ex(ev->m_cur_time).c_str());
+        }
+    }
+}
+
+template<> std::shared_ptr<event_list>
+single_base<event_list, uint64_t, std::shared_ptr<ya_event>>::m_instance=std::make_shared<event_list>();
+
+

+ 292 - 0
ya_event.h

@@ -0,0 +1,292 @@
+#ifndef YA_EVENT_H
+#define YA_EVENT_H
+
+/**
+ * @brief 告警事件类型
+ * @author 戴月腾
+ * @date 2018-09-24
+ */
+
+#include<map>
+#include<chrono>
+#include<memory>
+#include"write-copy.h"
+#include"log.h"
+#include "db_api/CDBConnPool.h"
+#include"card.h"
+#include"common_tool.h"
+
+/**
+ * @brief 事件状态
+ */
+enum EVENT_STATUS
+{
+    ///事件开始
+    ES_START = 0,
+    ///呼救已处理状态
+    ES_DEAL_HELP = 1,
+    ///事件结束
+    ES_END = 100
+};
+
+enum EVENT_TYPE{ // 事件类型
+    ET_AREA_OVER_COUNT_PERSON = 3,	// 区域人员超员
+    ET_AREA_OVER_COUNT_VEHICLE = 4,	// 区域车辆超员
+
+    ET_CARD_LOW_POWER_SERIOUS = 12, // 电量极低
+
+    ET_CARD_AREA_OVER_TIME_PERSON = 15, // 人员区域超时
+    ET_CARD_AREA_OVER_TIME_VEHICLE = 16, // 车辆区域超时
+    ET_CARD_OVER_SPEED = 21, // 车辆超速
+    ET_CARD_HELP = 24, // 人员呼救
+
+    CARD_EVENT_COUNT_MAX,
+};
+
+/**
+ * @brief 对象类型
+ */
+enum OBJECT_TYPE
+{
+    ///矿井
+    OT_MINE = 1,
+    ///区域
+    OT_AREA = 2,
+    ///分站
+    OT_DEVICE_READER = 4,
+    ///标识卡,包括人员、车辆、自组网等
+    OT_CARD = 9,
+};
+
+/**
+ * @brief 告警事件
+ */
+struct ya_event
+{
+private:
+    uint64_t m_ev_id;
+public:
+    ya_event(uint64_t e_id):m_cur_time(std::chrono::system_clock::now())
+    {
+        m_ev_id = e_id;
+
+        m_obj_id = "";
+        m_map_id = 0;
+        m_area_id = 0;
+        x = 0;
+        y = 0;
+        m_limit_value = 0;
+        m_cur_value = 0;
+        m_desc = "";
+        m_landmarkid = 0;
+        m_landmarkdirect = 0;
+        m_landmarkdist = 0;
+
+        m_status=ES_START;
+        m_is_display=true;
+    }
+    ~ya_event(){}
+public:
+    ///告警状态,开始、结束
+    EVENT_STATUS m_status;
+
+    ///告警类型
+    EVENT_TYPE m_ev_type;
+    ///告警对象类型
+    OBJECT_TYPE m_obj_type;
+    /// 告警对象编号,与告警对象类型对应,如告警对象类型为分站,此字段为分站编号
+    std::string m_obj_id;
+    ///当前时间,为告警事件的触发时间,如果状态为开始,则表示开始时间,否则为结束时间
+    std::chrono::system_clock::time_point m_cur_time;
+
+    ///告警所在地图
+    int m_map_id;
+    ///告警所在区域
+    int m_area_id;
+    ///位置
+    double x;
+    ///位置
+    double y;
+    ///告警阈值
+    double m_limit_value;
+    ///当前值
+    double m_cur_value;
+    ///描述
+    std::string m_desc;
+
+    /// 地标信息
+    int m_landmarkid;
+    /// 与地标的距离
+    double m_landmarkdist;
+    /// 所处地标的方向
+    int m_landmarkdirect;
+
+    bool m_is_display;
+
+    bool is_end()
+    {
+        return ES_END == m_status;
+    }
+
+    ///作为事件map列表的id,方便查找;(obj_type<<32| obj_id)
+    uint64_t get_list_id();
+
+    uint64_t get_id(){return m_ev_id;}
+};
+typedef std::shared_ptr<ya_event> event_ptr;
+typedef std::map<uint64_t, std::shared_ptr<ya_event>> event_map;
+typedef std::shared_ptr<event_map> event_map_ptr;
+
+
+struct event_list:single_base<event_list,uint64_t,std::shared_ptr<ya_event>>
+{
+public:
+    ///作为事件map列表的id,方便查找;(ev_type<<48 | obj_type<<40 |  obj_id_type<<32 | obj_id)
+    static uint64_t to_list_id(EVENT_TYPE ev_type, OBJECT_TYPE obj_type, int obj_id_type, uint32_t obj_id)
+    {
+        return (static_cast<uint64_t>(ev_type)<<48)|(static_cast<uint64_t>(obj_type)<<40)
+                |(static_cast<uint64_t>(obj_id_type)<<32)|static_cast<uint64_t>(obj_id);
+    }
+
+    ///创建区域警告
+    static event_ptr create_event_area(int area_id, EVENT_TYPE ev_type)
+    {
+        return create_event(OT_AREA, area_id, 0, ev_type);
+    }
+
+    ///创建与卡有关的警告,需要卡类型
+    static event_ptr create_event_card(uint32_t card_id, int32_t card_type, EVENT_TYPE ev_type)
+    {
+        return create_event(OT_CARD, static_cast<int32_t>(card_id), card_type, ev_type);
+    }
+
+    static void copy_event(const std::shared_ptr<card_location_base> card_ptr, event_ptr ev_ptr)
+    {
+        ev_ptr->x = card_ptr->x;
+        ev_ptr->y = card_ptr->y;
+        ev_ptr->m_cur_time = std::chrono::system_clock::time_point(std::chrono::milliseconds(card_ptr->m_time));
+                //std::chrono::system_clock::now();
+        ev_ptr->m_is_display = card_ptr->m_display;
+
+        auto hover = card_ptr->get_area_hover();
+        if(nullptr!=hover)
+        {
+            ev_ptr->m_area_id =  hover->m_area->id();
+            ev_ptr->m_map_id = hover->m_area->mapid();
+
+            ev_ptr->m_landmarkid = hover->landmark_dir;
+            ev_ptr->m_landmarkdist = hover->landmark_dis;
+            ev_ptr->m_landmarkdirect = hover->landmark_dir;
+        }
+    }
+
+    std::shared_ptr<ya_event> get_event_card(uint32_t card_id, int card_type, EVENT_TYPE ev_type)
+    {
+        return base::get(to_list_id(ev_type, OT_CARD, card_type, card_id));
+    }
+
+    std::shared_ptr<ya_event> get_event_area(int32_t area_id, EVENT_TYPE ev_type)
+    {
+        return base::get(to_list_id(ev_type, OT_AREA, 0, static_cast<uint32_t>(area_id)));
+    }
+
+    void load_his_data_from_db();
+
+    static void save_event(const event_ptr ev_ptr)
+    {
+        char sql[LENGTH_SQL] = {'\0'};
+
+        std::string _time = tool_time::to_str_ex(ev_ptr->m_cur_time);
+
+        sprintf(sql,
+                "INSERT IGNORE INTO his_event_data(event_id, stat, event_type_id, obj_type_id, obj_id, \
+                map_id, area_id, limit_value, cur_value, x, y, cur_time, description, \
+                landmark_id, landmark_dist,direction_mapper_id )\
+                VALUES(%ld, %d, %d, %d, %s, %d, %d, %.2f, %.2f, %f, %f, '%s', '%s', %d, %10.3f, %d);",
+        ev_ptr->get_id(), ev_ptr->m_status, ev_ptr->m_ev_type, ev_ptr->m_obj_type, ev_ptr->m_obj_id.c_str(),
+                ev_ptr->m_map_id, ev_ptr->m_area_id, ev_ptr->m_limit_value, ev_ptr->m_cur_value, ev_ptr->x, ev_ptr->y,
+                _time.c_str(), ev_ptr->m_desc.c_str(),
+                ev_ptr->m_landmarkid, ev_ptr->m_landmarkdist, ev_ptr->m_landmarkdirect);
+
+        tool_db::PushAsync(sql);
+    }
+
+    ~event_list(){}
+
+    static std::string ev_to_json(std::shared_ptr<ya_event> ev_ptr)
+    {
+        std::vector<std::shared_ptr<ya_event>> evs;
+        evs.push_back(ev_ptr);
+        return evs_to_json(evs);
+    }
+
+    static std::string evs_to_json(std::vector<std::shared_ptr<ya_event>> arr)
+    {
+        rapidjson::Document doc(rapidjson::kObjectType);
+        rapidjson::Value data(rapidjson::kArrayType);
+        rapidjson::Document::AllocatorType& allocator=doc.GetAllocator();
+
+        auto it=arr.begin();
+        for(;it!=arr.end();++it)
+        {
+            if((*it)->m_is_display)
+            {
+                ev_to_node(*it, allocator, data);
+            }
+        }
+
+        doc.AddMember(JSON_ROOT_KEY_CMD,JSON_CMD_VALUE_EVENT, allocator);
+        doc.AddMember(JSON_ROOT_KEY_VERSION,INTERFACE_VERSION, allocator);
+        doc.AddMember(JSON_ROOT_KEY_DATA,data, allocator);
+
+        rapidjson::StringBuffer sb;
+        rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
+        doc.Accept(writer);
+
+        return sb.GetString();
+    }
+
+private:
+    static void ev_to_node(std::shared_ptr<ya_event> ev_ptr,
+                           rapidjson::Document::AllocatorType& allocator,
+                           rapidjson::Value& out_data)
+    {
+        rapidjson::Value ev(rapidjson::kObjectType);
+
+        ev.AddMember(JSON_KEY_EVENT_EVENT_ID,ev_ptr->get_id(), allocator);
+        ev.AddMember(JSON_KEY_EVENT_STATUS,ev_ptr->m_status, allocator);
+
+        ev.AddMember(JSON_KEY_EVENT_TYPE_ID,ev_ptr->m_ev_type, allocator);
+        ev.AddMember(JSON_KEY_EVENT_OBJ_TYPE_ID,ev_ptr->m_obj_type, allocator);
+
+        tool_json::add_member(ev, JSON_KEY_EVENT_OBJ_ID, ev_ptr->m_obj_id, allocator);
+        ev.AddMember(JSON_KEY_EVENT_MAP_ID,ev_ptr->m_map_id, allocator);
+        ev.AddMember(JSON_KEY_EVENT_AREA_ID,ev_ptr->m_area_id, allocator);
+        ev.AddMember(JSON_KEY_EVENT_X,ev_ptr->x, allocator);
+        ev.AddMember(JSON_KEY_EVENT_Y,ev_ptr->y, allocator);
+
+        ev.AddMember(JSON_KEY_EVENT_LIMIT_VALUE,ev_ptr->m_limit_value, allocator);
+        ev.AddMember(JSON_KEY_EVENT_CUR_VALUE,ev_ptr->m_cur_value, allocator);
+        ev.AddMember(JSON_KEY_EVENT_CUR_TIME,tool_time::to_ms(ev_ptr->m_cur_time), allocator);
+
+        ev.AddMember(JSON_KEY_EVENT_LANDMARK_ID,ev_ptr->m_landmarkid, allocator);
+        ev.AddMember(JSON_KEY_EVENT_LANDMARK_DIRECTION,ev_ptr->m_landmarkdirect, allocator);
+        ev.AddMember(JSON_KEY_EVENT_LANDMARK_DISTANCE,ev_ptr->m_landmarkdist, allocator);
+
+        out_data.PushBack(ev, allocator);
+    }
+
+private:
+    static event_ptr create_event(OBJECT_TYPE obj_type, int obj_id, int type, EVENT_TYPE ev_type)
+    {
+        auto ev_ptr = std::make_shared<ya_event>(tool_time::now_to_us());
+
+        ev_ptr->m_ev_type = ev_type;
+        ev_ptr->m_obj_type = obj_type;
+        ev_ptr->m_obj_id = card_list::to_id64_str(type, static_cast<uint32_t>(obj_id) );
+
+        return ev_ptr;
+    }
+};
+
+#endif // YA_EVENT_H