Browse Source

Merge branch 'master' of http://local.beijingyongan.com:3000/linux-dev/ya-serv

zzj 6 years ago
parent
commit
ba1fbc4eb9

+ 83 - 0
CMakeLists.txt

@@ -0,0 +1,83 @@
+cmake_minimum_required(VERSION 2.8)
+#在项目中显示所有源码
+file(GLOB files_ya-serv ./*.cpp ./*.h ./websocket/* ./db_api/* ./src/* ./src/internal/*
+    ./module_service/*)
+add_custom_target(files_ya-serv SOURCES ${files_ya-serv})
+MESSAGE(STATUS "module: ya-serv")
+
+#g++编译参数
+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pthread -m64 -std=c++11 -fPIC -fno-strict-aliasing")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}  -pthread -m64 -std=c++11 -fPIC -fno-strict-aliasing")
+#第三方库库文件目录
+link_directories( "/root/soft/boost_1_67_0/lib" "/usr/lib64/mysql"  "/root/projection/includelib/lib")
+#第三方库头文件目录
+include_directories("/home/user/libev-4.24" "." "/home/user/boost_1_67_0"
+    "/root/projection/includelib/rapidjson"
+    "/root/projection/includelib/websocketpp" "websocketpp/"
+    "/usr/include/mysql/"  "src/" "src/internal/"
+    "websocket/" "db_api/")
+
+#输出项目名称
+project(ya-serv)
+#编译项目所需源码
+set(SRC_YASL "ant.cpp" "ant.h" "base64.cpp" "base64.h" "card.cpp" "card.h" "clock.h"
+    "io_buf.h" "line.h" "log.h" "message.cpp" "message.h" "point.cpp"
+    "point.h" "tdoa_sync.cpp" "tdoa_sync.h" "web-client.cpp" "web-client.h" "worker.cpp" "worker.h" "zio.h"
+    "zloop.h" "znet.cpp" "znet.h" "zstream.h"
+
+    "net-service.h" "net-service.cpp"
+
+    "loc_tool.h" "loc_tool.cpp"
+
+    "db_api/CDBCommon.h" "db_api/CDBConnect.h" "db_api/CDBConnect.cpp"  "db_api/CjasonCommon.h"
+    "db_api/CDBConnPool.h" "db_api/CDBConnPool.cpp"
+    "db_api/CDBHelper.h" "db_api/CDBHelper.cpp"
+    "db_api/CDBResultSet.h" "db_api/CDBResultSet.cpp"
+
+
+    "src/sio_client.h" "src/sio_client.cpp" "src/sio_message.h"
+    "src/sio_socket.h" "src/sio_socket.cpp"
+
+    "src/internal/sio_client_impl.h" "src/internal/sio_client_impl.cpp"
+    "src/internal/sio_packet.h" "src/internal/sio_packet.cpp"
+
+    "websocket/constdef.h"
+    "websocket/jsonBuilder.h" "websocket/jsonBuilder.cpp"
+    "websocket/jsonCommon.h" "websocket/thread_safe_map.h"
+    "websocket/ws_common.h"
+    "websocket/wsClient.h" "websocket/wsClient.cpp"
+    "websocket/wsClientMgr.h" "websocket/wsClientMgr.cpp"
+    "websocket/wsTimerThread.h" "websocket/wsTimerThread.cpp"
+    )
+
+set(SRC_MODULE
+
+    "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_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"
+    )
+
+add_executable(${PROJECT_NAME} "main.cpp" ${SRC_YASL}  ${SRC_MODULE})
+
+#set(LIB_BOOST "")
+target_link_libraries (${PROJECT_NAME}  zlog rt ev boost_system boost_thread mysqlclient)
+
+
+
+
+
+
+
+
+
+
+
+

+ 245 - 0
CMakeLists.txt.user

@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<!-- Written by QtCreator 4.7.0, 2018-09-06T09:13:37. -->
+<qtcreator>
+ <data>
+  <variable>EnvironmentId</variable>
+  <value type="QByteArray">{149fbad2-c2c1-46e2-b53b-a02601bae2a5}</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.ActiveTarget</variable>
+  <value type="int">0</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.EditorSettings</variable>
+  <valuemap type="QVariantMap">
+   <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
+   <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
+   <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
+   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
+    <value type="QString" key="language">Cpp</value>
+    <valuemap type="QVariantMap" key="value">
+     <value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
+    </valuemap>
+   </valuemap>
+   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
+    <value type="QString" key="language">QmlJS</value>
+    <valuemap type="QVariantMap" key="value">
+     <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
+    </valuemap>
+   </valuemap>
+   <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
+   <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
+   <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
+   <value type="int" key="EditorConfiguration.IndentSize">4</value>
+   <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
+   <value type="int" key="EditorConfiguration.MarginColumn">80</value>
+   <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
+   <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
+   <value type="int" key="EditorConfiguration.PaddingMode">1</value>
+   <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
+   <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
+   <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
+   <value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
+   <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
+   <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
+   <value type="int" key="EditorConfiguration.TabSize">8</value>
+   <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
+   <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
+   <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
+   <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
+   <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
+   <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.PluginSettings</variable>
+  <valuemap type="QVariantMap">
+   <valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey"/>
+   <value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Target.0</variable>
+  <valuemap type="QVariantMap">
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">桌面</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">桌面</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{9a595fce-5778-4edd-9faa-19eb476f9ba8}</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
+    <valuelist type="QVariantList" key="CMake.Configuration">
+     <value type="QString">CMAKE_BUILD_TYPE:STRING=Debug</value>
+    </valuelist>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/root/projection/ya-serv/Debug</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">all</value>
+      </valuelist>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+    </valuemap>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">clean</value>
+      </valuelist>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
+   </valuemap>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
+    <valuelist type="QVariantList" key="CMake.Configuration">
+     <value type="QString">CMAKE_BUILD_TYPE:STRING=Release</value>
+    </valuelist>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/root/projection/ya-serv/Release</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">all</value>
+      </valuelist>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+    </valuemap>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">clean</value>
+      </valuelist>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">CMake Build</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy Configuration</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+    <value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
+    <value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
+    <value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
+    <value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
+    <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+    <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+    <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
+    <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+    <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
+    <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+    <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
+    <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+    <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+     <value type="int">0</value>
+     <value type="int">1</value>
+     <value type="int">2</value>
+     <value type="int">3</value>
+     <value type="int">4</value>
+     <value type="int">5</value>
+     <value type="int">6</value>
+     <value type="int">7</value>
+     <value type="int">8</value>
+     <value type="int">9</value>
+     <value type="int">10</value>
+     <value type="int">11</value>
+     <value type="int">12</value>
+     <value type="int">13</value>
+     <value type="int">14</value>
+    </valuelist>
+    <value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.Arguments"></value>
+    <value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory"></value>
+    <value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory.default">/root/projection/ya-serv/Debug</value>
+    <value type="int" key="PE.EnvironmentAspect.Base">2</value>
+    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">ya-serv</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.ya-serv
+/root/projection/ya-serv/</value>
+    <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
+    <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
+    <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+    <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.TargetCount</variable>
+  <value type="int">1</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+  <value type="int">18</value>
+ </data>
+ <data>
+  <variable>Version</variable>
+  <value type="int">18</value>
+ </data>
+</qtcreator>

+ 14 - 0
ant.h

@@ -101,6 +101,17 @@ struct ant :point
 
 };
 
+/**
+ * @brief 分站位置 1井上,2井下
+ */
+enum UP_DOWN_SITE
+{
+    ///井上分站
+    UP_SITE=1,
+    ///井下分站
+    DOWN_SITE=2
+};
+
 struct site:point
 {
 	static algo_config g_config[];
@@ -123,6 +134,9 @@ struct site:point
 	mutable double m_ant_dist_sum_new=0;
 	mutable int m_ant_dist_cnt_new=0;
 
+    ///分站位置 UP_DOWN_SITE
+    int m_up_down;
+
     point get_dstp(const point pt) const 
     {
         point tmp;

+ 60 - 21
area.h

@@ -10,30 +10,57 @@
 
 struct area_hover;
 struct point;
+
+/**
+ * @brief 区域类型
+ */
+enum AREA_TYPE
+{
+    ///非考勤区域
+    AT_NOT_ATTENDANCE,
+
+    ///与考勤,卡数统计,超员,超时无关的区域
+    AT_OTHER,
+};
+
 struct area
 {
 	area()
 	{
 	}
 
-    virtual void on_hover(int64_t card_id,std::shared_ptr<area_hover>&c,double speed)=0;
-    virtual void on_enter(int64_t card_id,std::shared_ptr<area_hover>&c,double speed)=0;
-    virtual void on_leave(int64_t card_id,std::shared_ptr<area_hover>&c,double speed)=0;
+    virtual void on_hover(uint64_t card_id,std::shared_ptr<area_hover>&c,double speed)=0;
+    virtual void on_enter(uint64_t card_id,std::shared_ptr<area_hover>&c,double speed)=0;
+    virtual void on_leave(uint64_t card_id,std::shared_ptr<area_hover>&c,double speed)=0;
 
 	int id()const
 	{
 		return m_id;
 	}
 
-	std::atomic<int> m_card_count;
-
 	int    m_id;
-	double m_limit_speed;
+    ///区域类型  AREA_TYPE
+    int m_area_type;
+
+    ///区域卡数
+    int card_count()
+    {
+        return m_person_count + m_vehicle_count;
+    }
+    ///区域人卡数
+    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;
 
 //	std::string m_name;
-//	int m_limit_time_second;
-//	int m_limit_person_count;
-//	int m_area_type;
 
 	std::vector<point> m_bound;
 };
@@ -51,18 +78,30 @@ struct area_list:single_base<area_list,int,std::shared_ptr<area>>
 struct area_hover
 {
 	std::shared_ptr<area>  m_area;
-	time_t m_enter_time,m_last_time;
+    //time_t m_enter_time,m_last_time;
 	point  m_enter_point,m_last_point;
-	int    m_num_speeding;
+    //int    m_num_speeding;
+
+    ///车卡区域超速
+    std::atomic<bool> m_is_area_over_speed_vehicle;
+    ///车卡区域超速次数计数器
+    int m_vehicle_area_over_speed_count;
+    ///车卡速度正常次数计数器
+    int m_vehicle_area_normal_speed_count;
+
+    ///人卡是否区域超时
+    std::atomic<bool> m_is_area_over_time_person;
+    ///进入区域的时间
+    std::chrono::system_clock::time_point m_enter_time;
 
 	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;
-		if(speed>m_area->m_limit_speed)
-			m_num_speeding++;
+//		m_enter_time=m_last_time=time(0);
+//		m_enter_point=m_last_point=pt;
+//		m_num_speeding=0;
+//		if(speed>m_area->m_limit_speed)
+//			m_num_speeding++;
 	}
 
 	int id()const
@@ -86,25 +125,25 @@ struct area_hover
 struct area_tool
 {
 	std::vector<std::shared_ptr<area_hover>> m_clist;
-	void on_point(int64_t card_id,const point&pt,double speed);
+    void on_point(uint64_t card_id,const point&pt,double speed);
 
 	//检测是否超时
-    void on_timer(int64_t card_id)
+    void on_timer(uint64_t card_id)
 	{
 	
 	}
 
-    void do_hover_biz(int64_t card_id,std::shared_ptr<area_hover>&a,double speed)
+    void do_hover_biz(uint64_t card_id,std::shared_ptr<area_hover>&a,double speed)
 	{
 		a->m_area->on_hover(card_id,a,speed);
 	}
 
-    void do_enter_biz(int64_t card_id,std::shared_ptr<area_hover>&a,double speed)
+    void do_enter_biz(uint64_t card_id,std::shared_ptr<area_hover>&a,double speed)
 	{
 		a->m_area->on_enter(card_id,a,speed);
 	}
 
-    void do_leave_biz(int64_t card_id,std::shared_ptr<area_hover>&a,double speed)
+    void do_leave_biz(uint64_t card_id,std::shared_ptr<area_hover>&a,double speed)
 	{
 		a->m_area->on_leave(card_id,a,speed);
 	}

+ 118 - 28
card.h

@@ -6,6 +6,9 @@
 #include "ant.h"
 
 #include "write-copy.h"
+#include "atomic"
+#include "area.h"
+//#include "module_service/module_call_help.h"
 
 struct task;
 template<typename T> struct zloop;
@@ -14,55 +17,142 @@ struct smooth_tool;
 enum STA_TYPE
 {
     STATUS_HELP=0,
-    STATUS_LOW_POWER, 
+    STATUS_LOW_POWER,
 };
+
+/**
+ * @brief 0初始状态 1 没在考勤 2 考勤
+ */
+enum ATTENDANCE_STATUS
+{
+    ///初始状态
+    AS_INIT=0,
+    ///没在考勤
+    AS_NOT_ATTENDANCE=1,
+    ///考勤
+    AS_ATTENDANCE=2,
+};
+
+/**
+ * @brief 卡类型 人卡  车卡
+ */
+enum CARD_TYPE
+{
+    ///卡类型 人卡
+    CT_PERSON=1,
+    ///卡类型 车卡
+    CT_VEHICLE=2,
+};
+
 struct card_message_handle;
 struct card:point
 {
-	card(uint32_t id,uint16_t dis,int16_t type)
-		:m_id(id)
-		,m_type(type)
-		,m_display(dis)
-		,m_speed(0)
-		,m_is_attendance(0)
-		,m_stat(0)
-	{}
-	uint32_t m_id;				//卡号
-	int16_t  m_type;			//类型
-	uint16_t m_display;			//1显示0不显示,往前端推送
-	double   m_speed;			//速度
-	int      m_is_attendance;	//井上井下状态  0初始状态 1 井上 2 井下
-	int		 m_stat;			//运动静止状态
+    card(uint32_t id,uint16_t dis,int16_t type)
+        :m_id(id)
+        ,m_type(type)
+        ,m_display(dis)
+        ,m_speed(0)
+        ,m_stat_attendance(0)
+        ,m_stat(0)
+    {}
+
+    ///卡号
+    uint32_t m_id;
+    ///类型  CARD_TYPE
+    int16_t  m_type;
+    ///1显示0不显示,往前端推送
+    uint16_t m_display;
+    ///速度
+    double   m_speed;
+    ///考勤状态  0初始状态 1 没在考勤 2 考勤;参看ATTENDANCE_STATUS
+    std::atomic<int> m_stat_attendance;
+    ///考勤开始时间
+    std::chrono::system_clock::time_point m_attendance_start_time;
+
+    ///运动静止状态
+    int		 m_stat;
+
+    ///
+    std::shared_ptr<area_hover> m_area_hover;
+
+    ///分站id
+    int m_site_id;
+    /// 天线号
+    int m_antenna_id;
+    /// 分站发送数据的计数次数
+    int m_reader_tickcount;
+
+    /// 飞行时间
+    int64_t flying_time;
+    /// 天线角度
+    double m_antenna_angle;
+    /// 距离
+    double m_distance;
+    /// 飞行时间
+    int64_t m_flying_time;
+
+    // 分站接收到卡时的时间
+    std::string m_str_his_time;
+    // 采集程序接收到数据的时间
+    std::string m_str_rec_time;
+    /// 定位时间戳
+    unsigned short m_time_stamp;
+    /// 报文类型 tof,tdoa
+    int m_ranging_type;
+    // 加速度
+    int m_accelerate_state;
+
+    /// 电量
+    int m_power_state;
+    /// 上一次加速度状态
+    int m_accelerate_state_last;
+
+    ///呼救状态:事件开始(0),呼救已处理状态(1),事件结束(100);参看EVENT_STATUS
+    std::atomic<int> m_stat_call_help;
+
+    ///最后处理时间
+    std::chrono::system_clock::time_point m_deal_time;
+
+    /// 地标信息
+    int m_landmarkid;
+    /// 与地标的距离
+    double m_landmarkdist;
+    /// 所处地标的方向
+    int m_landmarkdirect;
 };
 struct card_location_base:card
 {
     std::unique_ptr <select_tool> m_sel_tool;
     std::unique_ptr <smooth_tool> m_smo_tool;
-	std::unique_ptr <card_message_handle> m_message_handle;
+    std::unique_ptr <card_message_handle> m_message_handle;
     ev::dynamic_loop * m_loop = nullptr;
-	ev::timer m_timer;
+    ev::timer m_timer;
 
     card_location_base()=default;
     card_location_base(std::string type,uint32_t id,uint16_t dis,int16_t t);
-	void set(ev::dynamic_loop * loop);
-	void on_timer();
+    void set(ev::dynamic_loop * loop);
+    void on_timer();
 
-	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 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
+        }
     }
-	virtual ~card_location_base();
+    virtual ~card_location_base();
 };
 
 struct card_list:single_base<card_list,uint64_t,std::shared_ptr<card_location_base>>
 {
-	void init_staffer();
-	void init_vehicle();
-	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();
-	~card_list(){}
+    void init_staffer();
+    void init_vehicle();
+    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();
+    ~card_list(){}
 };
 
 #endif

+ 4 - 0
main.cpp

@@ -10,6 +10,7 @@
 #include "card_path.h"
 
 #include <config_file.h>
+#include"module_service/module_mgr.h"
 
 config_file config;
 struct Init_Setting
@@ -97,6 +98,9 @@ int main()
 	
 	atexit(&cleanup);
 
+    module_mgr::instance()->init();
+    module_mgr::instance()->start();
+
 	card_path::init();
 	net_service mh;
 

+ 122 - 0
module_service/module_area.cpp

@@ -0,0 +1,122 @@
+#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);
+    }
+}
+
+
+

+ 87 - 0
module_service/module_area.h

@@ -0,0 +1,87 @@
+#ifndef MODULE_AREA_H
+#define MODULE_AREA_H
+
+/**
+ * @brief 与区域相关的业务模块总接口
+ * @author 戴月腾
+ * @date 2018-08-25
+ */
+
+#include"area.h"
+#include"module_const.h"
+#include"module_web.h"
+
+class module_area:public i_thread, public singleton_base<module_area>
+{
+private:
+    friend class singleton_base<module_area>;
+    module_area()
+    {
+    }
+
+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()
+    {
+        std::vector<std::shared_ptr<ya_event>> arr;
+        get_all_events(arr);
+
+        if(!arr.empty())//发送给web端
+        {
+            return tool_json::evs_to_json(arr);
+        }
+
+        return "";
+    }
+private:
+    /**
+     * @brief 线程函数
+     */
+    void run()
+    {
+        std::vector<std::shared_ptr<ya_event>> arr;
+        get_all_events(arr);
+
+        if(!arr.empty())//发送给web端
+        {
+            swsClientMgr.send(JSON_CMD_VALUE_PUSH, tool_json::evs_to_json(arr));
+        }
+    }
+
+    /**
+     * @brief 获取所有的告警事件
+     * @param out_data
+     */
+    void get_all_events(std::vector<std::shared_ptr<ya_event>>& arr)
+    {
+        {
+            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--);
+                }
+            }
+        }
+    }
+
+    std::map<uint64_t, std::shared_ptr<ya_event>> _map;
+};
+
+#endif // MODULE_AREA_H

+ 3 - 0
module_service/module_area_over_speed.cpp

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

+ 127 - 0
module_service/module_area_over_speed.h

@@ -0,0 +1,127 @@
+#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

+ 3 - 0
module_service/module_area_overman.cpp

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

+ 92 - 0
module_service/module_area_overman.h

@@ -0,0 +1,92 @@
+#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

+ 3 - 0
module_service/module_area_timeout.cpp

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

+ 97 - 0
module_service/module_area_timeout.h

@@ -0,0 +1,97 @@
+#ifndef MODULE_AREA_TIMEOUT_H
+#define MODULE_AREA_TIMEOUT_H
+
+/**
+  *@brief 区域超时模块 2018-08-26 戴月腾修改
+  * 当某张人卡在某个区域的时间超过指定值时,会发出区域超时告警
+  * @author 陈欧美
+  * @date 2018-08-05
+*/
+
+#include <mutex>
+#include <map>
+#include <chrono>
+#include <boost/thread.hpp>
+#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:
+    friend class singleton_base<module_area_timeout>;
+    module_area_timeout()
+    {
+    }
+
+public:
+    void on_enter(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed)
+    {
+        c->m_is_area_over_time_person=false;
+    }
+
+    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)//发生告警
+        {
+            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);
+            }
+        }
+        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);
+                }
+            }
+        }
+    }
+
+    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_timeout> module_area_timeout_ptr;
+
+#endif // MODULE_AREA_TIMEOUT_H

+ 9 - 0
module_service/module_attendance_person.cpp

@@ -0,0 +1,9 @@
+#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>
+
+

+ 138 - 0
module_service/module_attendance_person.h

@@ -0,0 +1,138 @@
+#ifndef MODULE_ATTENDANCE_PERSON_H
+#define MODULE_ATTENDANCE_PERSON_H
+
+/**
+  *@brief 人员考勤模块 2018-08-26 戴月腾修改
+  *主要是针对人卡进行考勤,人卡从井上切换到井下为考勤开始,人卡从井下切换到井上为考勤结束
+  *@author 陈欧美
+  *@date 2018-08-03
+*/
+
+#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"
+
+/**
+ * @brief 主要是针对人卡进行考勤,人卡从井上切换到井下为考勤开始,人卡从井下切换到井上为考勤结束
+ */
+class module_attendance_person:public singleton_base<module_attendance_person>
+{
+private:
+    friend class singleton_base<module_attendance_person>;
+    module_attendance_person()
+    {
+    }
+
+public:
+    /**
+     * @brief 进入分站覆盖区域处理,考勤
+     * @param card_id
+     * @param enter_site
+     */
+    void enter_site(uint64_t card_id,int enter_site)
+    {
+        auto card_ptr=card_list::instance()->get(card_id);
+        if(!card_ptr)
+        {
+            log_error("卡不存在card_id=%d", card_id);
+            return;
+        }
+
+        auto site_ptr=sit_list::instance()->get(enter_site);
+        if(!site_ptr)
+        {
+            log_error("在分站列表中找不到分站,分站id=%d", enter_site);
+            return;
+        }
+
+        card_ptr->m_site_id = enter_site;
+
+        // 从井下切换到井上为考勤结束
+        if(UP_SITE==site_ptr->m_up_down)
+        {
+            if(AS_ATTENDANCE == card_ptr->m_stat_attendance)
+            {
+                //考勤结束
+                card_ptr->m_stat_attendance=AS_NOT_ATTENDANCE;
+
+                //作为一条结束考勤记录保存到数据库
+                tool_db::save_attendance(card_ptr);
+            }
+        }
+
+        // 从井上切换到井下为考勤开始
+        if(DOWN_SITE==site_ptr->m_up_down)
+        {
+            if(AS_ATTENDANCE != card_ptr->m_stat_attendance)
+            {
+                //考勤开始
+                card_ptr->m_stat_attendance=AS_ATTENDANCE;
+                card_ptr->m_attendance_start_time=std::chrono::system_clock::now();
+
+                //作为一条开始考勤记录保存到数据库
+                tool_db::save_attendance(card_ptr);
+            }
+        }
+    }
+
+    /**
+     * @brief 离开现有分站处理,记录现有分站的进出时间和地点
+     * @param card_id
+     * @param enter_site
+     */
+    void leave_site(uint64_t card_id,int enter_site)
+    {
+
+    }
+    /**
+     * @brief 手工升井函数
+     */
+    void up_well(std::vector<std::string>& card_ids)
+    {
+        //    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);
+
+        //        // 插入考勤记录到数据库
+        //    }
+    }
+
+};
+
+#endif // MODULE_ATTENDANCE_PERSON_H

+ 2 - 0
module_service/module_attendance_vehicle.cpp

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

+ 73 - 0
module_service/module_attendance_vehicle.h

@@ -0,0 +1,73 @@
+#ifndef MODULE_ATTENDANCE_VEHICLE_H
+#define MODULE_ATTENDANCE_VEHICLE_H
+
+/**
+  *@brief 车辆考勤模块
+  *车辆进入某些特定区域,结束考勤;从特定区域进入其他区域,开始考勤
+  *@author 戴月腾
+  *@date 2018-08-07
+*/
+
+#include <memory>
+#include <mutex>
+#include <map>
+#include <string>
+#include <chrono>
+#include <vector>
+#include <set>
+#include "module_const.h"
+
+/**
+ * @brief 车辆进入某些特定区域,结束考勤;从特定区域进入其他区域,开始考勤, 单例
+ */
+class module_attendance_vehicle:public singleton_base<module_attendance_vehicle>
+{
+private:
+    friend class singleton_base<module_attendance_vehicle>;
+    module_attendance_vehicle()
+    {
+    }
+
+public:
+    void on_enter(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed)
+    {
+        card_ptr->m_attendance_start_time=std::chrono::system_clock::now();
+    }
+
+    void on_hover(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed,
+                  event_map& ev_map)
+    {
+        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);
+            }
+        }
+    }
+
+
+    void on_leave(std::shared_ptr<card_location_base> card_ptr,std::shared_ptr<area_hover>&c,double speed)
+    {
+
+    }
+};
+typedef std::shared_ptr<module_attendance_vehicle>  module_attendance_vehicle_ptr;
+
+#endif // MODULE_ATTENDANCE_VEHICLE_H

+ 505 - 0
module_service/module_call.cpp

@@ -0,0 +1,505 @@
+#include "module_call.h"
+
+#include <boost/bind.hpp>
+#include <vector>
+#include <set>
+#include <string>
+#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()
+{
+    std::vector<call_card_ptr> arr;
+
+    get_all_call_cards(arr);
+
+    if(arr.empty())
+    {
+        return ;
+    }
+    //转发给web
+    swsClientMgr.send(JSON_CMD_VALUE_PUSH, to_call_card_list_json(arr));
+
+    //将呼叫命令发送给标识卡终端
+}
+
+/*
+web发给采集:发起呼叫
+{
+    cmd: 'call_card_req',
+    data: {
+      call_type_id: this.cal_type, // 全员呼叫:0 定员呼叫:1
+      call_time_out: this.choosedTime, // 呼叫时长
+      call_level_id: this.call_type_id, // 呼叫类型 一般呼叫:1 紧急呼叫:2
+      user_name: xdata.userName, // 呼叫人
+      call_time: time, // 呼叫时间戳
+      stations: [{ stationid: 0 }], // 分站 0为全员
+      cards: cards // 人员 0为全员   //旧代码为map格式 [{ stationid: 0 }]
+    }
+}
+*/
+void module_call::accept_call(const rapidjson::Document& node_data)
+{
+    int call_type = -1, call_level = -1, call_time_out;
+    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)
+            )
+    {
+        log_error("收到的json不对,解析不出int call_type = -1, call_level = -1, call_time_out,user_name");
+        return;
+    }
+
+    if(user_name.empty())
+    {
+        log_error("user_name用户名为空");
+        return;
+    }
+
+    std::vector<call_card_ptr> arr;//结果集
+
+    call_user_ptr user_ptr;
+    if(CCT_CALL_ALL==call_type)// 全员
+    {
+        user_ptr=call_user_ptr(new call_user());
+
+        user_ptr->call_time=std::chrono::system_clock::now();
+        user_ptr->call_time_out=call_time_out;
+        user_ptr->call_type_id=call_type;
+        user_ptr->call_level_id=call_level;
+        user_ptr->user_name=user_name;
+
+        call_card_ptr temp(new call_card());
+        copy(user_ptr, temp);
+        temp->cardid = CCT_CALL_ALL; //全员卡
+
+        arr.push_back(temp);//增加到结果集中
+
+        //添加全员卡
+        user_ptr->cards.insert(std::make_pair(CCT_CALL_ALL, temp));
+
+        //更新用户信息
+        std::lock_guard<std::mutex> lock(_mutex);
+        _map[user_name]=user_ptr;
+    }
+    else// 定员: 如果有全员,定员不生效
+    {
+        std::lock_guard<std::mutex> lock(_mutex);
+
+        auto user_map_ptr = _map.find(user_name);
+        if(user_map_ptr==_map.end())//没有这个用户就新建并加入
+        {
+            user_ptr=call_user_ptr(new call_user());
+            _map[user_name]=user_ptr;
+        }
+        else//有这个用户
+        {
+            user_ptr=user_map_ptr->second;
+            // 如果有全员,定员不生效
+            if(user_ptr->cards.size()==1 && CCT_CALL_ALL == user_ptr->cards[CCT_CALL_ALL]->cardid)
+            {
+                return;
+            }
+        }
+
+        //更新用户信息
+        user_ptr->call_time=std::chrono::system_clock::now();
+        user_ptr->call_time_out=call_time_out;
+        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())
+        {
+            return;
+        }
+
+        add_cards_to_user(call_level, node_cards, user_ptr);
+
+        for(auto& it:user_ptr->cards)//添加到结果集中
+        {
+            arr.push_back(it.second);
+        }
+    }
+
+    //组装json发送给web
+    if(!arr.empty())
+    {
+        response_accept_call(arr);
+    }
+}
+
+//采集回复web发起呼叫
+//{
+//	'cmd': 'call_card_resp',
+//	'data': [
+//		["fjb", // 发起呼叫人
+//		"0010000000001", // 呼叫的卡号
+//		103, // 分站号
+//		23431, // 发起呼叫时间
+//		0, //
+//		0 // 正在呼叫:2/结束呼叫/
+//		]
+//	]
+//}
+void module_call::response_accept_call(std::vector<call_card_ptr> cards)
+{
+    rapidjson::Document doc(rapidjson::kObjectType);
+    auto& allocator = doc.GetAllocator();
+    rapidjson::Value node_cards(rapidjson::kArrayType);
+
+    //组装json发送给web
+    to_node_array(node_cards, cards, allocator);
+
+    doc.AddMember(JSON_ROOT_KEY_CMD,JSON_CMD_VALUE_CALL_CARD_RESPONSE, allocator);
+    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));
+}
+
+
+//web发给采集:取消呼叫
+//{
+//	cmd: 'call_card_cancel_req',
+//	data: {
+//	  call_type_id: type, // 全员/定员
+//	  user_name: xdata.userName, // 取消人
+//	  call_time: callTime, // 时间戳
+//	  stations: this.stationid, // 分站
+//	  cards: this.cards // 取消呼叫卡  //旧代码为map格式 [{ stationid: 0 }]
+//	}
+//}
+void module_call::accept_cancel(const rapidjson::Document& node_data)
+{
+    int call_type = -1, call_level = -1;
+    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(user_name, JSON_KEY_CALL_CARD_USER_NAME, node_data)
+            )
+    {
+        log_error("收到的json不对,解析不出int call_type = -1, call_level = -1,user_name");
+        return;
+    }
+
+    if(user_name.empty())
+    {
+        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->user_name=user_name;
+
+    //取消呼叫有两种:
+    //取消全员呼叫
+    //对指定卡取消呼叫
+    if(CCT_CALL_ALL==call_type)// 取消全员呼叫
+    {
+        //删除用户
+        std::lock_guard<std::mutex> lock(_mutex);
+        _map.erase(user_name);
+    }
+    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())
+        {
+            return;
+        }
+
+        std::lock_guard<std::mutex> lock(_mutex);
+
+        call_user_ptr user_ptr(new call_user());
+        auto it_map = _map.find(user_name);
+        if(_map.end()!=it_map)//呼叫用户
+        {
+            user_ptr=it_map->second;
+        }
+
+        uint64_t id_card;
+        for(rapidjson::SizeType i = 0; i < node_cards.Size(); ++i)
+        {
+            if(!tool_json::try_get_value( id_card, JSON_KEY_CALL_CARD_CARD_ID, node_cards[i])
+                    || 0==id_card
+                    )
+            {
+                continue;
+            }
+
+            call_card_ptr card_ptr(new call_card());
+            card_ptr->cardid = id_card;
+
+            result_user_ptr->cards[id_card]=card_ptr;//增加到结果集中
+
+            user_ptr->cards.erase(id_card);//删除这个卡
+        }
+
+        // 没有呼叫信息,删除该用户记录
+        if(user_ptr->cards.empty())
+        {
+            _map.erase(user_name);
+        }
+    }
+
+    //如果要取消呼叫的用户下没有卡,建一张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_time_out=0;
+        result_user_ptr->call_type_id=call_type;
+        result_user_ptr->user_name=user_name;
+
+        call_card_ptr card_ptr(new call_card());
+        card_ptr->cardid=CCT_CALL_ALL;
+
+        result_user_ptr->cards[card_ptr->cardid]=card_ptr;
+    }
+
+    //转发给web
+    response_accept_cancel(result_user_ptr);
+}
+
+/*
+采集回复web:取消呼叫
+{
+    "user_name":"fjb", // 取消人
+    "call_time": 23432, // 发起呼叫时间
+    "stations":[{"stationid":102}], // 分站号
+    "cards":[{"cardid":"0","cardtype":"1"}] // 取消的卡
+}
+*/
+void module_call::response_accept_cancel(const call_user_ptr user_ptr)
+{
+    rapidjson::Document doc(rapidjson::kObjectType);
+    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);
+    node_data.AddMember(JSON_KEY_CALL_CARD_CALL_TIME, tool_time::to_ms(user_ptr->call_time), allocator);
+
+    rapidjson::Value node_cards(rapidjson::kArrayType);
+
+    //加入取消呼叫的卡
+    auto iter = user_ptr->cards.begin();
+    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);
+
+        node_cards.PushBack(node_card,allocator);
+    }
+
+    node_data.AddMember(JSON_KEY_CALL_CARD_CARDS, node_cards, allocator);
+
+    doc.AddMember(JSON_ROOT_KEY_CMD, JSON_CMD_VALUE_CALL_CARD_CANCEL_RESPONSE, allocator);
+    doc.AddMember(JSON_ROOT_KEY_VERSION, INTERFACE_VERSION, allocator);
+    doc.AddMember(JSON_ROOT_KEY_DATA, node_data, allocator);
+
+    //转发给web
+    swsClientMgr.send(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":[
+    ["fjb", // 发起呼叫人
+    "0010000000001", // 呼叫的卡号
+    103, // 分站号
+    23431, // 发起呼叫时间
+    0, //
+    0 // 正在呼叫:2/结束呼叫/
+    ]
+]}
+*/
+std::string module_call::accept_login()
+{
+    std::vector<call_card_ptr> arr;
+
+    get_all_call_cards(arr);
+
+    if(arr.empty())
+    {
+        return "";
+    }
+
+    return to_call_card_list_json(arr);
+}
+
+std::string module_call::to_call_card_list_json(std::vector<call_card_ptr> arr)
+{
+    rapidjson::Document doc(rapidjson::kObjectType);
+    auto& allocator = doc.GetAllocator();
+    rapidjson::Value node_cards(rapidjson::kArrayType);
+
+    to_node_array(node_cards, arr, allocator);
+
+    doc.AddMember(JSON_ROOT_KEY_CMD, JSON_CMD_VALUE_CALL_CARD_LIST, allocator);
+    doc.AddMember(JSON_ROOT_KEY_VERSION, INTERFACE_VERSION, allocator);
+    doc.AddMember(JSON_ROOT_KEY_DATA, node_cards, allocator);
+
+    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)
+{
+    uint64_t id_card;
+    for(rapidjson::SizeType i = 0; i < node_cards.Size(); ++i)
+    {
+        if(!tool_json::try_get_value( id_card, JSON_KEY_CALL_CARD_CARD_ID, node_cards[i])
+                || 0==id_card
+                )
+        {
+            continue;
+        }
+
+        call_card_ptr card_ptr(new call_card());
+        card_ptr->cardid = id_card;
+        copy(user_ptr, card_ptr);
+
+        card_ptr->call_state = CALL_ING;
+
+        user_ptr->cards[card_ptr->cardid]=card_ptr;
+    }
+}
+
+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)
+{
+    auto& cards=user_ptr->cards;
+    int status = CALL_ING;
+    //如果是全员呼叫,增加所有卡
+    if(cards.size()==1 && CCT_CALL_ALL == cards[0]->cardid)
+    {
+        uint32_t seconds = tool_time::elapse_seconds(user_ptr->call_time);
+        if(seconds > user_ptr->call_time_out*60)//呼叫超时, 清空全员卡, 并设置呼叫状态为结束
+        {
+            cards.clear();
+            status=CALL_END;
+        }
+
+        auto g_it=cardlist.begin();
+        for(;g_it!=cardlist.end();++g_it)//如果是全员呼叫,增加所有卡
+        {
+            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->call_state=status;
+
+            out_data.push_back(card_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);
+        if(cardlist.end()==g_card)//在全局卡列表中没有这张卡,
+        {
+            iter_card->second->call_state = CALL_FAILED;
+
+            cards.erase(iter_card--); //在用户下删除这张卡
+            continue;
+        }
+
+        //更新卡的分站id
+        iter_card->second->stationid = g_card->second->m_site_id;
+
+        uint32_t seconds = tool_time::elapse_seconds(iter_card->second->call_time);
+        if(seconds > iter_card->second->call_time_out*60)//呼叫超时
+        {
+            iter_card->second->call_state = CALL_END;
+
+            cards.erase(iter_card--);//在用户下删除这张卡
+        }
+    }
+}
+
+

+ 278 - 0
module_service/module_call.h

@@ -0,0 +1,278 @@
+#ifndef MODULE_CALL_H
+#define MODULE_CALL_H
+
+/**
+ * @brief 呼叫模块
+ * 用户通过WEB呼叫指定人员或者全部人员
+ * @author 戴月腾
+ * @date 2018-08-22
+ */
+
+#include <map>
+#include <mutex>
+#include <string>
+#include <chrono>
+#include <boost/thread.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <atomic>
+#include "rapidjson/prettywriter.h"
+#include"module_const.h"
+#include"module_web.h"
+
+/**
+ * @brief 呼叫模块
+ */
+class module_call : public i_thread, public singleton_base<module_call>
+{
+private:
+    friend class singleton_base<module_call>;
+    module_call()
+    {
+    }
+
+private:
+    /**
+     * @brief 呼叫卡的信息
+     */
+    struct call_card
+    {
+        /// 呼叫卡号 0为全员
+        uint32_t cardid;
+        /// 分站号  0为全员
+        int stationid;
+        /// 呼叫类型:一般1,紧急2  CALL_CARD_LEVEL
+        int call_level_id;
+        /// 呼叫时长,单位分钟
+        int call_time_out;
+        /// 呼叫开始时间
+        std::chrono::system_clock::time_point call_time;
+        /// 呼叫状态,正在呼叫、呼叫成功
+        int call_state;
+        ///呼叫人
+        std::string user_name;
+    };
+    typedef std::shared_ptr<call_card>  call_card_ptr;
+    typedef std::map<uint64_t,call_card_ptr>  call_card_map;
+
+    /**
+     * @brief 呼叫用户信息
+     */
+    struct call_user
+    {
+        ///呼叫人
+        std::string user_name;
+        ///呼叫类型 全员0, 定员1   CALL_CARD_TYPE
+        int call_type_id;
+        /// 呼叫等级:一般1,紧急2  CALL_CARD_LEVEL
+        int call_level_id;
+        /// 呼叫时长,单位分钟
+        int call_time_out;
+        /// 呼叫开始时间
+        std::chrono::system_clock::time_point call_time;
+        ///呼叫卡列表
+        call_card_map cards;
+    };
+    typedef std::shared_ptr<call_user>  call_user_ptr;
+    typedef std::map<std::string, call_user_ptr> call_user_map;
+
+public:
+
+    /**
+     * @brief web发给采集:发起呼叫
+     * @param node_data
+     */
+    void accept_call(const rapidjson::Document& node_data);
+
+    /**
+     * @brief web发给采集:取消呼叫
+     * @param node_data
+     */
+    void accept_cancel(const rapidjson::Document& node_data);
+
+    /**
+     * @brief 登陆时,采集发送web:请求井下所有呼叫
+     */
+    std::string accept_login();
+
+private:
+    /**
+     * @brief 采集回复web发起呼叫
+     * @param arr
+     */
+    void response_accept_call(const std::vector<call_card_ptr> arr);
+
+    /**
+     * @brief 采集回复web:取消呼叫
+     * @param node_data
+     */
+    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);
+
+    /**
+     * @brief 线程函数
+     */
+    void run();
+
+    void copy(const call_user_ptr src, call_user_ptr des)
+    {
+        des->call_level_id = src->call_level_id;
+        des->call_time = src->call_time;
+        des->call_time_out = src->call_time_out;
+        des->call_type_id = src->call_type_id;
+        des->user_name = src->user_name;
+    }
+
+    void copy(const call_card_ptr src, call_card_ptr des)
+    {
+        des->call_level_id = src->call_level_id;
+        des->call_state = src->call_state;
+        des->call_time = src->call_time;
+        des->call_time_out = src->call_time_out;
+        des->cardid = src->cardid;
+        des->user_name = src->user_name;
+        des->stationid = src->stationid;
+    }
+
+    void copy(const call_user_ptr src, call_card_ptr des)
+    {
+        des->call_level_id = src->call_level_id;
+        //des->call_state = src->call_state;
+        des->call_time = src->call_time;
+        des->call_time_out = src->call_time_out;
+        //des->cardid = src->cardid;
+        des->user_name = src->user_name;
+    }
+
+    /**
+     * @brief 获取用户下的所有呼叫卡
+     * @param user_ptr
+     * @param cardlist
+     * @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);
+
+    /**
+     * @brief 获取所有的呼叫卡
+     * @param user_map
+     * @param cardlist
+     * @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)
+    {
+        auto iter_m_map=user_map.begin();
+        for(;iter_m_map!=user_map.end();++iter_m_map)
+        {
+            get_user_all_call_cards(iter_m_map->second, cardlist, out_data);
+
+            if(iter_m_map->second->cards.empty())//没有卡了 删除呼叫用户
+            {
+                user_map.erase(iter_m_map--);
+            }
+        }
+    }
+
+    /**
+     * @brief 获取所有的呼叫卡
+     * @param out_data
+     */
+    void get_all_call_cards(std::vector<call_card_ptr>& out_data)
+    {
+        auto cardlist = card_list::instance()->m_map;
+
+        {
+            std::lock_guard<std::mutex> lock(_mutex);
+
+            get_all_call_cards(_map, cardlist, out_data);
+        }
+    }
+
+    /*
+     * @brief
+     * ["fjb", // 发起呼叫人
+     * "0010000000001", // 呼叫的卡号
+     * 103, // 分站号
+     * 23431, // 发起呼叫时间
+     * 0, //
+     * 0 // 正在呼叫:2/结束呼叫/
+     * ]
+    */
+    static void to_node_element(rapidjson::Value& out_elemet,
+                                           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);
+
+        out_elemet.PushBack(card_ptr->stationid, allocator);
+        out_elemet.PushBack(tool_time::to_ms(card_ptr->call_time), allocator);
+
+        out_elemet.PushBack(0, 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)
+    {
+        std::vector<std::shared_ptr<call_card>>::size_type i;
+
+        for(i=0; i<cards.size(); i++)
+        {
+            rapidjson::Value node_card(rapidjson::kArrayType);
+
+            to_node_element(node_card, cards[i], allocator);
+
+            out_array.PushBack(node_card, allocator);
+        }
+    }
+
+    /**
+     * @brief  生成所有呼叫卡的json
+     * @param cards
+     * @return
+     */
+    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;
+//    }
+
+private:
+    /// 呼叫用户列表
+    call_user_map _map;
+};
+
+
+#endif // MODULE_CALL_H

+ 8 - 0
module_service/module_call_help.cpp

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

+ 149 - 0
module_service/module_call_help.h

@@ -0,0 +1,149 @@
+#ifndef MODULE_CALL_HELP_H
+#define MODULE_CALL_HELP_H
+
+/**
+  *@brief 呼救模块
+  * 把呼救消息保存到数据库,同时推送给web
+  * @author 戴月腾
+  * @date 2018-08-09
+*/
+
+#include <mutex>
+#include <map>
+#include <chrono>
+#include <boost/thread.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include "module_web.h"
+#include "module_const.h"
+
+/**
+ * @brief 呼救类
+ * 把呼救消息保存到数据库,同时推送给web, 单例
+ */
+class module_call_help : public i_thread, public singleton_base<module_call_help>
+{
+private:
+    friend class singleton_base<module_call_help>;
+    module_call_help()
+    {
+    }
+
+public:
+    /**
+     * @brief 接收到呼救请求
+     */
+    void rev_help(std::shared_ptr<card> 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);
+
+//            ev_ptr->status = ES_START;
+//            ev_ptr->cur_time = std::chrono::system_clock::now();
+
+            //保存到数据库
+            tool_db::save_event(ev_ptr);
+            //转发给web
+            swsClientMgr.send(JSON_CMD_VALUE_PUSH, tool_json::ev_to_json(ev_ptr));
+
+            std::lock_guard<std::mutex> lock(_mutex);
+            tool_other::insert_event(ev_ptr, _map);
+        }
+    }
+
+    /**
+     * @brief 接收到web端发来的处理呼救请求
+     * @param data_map
+     */
+    void accept_deal_help(std::map<std::string, sio::message::ptr> data_map)
+    {
+        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);
+//        }
+    }
+
+    /**
+     * @brief web前端有用户登录时,反馈给web所有信息
+     */
+    std::string response_login()
+    {
+        std::vector<std::shared_ptr<ya_event>> arr;
+        get_all_events(arr);
+
+        if(!arr.empty())//发送给web端
+        {
+            return tool_json::evs_to_json(arr);
+        }
+
+        return "";
+    }
+
+    /**
+     * @brief 读取数据库中的告警,初始化告警列表
+     */
+    void init()
+    {}
+
+private:
+    /**
+     * @brief 线程函数
+     */
+    void run()
+    {
+        std::vector<std::shared_ptr<ya_event>> arr;
+        get_all_events(arr);
+
+        if(!arr.empty())//发送给web端
+        {
+            swsClientMgr.send(JSON_CMD_VALUE_PUSH, tool_json::evs_to_json(arr));
+        }
+    }
+
+    /**
+     * @brief 获取所有的告警事件
+     * @param out_data
+     */
+    void get_all_events(std::vector<std::shared_ptr<ya_event>>& arr)
+    {
+        {
+            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--);
+                }
+            }
+        }
+    }
+
+    std::map<uint64_t, std::shared_ptr<ya_event>> _map;
+};
+
+
+#endif

+ 9 - 0
module_service/module_const.cpp

@@ -0,0 +1,9 @@
+#include "module_const.h"
+
+
+template<typename T>
+T *singleton_base<T>::_instance = nullptr;
+
+template<typename T>
+std::mutex singleton_base<T>::_mutex_singleton_base;
+

+ 629 - 0
module_service/module_const.h

@@ -0,0 +1,629 @@
+#ifndef MODULE_CONST_H
+#define MODULE_CONST_H
+
+/**
+ * @brief 包含常用的常量,接口基类,工具类
+ * @author 戴月腾
+ * @date 2018-08-24
+ */
+
+#include<map>
+#include<vector>
+#include<string>
+#include<chrono>
+#include"db_api/CDBConnPool.h"
+#include"log.h"
+#include<rapidjson/document.h>
+#include<rapidjson/prettywriter.h>
+#include<rapidjson/stringbuffer.h>
+#include<websocket/wsClientMgr.h>
+#include<thread>
+
+#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 uint64_t to_uint64_cardid(uint32_t type, uint32_t id)
+    {
+        return (static_cast<uint64_t>(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)
+    {
+        char sql[LENGTH_SQL] = {0};
+
+        std::string call("add_att_staff");
+        if(CT_VEHICLE==card_ptr->m_type)//车卡
+        {
+            call="add_att_vehicle";
+        }
+
+        auto tt = card_ptr->m_attendance_start_time;
+        if(AS_ATTENDANCE != card_ptr->m_stat_attendance)//考勤结束时间
+        {
+            tt = std::chrono::system_clock::now();
+        }
+
+        std::string _time = tool_time::to_str(tt);
+
+        sprintf(sql, "CALL %s(%ld, %d, '%s', '%s', %d, %d, %.3f);", call.c_str(),
+                card_ptr->m_id, card_ptr->m_type, _time.c_str(), _time.c_str(),
+                card_ptr->m_landmarkid, card_ptr->m_landmarkdirect, card_ptr->m_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;
+//            }
+//        }
+    }
+};
+
+
+
+/**
+ * @brief 线程接口类,重写run函数,改变睡眠时间 sleep_ms
+ */
+class i_thread
+{
+public:
+    i_thread()
+    {
+        sleep_ms=10*1000;
+    }
+
+    virtual ~i_thread(){}
+
+    /**
+     * @brief 启动线程
+     */
+    void start()
+    {
+        _thread_flag=true;
+
+        _thread_handler=std::thread(&i_thread::thread_proc, this);
+    }
+
+    /**
+     * @brief 终止线程
+     */
+    void stop()
+    {
+        _thread_flag=false;
+        _thread_handler.join();
+    }
+
+    ///线程睡眠时间 毫秒
+    std::atomic<int> sleep_ms;
+
+protected:
+    /// 互斥量
+    std::mutex _mutex;
+
+    /**
+     * @brief 线程函数
+     */
+    virtual void run(){}
+
+private:
+    /// 线程句柄
+    std::thread _thread_handler;
+    /// 线程标志
+    std::atomic<bool> _thread_flag;
+
+    void thread_proc()
+    {
+        while(_thread_flag)
+        {
+            run();
+
+            std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
+        }
+    }
+};
+
+
+template<typename T>
+class singleton_base
+{
+public:
+    static T *instance()
+    {
+        if(nullptr != _instance)
+        {
+            return _instance;
+        }
+
+        std::lock_guard<std::mutex> ll(_mutex_singleton_base);
+        if(nullptr == _instance)
+        {
+            _instance = new(std::nothrow) T();
+        }
+
+        return _instance;
+    }
+
+protected:
+    //使继承者无法public构造函数和析构函数
+    singleton_base(){}
+    virtual ~singleton_base(){}
+private:
+    //禁止拷贝构造和赋值运算符
+    singleton_base(const singleton_base& src){}
+    singleton_base &operator=(const singleton_base& src){}
+
+    //它的唯一工作就是在析构函数中析构Singleton的实例,所以private
+    class Garbo
+    {
+    public:
+        ~Garbo()
+        {
+            if (singleton_base::_instance)
+            {
+                delete singleton_base::_instance;
+                singleton_base::_instance = nullptr;
+            }
+        }
+    };
+    //定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数,我们不需要访问这个变量,所以不需要初始化
+    static Garbo garbo;
+
+    static T *_instance;
+    static std::mutex _mutex_singleton_base;
+};
+
+
+
+#endif // MODULE_CONST_H

+ 2 - 0
module_service/module_mgr.cpp

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

+ 55 - 0
module_service/module_mgr.h

@@ -0,0 +1,55 @@
+#ifndef MODULE_MGR_H
+#define MODULE_MGR_H
+
+/**
+ * @brief 业务模块的管理类,包括:
+ * 1、初始化(init:注册web回调函数,读数据库初始化事件列表)
+ * 2、启动线程start:向web发送事件
+ * 3、结束线程stop
+ * @author 戴月腾
+ * @date 2018-08-25
+ */
+
+#include"module_web.h"
+#include"module_area.h"
+#include"module_call_help.h"
+
+class module_mgr: public singleton_base<module_mgr>
+{
+private:
+    friend class singleton_base<module_mgr>;
+    module_mgr()
+    {
+    }
+
+public:
+    /**
+     * @brief 注册web回调函数,读数据库初始化事件列表
+     */
+    void init()
+    {
+        //module_web::instance()->init();
+        module_area::instance()->init();
+        module_call_help::instance()->init();
+    }
+
+    /**
+     * @brief 启动线程start:向web发送事件
+     */
+    void start()
+    {
+        module_area::instance()->start();
+        module_call_help::instance()->start();
+    }
+
+    /**
+     * @brief 结束线程stop
+     */
+    void stop()
+    {
+        module_area::instance()->stop();
+        module_call_help::instance()->stop();
+    }
+};
+
+#endif // MODULE_MGR_H

+ 117 - 0
module_service/module_web.cpp

@@ -0,0 +1,117 @@
+#include "module_web.h"
+#include"module_const.h"
+#include"module_call_help.h"
+#include"module_call.h"
+#include"module_area.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("发来的数据不是对象");
+        return;
+    }
+
+    std::string cmd = data->get_map()[JSON_ROOT_KEY_CMD]->get_string();
+    if(cmd.empty())
+    {
+        log_error("cmd字段为空");
+        return;
+    }
+
+    if (JSON_CMD_VALUE_REQUEST_ALL_DATA == cmd)//web登录请求所有信息
+    {
+        response_login();
+    }
+    else if(JSON_CMD_VALUE_DEAL_HELP == cmd) // 处理呼救信息
+    {
+        module_call_help::instance()->accept_deal_help(data->get_map()[JSON_ROOT_KEY_DATA]->get_map());
+    }
+    else
+    {
+        std::string json=data->get_map()[JSON_ROOT_KEY_DATA]->get_string();
+        rapidjson::Document doc;
+        doc.Parse(json.c_str());
+
+        if(doc.HasParseError())
+        {
+            log_error("发来的data字段数据有错误");
+            return;
+        }
+
+        if(JSON_CMD_VALUE_CALL_CARD_REQUEST == cmd)//呼叫
+        {
+            module_call::instance()->accept_call(doc);
+        }
+        else if(JSON_CMD_VALUE_CALL_CARD_CANCEL_REQUEST == cmd)//取消呼叫
+        {
+            module_call::instance()->accept_cancel(doc);
+        }
+    }
+}
+
+void module_web::init(std::map<std::string, YA::MSG_HANDLE_FUNC_TYPE>& MsgFuncList)
+{
+//    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 ) );
+}
+
+
+void module_web::response_login()
+{
+    rapidjson::Document doc(rapidjson::kObjectType);
+    auto& allocator = doc.GetAllocator();
+    rapidjson::Value nodes(rapidjson::kArrayType);
+
+    //所有的呼叫信息
+    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);
+    }
+
+    //所有其他告警
+    str=module_area::instance()->response_login();
+    if(!str.empty())
+    {
+        nodes.PushBack(rapidjson::StringRef(str.c_str()), allocator);
+    }
+
+    if(nodes.Size()>0)
+    {
+        doc.AddMember(JSON_ROOT_KEY_CMD,JSON_CMD_VALUE_RESPONSE_ALL_DATA, allocator);
+        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));
+    }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 331 - 0
module_service/module_web.h

@@ -0,0 +1,331 @@
+#ifndef MODULE_WEB_H
+#define MODULE_WEB_H
+
+/**
+ * @brief 与web通信的接口类,以及json工具类:tool_json
+ * @author 戴月腾
+ * @date 2018-08-25
+ */
+
+#include <memory>
+#include <string>
+#include"module_const.h"
+
+#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>
+{
+private:
+    friend class singleton_base<module_web>;
+    module_web()
+    {
+    }
+
+    /**
+     * @brief 用来处理WEB发送的请求(web请求回调函数)
+     * @param ID
+     * @param name
+     * @param data
+     * @param need_ack
+     * @param ack_resp
+     */
+    void accept( int ID, std::string const& name,
+                 sio::message::ptr const& data, bool need_ack, sio::message::list &ack_resp );
+
+    /**
+     * @brief 注册web请求回调函数
+     * @param MsgFuncList
+     */
+    void init(std::map<std::string, YA::MSG_HANDLE_FUNC_TYPE>& MsgFuncList);
+
+    /// web前端有用户登录时,反馈给web所有信息
+    void response_login();
+};
+
+class tool_json
+{
+public:
+    static bool try_get_value(int& d, const char* k, const rapidjson::Value& data)
+    {
+        if(data.IsObject())
+        {
+            auto iter = data.FindMember(k);
+            if(data.MemberEnd() == iter)
+            {
+                return false;
+            }
+            if(iter->value.IsInt())
+            {
+                d = iter->value.GetInt();
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    static bool try_get_value(uint64_t& d, const char* k, const rapidjson::Value& data)
+    {
+        if(data.IsObject())
+        {
+            auto iter = data.FindMember(k);
+            if(data.MemberEnd() == iter)
+            {
+                return false;
+            }
+            if(iter->value.IsUint64())
+            {
+                d = iter->value.GetUint64();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static bool try_get_value(std::string& d, const char* k, const rapidjson::Value& data)
+    {
+        if(data.IsObject())
+        {
+            auto iter = data.FindMember(k);
+            if(data.MemberEnd() == iter)
+            {
+                return false;
+            }
+            if(iter->value.IsString())
+            {
+                d = iter->value.GetString();
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+//    static bool is_equal(const char* k, const char* v, const rapidjson::Value& data){
+//        auto iter = data.FindMember(k);
+//        if(data.MemberEnd() == iter){
+//            return false;
+//        }
+//        return 0 == strcmp(v, iter->value.GetString());
+//    }
+
+//    static bool is_equal(const char* k, const std::string& v, const rapidjson::Value& data){
+//        return is_equal(k, v.c_str(), data);
+//    }
+
+//    static int get_value(const char* k, const int& d, const rapidjson::Value& data){
+//        auto iter = data.FindMember(k);
+//        if(data.MemberEnd() == iter){
+//            return d;
+//        }
+//        if(iter->value.IsInt()){
+//            return iter->value.GetInt();
+//        }
+//        return d;
+//    }
+
+//    static std::string get_value(const char* k, const std::string& d, const rapidjson::Value& data){
+//        auto iter = data.FindMember(k);
+//        if(data.MemberEnd() == iter){
+//            return d;
+//        }
+//        if(iter->value.IsArray() || iter->value.IsObject()){
+//            return d;
+//        }
+//        return iter->value.GetString();
+//    }
+
+
+
+
+//    static void push_back(const std::string& v, rapidjson::Value& data, rapidjson::Document::AllocatorType& allocator){
+//        rapidjson::Value value_tmp;
+//        value_tmp.SetString(v.c_str(), static_cast<rapidjson::SizeType>(v.size()), allocator);
+//        data.PushBack(value_tmp, allocator);
+//    }
+
+    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 doc_to_json(rapidjson::Document& doc)
+    {
+        rapidjson::StringBuffer sb;
+        rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
+        doc.Accept(writer);
+
+        return sb.GetString();
+    }
+
+    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)
+        {
+            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);
+        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

+ 3 - 3
site_area.cpp

@@ -13,7 +13,7 @@ site_area_hover::site_area_hover()
 {
 }
 
-void site_area_hover::on_point(int64_t card_id,int site_id,const point*pt)
+void site_area_hover::on_point(uint64_t card_id,int site_id,const point*pt)
 {
 	if(pt!=nullptr)
 	{
@@ -40,13 +40,13 @@ void site_area_hover::on_point(int64_t card_id,int site_id,const point*pt)
 	}
 }
 
-void site_area_hover::enter_site(int64_t card_id,int enter_site)
+void site_area_hover::enter_site(uint64_t card_id,int enter_site)
 {
 
 
 }
 
-void site_area_hover::leave_site(int64_t card_id,int enter_site)
+void site_area_hover::leave_site(uint64_t card_id,int enter_site)
 {
 
 

+ 3 - 3
site_area.h

@@ -10,10 +10,10 @@ struct site_area_hover
 	//调用时机:
 	//1、tof一维收到第一个数据点时,以pt=0调用
 	//2、数据点解析完毕之后调用
-    void on_point(int64_t card_id,int site_id,const point*pt);
+    void on_point(uint64_t card_id,int site_id,const point*pt);
 private:
-    void enter_site(int64_t card_id,int enter_site);
-    void leave_site(int64_t card_id,int enter_site);
+    void enter_site(uint64_t card_id,int enter_site);
+    void leave_site(uint64_t card_id,int enter_site);
 
 	int    m_site_id;
 	time_t m_enter_time,m_last_time;