初始化提交
This commit is contained in:
parent
1af8f545c7
commit
dad3973bfc
112
platform/src/3rd/3rd目录结构调整.docx
Normal file
112
platform/src/3rd/3rd目录结构调整.docx
Normal file
@ -0,0 +1,112 @@
|
||||
3rd目录结构调整
|
||||
--------------------------------------------------------------------------------
|
||||
编写:易柯楠 2020/03/20
|
||||
|
||||
为什么需要调整
|
||||
当前的 ISCS6000_HOME\src\3rd 目录结构如下:
|
||||
|
||||
"include"目录用于存放第三方库编译部署后的头文件,编译的二进制文件(动态库、静态库)放在platform目录下各平台目录中。
|
||||
"src_package"目录用于存放第三方库的源码、编译说明等,非部署路径,而是为了源码存档。
|
||||
|
||||
当前的目录结构基于以下假设:
|
||||
第三方库是需要编译的,部署为编译后的二进制文件,和头文件。
|
||||
第三方库部署后的头文件,对各个平台、各种环境都是一样的,所以可以共用一份。比如Windows下和Linux下的头文件都是一样的。
|
||||
|
||||
以上的假设的确是最常见的情况,但是有些第三方库并不是这样的,这导致引入这些库时目录结构比较别扭。
|
||||
|
||||
有些第三方代码不需要编译成库
|
||||
这些代可能比较轻量,没必要单独编译;也可能作者就没做编译文件,让你直接用到自己的项目。这些代码往往都使用BSD、MIT等商业友好的协议开源,所以直接用到自己的项目中没有任何问题。
|
||||
当前,这类代码的处理方式如下:
|
||||
放到"include"目录下。其实并不合适,因为里面不仅仅是头文件,还包含了cpp、c等文件。比如"3rd\include\xlsx"。
|
||||
放在使用的项目目录中。这种弊端是:
|
||||
整个代码中可能会有多份,不便于管理。
|
||||
严格来说,BSD、MIT等开源协议都是要求在我们的发行包里携带一份协议类容的。这样散落在各个目录中,不便于我们梳理用了哪些第三方库。
|
||||
|
||||
有些第三方库的部署头文件在不同环境下不一样
|
||||
如果说上述原因"不痛不痒"的话,这个原因是促使我写此文的直接目的。
|
||||
这类第三方库一般有以下原因:
|
||||
不同平台下的代码本身就是不同的分支,比如hiredis。因此在不同系统下的头文件自然不同。
|
||||
头文件由编译时生成。比如由autoconf等工具,检查编译环境的编译器版本、相关库存在与否、版本等等,然后生成头文件。头文件必须与编译后的二进制文件对应,否则可能出现运行错误。这种情况,头文件不仅与操作系统相关,还与编译环境相关,因此不能简单区分window、linux,需与编译的库文件对应。比如SNMP++、Agent++。
|
||||
|
||||
调整方案
|
||||
目录结构
|
||||
|
||||
3rd
|
||||
include
|
||||
compiled_in
|
||||
src_package
|
||||
platform
|
||||
centos7
|
||||
ubuntu18
|
||||
windows10
|
||||
其他platform
|
||||
include
|
||||
|
||||
compiled_in
|
||||
|
||||
src_package
|
||||
|
||||
|
||||
|
||||
一级目录
|
||||
二级目录
|
||||
三级目录
|
||||
目录说明
|
||||
include
|
||||
自定义
|
||||
|
||||
如果头文件各平台通用,则可放在此目录
|
||||
需解释一点:
|
||||
不一定是一个第三方库一个目录,原则上遵循该库原本的部署目录结构,即该库在/usr/include/下,或者/usr/local/include下的部署结构。
|
||||
|
||||
compiled_in
|
||||
新增
|
||||
自定义
|
||||
|
||||
各平台通用的,无需编译的第三方代码。
|
||||
一个库一个目录。
|
||||
|
||||
src_package
|
||||
自定义
|
||||
|
||||
各平台通用的第三方代码源码包,编译说明等。
|
||||
一个库一个目录。
|
||||
platform
|
||||
新增
|
||||
|
||||
存放用于该平台的文件,各目录说明同上。
|
||||
windows10
|
||||
新增
|
||||
include
|
||||
比如breakpad、hiredis_win都应该移到这边来。
|
||||
"windows10"目录名的由来:与ISCS6000_PLATFORM系统环境变量名对应。
|
||||
|
||||
|
||||
compiled_in
|
||||
|
||||
|
||||
|
||||
src_package
|
||||
|
||||
|
||||
centos7
|
||||
新增
|
||||
同上
|
||||
目录名与ISCS6000_PLATFORM系统环境变量名对应。
|
||||
|
||||
ubuntu18
|
||||
新增
|
||||
同上
|
||||
目录名与ISCS6000_PLATFORM系统环境变量名对应。
|
||||
|
||||
common.pri文件
|
||||
|
||||
|
||||
|
||||
|
||||
实施步骤
|
||||
分两步走
|
||||
第一步,建立上述目录,修改common.pri。解决引入SNMP++、Agent++的问题。对于现有代码无感。
|
||||
第二步:将breakpad、hiredis_win等仅在Windows下使用的第三方库,移动至windows10下的相应目录。将散落在源码中的第三方库,集中归类到3rd目录。执行时间待定。
|
||||
|
||||
|
||||
17
platform/src/3rd/src_package/Boost/ReadMe.txt
Normal file
17
platform/src/3rd/src_package/Boost/ReadMe.txt
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
writen by yikenan,2018-01-02
|
||||
|
||||
编译参数:
|
||||
|
||||
Linux:
|
||||
./b2 stage --stagedir=/opt/boost/ linkflags="-Wl,-z,origin -Wl,-rpath,'\$ORIGIN'" --layout=system link=shared runtime-link=shared threading=multi variant=release -a -q -d+2 address-model=64 --with-regex --with-chrono --with-date_time --with-filesystem --with-program_options --with-system --with-thread --with-locale
|
||||
|
||||
Win release:
|
||||
b2.exe stage --stagedir=e:\boost\ cxxflags="/Zi" linkflags="/DEBUG" --layout=system link=shared runtime-link=shared threading=multi variant=release -a -q -d+2 address-model=64 --with-regex --with-chrono --with-date_time --with-filesystem --with-program_options --with-system --with-thread --with-locale
|
||||
|
||||
Win debug:
|
||||
b2.exe stage --stagedir=e:\boost\ --layout=system link=shared runtime-link=shared threading=multi variant=debug -a -q -d+2 address-model=64 --with-regex --with-chrono --with-date_time --with-filesystem --with-program_options --with-system --with-thread --with-locale
|
||||
|
||||
|
||||
注:
|
||||
从1.62的版本升级为1.68版本原因:解决条件变量time_wait时如果系统时间调整,造成死锁的问题。
|
||||
BIN
platform/src/3rd/src_package/Boost/boost_1_68_0.tar.gz
Normal file
BIN
platform/src/3rd/src_package/Boost/boost_1_68_0.tar.gz
Normal file
Binary file not shown.
BIN
platform/src/3rd/src_package/Lua/LuaBridge-master_1210.zip
Normal file
BIN
platform/src/3rd/src_package/Lua/LuaBridge-master_1210.zip
Normal file
Binary file not shown.
146
platform/src/3rd/src_package/Lua/Stack.patch
Normal file
146
platform/src/3rd/src_package/Lua/Stack.patch
Normal file
@ -0,0 +1,146 @@
|
||||
--- Stack_new.h 2018-12-12 09:58:49.286186200 +0800
|
||||
+++ Stack.h 2018-12-12 09:35:03.561621300 +0800
|
||||
@@ -83,6 +83,11 @@ struct Stack <int>
|
||||
|
||||
static inline int get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isinteger(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to integer");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <int> (luaL_checkinteger (L, index));
|
||||
}
|
||||
};
|
||||
@@ -106,6 +111,11 @@ struct Stack <unsigned int>
|
||||
|
||||
static inline unsigned int get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isinteger(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to integer");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <unsigned int> (luaL_checkinteger (L, index));
|
||||
}
|
||||
};
|
||||
@@ -129,6 +139,11 @@ struct Stack <unsigned char>
|
||||
|
||||
static inline unsigned char get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isinteger(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to integer");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <unsigned char> (luaL_checkinteger (L, index));
|
||||
}
|
||||
};
|
||||
@@ -152,6 +167,11 @@ struct Stack <short>
|
||||
|
||||
static inline short get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isinteger(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to integer");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <short> (luaL_checkinteger (L, index));
|
||||
}
|
||||
};
|
||||
@@ -175,6 +195,11 @@ struct Stack <unsigned short>
|
||||
|
||||
static inline unsigned short get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isinteger(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to integer");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <unsigned short> (luaL_checkinteger (L, index));
|
||||
}
|
||||
};
|
||||
@@ -198,6 +223,11 @@ struct Stack <long>
|
||||
|
||||
static inline long get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isinteger(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to integer");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <long> (luaL_checkinteger (L, index));
|
||||
}
|
||||
};
|
||||
@@ -221,6 +251,11 @@ struct Stack <unsigned long>
|
||||
|
||||
static inline unsigned long get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isinteger(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to integer");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <unsigned long> (luaL_checkinteger (L, index));
|
||||
}
|
||||
};
|
||||
@@ -244,6 +279,11 @@ struct Stack <float>
|
||||
|
||||
static inline float get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isnumber(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to float");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <float> (luaL_checknumber (L, index));
|
||||
}
|
||||
};
|
||||
@@ -266,6 +306,11 @@ template <> struct Stack <double>
|
||||
|
||||
static inline double get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isnumber(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to double");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <double> (luaL_checknumber (L, index));
|
||||
}
|
||||
};
|
||||
@@ -289,6 +334,11 @@ struct Stack <bool>
|
||||
|
||||
static inline bool get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isboolean(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to boolean");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return lua_toboolean (L, index) ? true : false;
|
||||
}
|
||||
};
|
||||
@@ -380,6 +430,11 @@ struct Stack <long long>
|
||||
}
|
||||
static inline long long get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isinteger(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to integer");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <long long> (luaL_checkinteger (L, index));
|
||||
}
|
||||
};
|
||||
@@ -402,6 +457,11 @@ struct Stack <unsigned long long>
|
||||
}
|
||||
static inline unsigned long long get (lua_State* L, int index)
|
||||
{
|
||||
+ if (!lua_isinteger(L, index))
|
||||
+ {
|
||||
+ std::logic_error ex("can not convert to integer");
|
||||
+ throw std::exception(ex);
|
||||
+ }
|
||||
return static_cast <unsigned long long> (luaL_checkinteger (L, index));
|
||||
}
|
||||
};
|
||||
BIN
platform/src/3rd/src_package/Lua/lua-5.3.4.tar.gz
Normal file
BIN
platform/src/3rd/src_package/Lua/lua-5.3.4.tar.gz
Normal file
Binary file not shown.
14
platform/src/3rd/src_package/Lua/lua编译.txt
Normal file
14
platform/src/3rd/src_package/Lua/lua编译.txt
Normal file
@ -0,0 +1,14 @@
|
||||
1、lua编译
|
||||
|
||||
windows平台:
|
||||
将win目录拷贝到lua5.3.4目录下,用vs2015打开编译即可
|
||||
|
||||
|
||||
linux平台:
|
||||
1、由于编译lua可执行程序需要依赖readline库,所以暂时仅编译liblua.so,不编译可执行程序
|
||||
2、lua默认只编译静态库,所以修改makefile,生成动态库,将lua_makefile文件中的Makefile文件替换掉lua源码中的文件
|
||||
3、执行make linux即可
|
||||
|
||||
2、LuaBridge
|
||||
LuaBridge是一个lua封装库,用模板实现,不需要编译,将解压文件拷贝include目录中即可。
|
||||
由于该库在返回值类型不匹配的情况下,会出现崩溃的问题,所以修改了源码,修改内容查看Stack.patch
|
||||
18
platform/src/3rd/src_package/ProtoBuf/ReadMe.txt
Normal file
18
platform/src/3rd/src_package/ProtoBuf/ReadMe.txt
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
writen by yikenan, 2018-01-02
|
||||
|
||||
protobuf使用gtest作为测试框架,但源代码包中不包含gtest,在autogen时会自动联网下载。
|
||||
由于公司网络限制,需手动下载gtest并解压到protobuf代码路径,并命名为“gtest”目录。
|
||||
|
||||
./autogen.sh
|
||||
./configure -prefix=/opt/protobuf --enable-static=no LDFLAGS="-Wl,-rpath,'\$\$ORIGIN' $LDFLAGS"
|
||||
gmake
|
||||
gmake check
|
||||
gmake install
|
||||
|
||||
只需复制动态库到platform目录。
|
||||
|
||||
Windows:
|
||||
在vsprojects\config.h增加:
|
||||
#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
|
||||
编译说明见vsprojects\readme.txt
|
||||
Binary file not shown.
BIN
platform/src/3rd/src_package/ProtoBuf/protobuf-2.6.1.tar.gz
Normal file
BIN
platform/src/3rd/src_package/ProtoBuf/protobuf-2.6.1.tar.gz
Normal file
Binary file not shown.
5
platform/src/3rd/src_package/RapidJSON/ReadMe.txt
Normal file
5
platform/src/3rd/src_package/RapidJSON/ReadMe.txt
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
#writen by yikenan,2018-08-28
|
||||
|
||||
纯头文件库,无需编译
|
||||
|
||||
BIN
platform/src/3rd/src_package/RapidJSON/rapidjson-1.1.0.zip
Normal file
BIN
platform/src/3rd/src_package/RapidJSON/rapidjson-1.1.0.zip
Normal file
Binary file not shown.
9
platform/src/3rd/src_package/ReadMe.txt
Normal file
9
platform/src/3rd/src_package/ReadMe.txt
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
writen by yikenan,2018-01-02
|
||||
|
||||
此目录为第三方组件源代码包存放目录,非部署路径。
|
||||
本目录下的个子目录内有各组件的编译说明。
|
||||
|
||||
注意:
|
||||
Unix、Linux下编译第三方库,请务必设置rpath为“$ORIGIN”,可用以下命令查看rpath字段:
|
||||
readelf -d 文件名
|
||||
105
platform/src/3rd/src_package/ZeroMQ/ReadMe.txt
Normal file
105
platform/src/3rd/src_package/ZeroMQ/ReadMe.txt
Normal file
@ -0,0 +1,105 @@
|
||||
|
||||
writen by yikenan,2018-01-02
|
||||
|
||||
由于指定prefix时,czmq始终会添加编译时libzmq的路径到rpath,需修改编译脚本才能改变,而且较为麻烦。
|
||||
所以,不指定prefix,默认为/usr/local。
|
||||
依次编译zeromq、czmq:
|
||||
|
||||
./autogen.sh
|
||||
./configure --enable-static=no --enable-drafts=no LDFLAGS="-Wl,-z,origin -Wl,-rpath,'\$\$ORIGIN' $LDFLAGS"
|
||||
make
|
||||
sudo make install
|
||||
|
||||
拷贝prefix路径下的lib目录下的动态库至platform下的对应系统目录
|
||||
拷贝prefix路径下的include目录下的文件到ISCS_HOME/src/3rd/include目录
|
||||
|
||||
依次清理zeromq、czmq安装:
|
||||
sudo make uninstall
|
||||
prefix路径下会残留空目录,可手动删除
|
||||
|
||||
|
||||
#########################################################################################################
|
||||
|
||||
Windows:
|
||||
建议安装新版Win SDK,见下方 AF_UNIX 相关段落说明。
|
||||
|
||||
官方已不推荐使用源码包中的VS工程进行编译了,推荐使用cmake。
|
||||
解压zeromq,目录命名为libzmq;解压czmq,目录命名为czmq;两个目录在同一级。
|
||||
|
||||
编译libzmq:
|
||||
编辑CMakeLists.txt,搜索"-mt",删除相应内容,让生成的文件名为libzmq.dll
|
||||
在VS命令行中执行:
|
||||
cmake -G "NMake Makefiles" -D CMAKE_BUILD_TYPE=Debug -D ZMQ_BUILD_TESTS=OFF -D BUILD_STATIC=OFF -D POLLER="epoll" -D API_POLLER="poll" -D ENABLE_DRAFTS=OFF -S . -B cmake_debug
|
||||
cd cmake_debug
|
||||
nmake
|
||||
|
||||
编译czmq:
|
||||
为防止编译出的dll为libczmq.dll,而lib文件为czmq.lib。编辑CMakeLists.txt,搜索"OUTPUT_NAME",值修改为"libczmq",并删除下方的"PREFIX"属性。
|
||||
cmake -G "NMake Makefiles" -D CMAKE_BUILD_TYPE=Debug -D BUILD_TESTING=OFF -D CZMQ_BUILD_STATIC=OFF -D ENABLE_DRAFTS=OFF -D LIBZMQ_INCLUDE_DIRS="..\libzmq\include" -D LIBZMQ_LIBRARIES="..\libzmq\cmake_debug\lib\libzmq.lib" -S . -B cmake_debug
|
||||
cd cmake_debug
|
||||
nmake
|
||||
|
||||
编译release版本同理,将命令中的"debug"换为release,保持大小写一致
|
||||
cmake -G "NMake Makefiles" -D CMAKE_BUILD_TYPE=Release -D ZMQ_BUILD_TESTS=OFF -D BUILD_STATIC=OFF -D POLLER="epoll" -D API_POLLER="poll" -D ENABLE_DRAFTS=OFF -S . -B cmake_release
|
||||
|
||||
cmake -G "NMake Makefiles" -D CMAKE_BUILD_TYPE=Release -D BUILD_TESTING=OFF -D CZMQ_BUILD_STATIC=OFF -D ENABLE_DRAFTS=OFF -D LIBZMQ_INCLUDE_DIRS="..\libzmq\include" -D LIBZMQ_LIBRARIES="..\libzmq\cmake_release\lib\libzmq.lib" -S . -B cmake_release
|
||||
|
||||
#########################################################################################################
|
||||
|
||||
Win 10 1709已支持AF_UNIX,ZeroMQ 4.3.3也对此做了适配,本机通信可以使用IPC方式
|
||||
Win 10增加AF_UNIX的文章:
|
||||
https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
|
||||
关键内容如下:
|
||||
How can I write a Windows AF_UNIX app?
|
||||
Download the Windows Insiders SDK for the Windows build 17061 — available here.
|
||||
Check whether your Windows build has support for unix socket by running “sc query afunix” from a Windows admin command prompt.
|
||||
#include <afunix.h> in your Windows application and write a Windows unix socket winsock application as you would write any other unix socket application, but, using Winsock API’s.
|
||||
|
||||
所以,要编译具有AF_UNIX特性的libzmq,VS 2015要安装对应于win 1709及以上版本的Win SDK,VS 2017及以上版本自带的win SDK就支持,无需再单独安装。
|
||||
|
||||
经消息总线整体测试,有以下结果:
|
||||
1、使用新版SDK编译的ZeroMQ性能(包括TCP连接方式)较VS2015自带的老SDK(应该是Win8.1的)更好。不严谨测试表明,小包极限性能提升有50%多。
|
||||
2、基于新版SDK编译的TCP方式与IPC方式(基于af_unix)性能差别不大,甚至TCP方式的小包极限性能更好。
|
||||
3、win不支持抽象命名的af_unix,必须使用文件系统路径,给使用带来不便。
|
||||
因此,没有启用ZeroMQ的IPC(基于af_unix)方式,但使用新版SDK编译是值得的。
|
||||
|
||||
最后一次提交的zmq库(SVN 16687,2021年1月22日) 使用的Win SDK 版本为:2004,详细版本号:10.0.19041.685
|
||||
|
||||
使用新版win sdk找不到rc.exe等问题:
|
||||
C:\Program Files (x86)\Windows Kits\10\bin下的x64等目录下缺失内容,应该是vs2015与新版win sdk配合问题。
|
||||
解决方法:将x64等原目录改名(以作备份,比如改名为x64_backup),然后建立软链指向本目录具体版本目录下的同名文件夹,参考如下:
|
||||
|
||||
C:\Windows\system32>cd C:\Program Files (x86)\Windows Kits\10\bin
|
||||
C:\Program Files (x86)\Windows Kits\10\bin>mklink /J arm 10.0.20348.0\arm
|
||||
为 arm <<===>> 10.0.20348.0\arm 创建的联接
|
||||
C:\Program Files (x86)\Windows Kits\10\bin>mklink /J arm64 10.0.20348.0\arm64
|
||||
为 arm64 <<===>> 10.0.20348.0\arm64 创建的联接
|
||||
C:\Program Files (x86)\Windows Kits\10\bin>mklink /J x64 10.0.20348.0\x64
|
||||
为 x64 <<===>> 10.0.20348.0\x64 创建的联接
|
||||
C:\Program Files (x86)\Windows Kits\10\bin>mklink /J x86 10.0.20348.0\x86
|
||||
为 x86 <<===>> 10.0.20348.0\x86 创建的联接
|
||||
|
||||
|
||||
#########################################################################################################
|
||||
|
||||
libzmq 4.2.5 版本存在如下Bug,在Win上较容易触发,在Linux概率很低,但长时间反复测试依然能触发。
|
||||
更新到 4.3.0 版本后,未发现此Bug。
|
||||
|
||||
1、A连接B,TCP连接后(此时监视A端,会收到ZMQ_EVENT_CONNECTED事件),进行ZMQ握手(期间会进行ZAP身份验证)。
|
||||
2、B端对A的ZAP身份验证不通过(比如不满足IP白名单),B端关闭来自A的连接(此时监视A端,会收到ZMQ_EVENT_DISCONNECTED事件)。
|
||||
3、A端的libzmq在内部会释放掉连接资源,但不知何种原因,zsock_t中的对该资源的指针未清理。此时外部再调用zsock_disconnect,会释放该指针指向的资源,但此对象已经被释放,该地址的内容可能已经变化,最终导致在zeromq-4.2.5/src/pipe.cpp 436行,状态值不在可能的范围内,从而assert,如下:
|
||||
// There are no other states.
|
||||
else {
|
||||
zmq_assert (false);
|
||||
}
|
||||
4、网络异常导致的断开,也可能会有此问题,只是手动测试次数、频度太低,没有触发过。
|
||||
|
||||
在官方修复此问题前,临时处理方案:
|
||||
在zeromq-4.2.5/src/pipe.cpp 436行,assert前,增加return语句。
|
||||
这样修改后,反复测试,未发现异常,未发现内存增长。
|
||||
|
||||
// There are no other states.
|
||||
else {
|
||||
return; //< added by yikenan
|
||||
zmq_assert (false);
|
||||
}
|
||||
BIN
platform/src/3rd/src_package/ZeroMQ/czmq-4.2.1.zip
Normal file
BIN
platform/src/3rd/src_package/ZeroMQ/czmq-4.2.1.zip
Normal file
Binary file not shown.
BIN
platform/src/3rd/src_package/ZeroMQ/gsl-4.1.5.tar.gz
Normal file
BIN
platform/src/3rd/src_package/ZeroMQ/gsl-4.1.5.tar.gz
Normal file
Binary file not shown.
BIN
platform/src/3rd/src_package/ZeroMQ/zeromq-4.3.4.zip
Normal file
BIN
platform/src/3rd/src_package/ZeroMQ/zeromq-4.3.4.zip
Normal file
Binary file not shown.
BIN
platform/src/3rd/src_package/ZeroMQ/zproto-master-20180115.zip
Normal file
BIN
platform/src/3rd/src_package/ZeroMQ/zproto-master-20180115.zip
Normal file
Binary file not shown.
16
platform/src/3rd/src_package/breakpad/Readme.txt
Normal file
16
platform/src/3rd/src_package/breakpad/Readme.txt
Normal file
@ -0,0 +1,16 @@
|
||||
参考教程:https://kingsamchen.github.io/2016/09/24/build-and-integrate-the-newest-version-of-breakpad-on-windows/
|
||||
压缩包breakpad.7z里面包含gyp和breakpad
|
||||
1. 下载https://chromium.googlesource.com/breakpad/breakpad
|
||||
2. 解压
|
||||
3. 下载gyp https://chromium.googlesource.com/external/gyp
|
||||
4. 安装gyp,将gyp.bat 目录添加至path
|
||||
5. 安装python3
|
||||
6. 打开cmd
|
||||
7. cd 到 breakpad所在目录 breakpad\src\client\windows\
|
||||
8. 执行命令行
|
||||
|
||||
SET GYP_MSVS_VERSION=2015
|
||||
gyp.bat --no-circular-check breakpad_client.gyp -Dwin_release_RuntimeLibrary=2 -Dwin_debug_RuntimeLibrary=3
|
||||
|
||||
9. 生成 sln,生成。
|
||||
10. 将debug和release目录的五个lib文件拷贝至对应目录
|
||||
BIN
platform/src/3rd/src_package/breakpad/breakpad.7z
Normal file
BIN
platform/src/3rd/src_package/breakpad/breakpad.7z
Normal file
Binary file not shown.
76
platform/src/3rd/src_package/curl/ReadMe.txt
Normal file
76
platform/src/3rd/src_package/curl/ReadMe.txt
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
writen by yikenan,2018-06-21
|
||||
modified by yikenan,2018-10-24
|
||||
|
||||
CentOS 7:
|
||||
./configure -prefix=/opt/curl --enable-static=no --with-zlib=/opt/zlib LDFLAGS="-Wl,-rpath,'\$\$ORIGIN' $LDFLAGS"
|
||||
gmake
|
||||
gmake install
|
||||
|
||||
拷贝install路径下的lib目录下的动态库至platform下的对应系统目录
|
||||
拷贝install路径下的include目录下的文件到ISCS_HOME/src/3rd/include目录
|
||||
|
||||
configure报告的信息如下:
|
||||
configure: Configured to build curl/libcurl:
|
||||
|
||||
curl version: 7.61.1
|
||||
Host setup: x86_64-pc-linux-gnu
|
||||
Install prefix: /opt/curl
|
||||
Compiler: gcc
|
||||
SSL support: enabled (OpenSSL)
|
||||
SSH support: no (--with-libssh2)
|
||||
zlib support: enabled
|
||||
brotli support: no (--with-brotli)
|
||||
GSS-API support: no (--with-gssapi)
|
||||
TLS-SRP support: no (--enable-tls-srp)
|
||||
resolver: POSIX threaded
|
||||
IPv6 support: enabled
|
||||
Unix sockets support: enabled
|
||||
IDN support: no (--with-{libidn2,winidn})
|
||||
Build libcurl: Shared=yes, Static=no
|
||||
Built-in manual: enabled
|
||||
--libcurl option: enabled (--disable-libcurl-option)
|
||||
Verbose errors: enabled (--disable-verbose)
|
||||
SSPI support: no (--enable-sspi)
|
||||
ca cert bundle: /etc/pki/tls/certs/ca-bundle.crt
|
||||
ca cert path: no
|
||||
ca fallback: no
|
||||
LDAP support: enabled (OpenLDAP)
|
||||
LDAPS support: enabled
|
||||
RTSP support: enabled
|
||||
RTMP support: no (--with-librtmp)
|
||||
metalink support: no (--with-libmetalink)
|
||||
PSL support: no (libpsl not found)
|
||||
HTTP2 support: disabled (--with-nghttp2)
|
||||
Protocols: DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3 POP3S RTSP SMB SMBS SMTP SMTPS TELNET TFTP
|
||||
|
||||
[root@centos-7-5-test-2 bin]# ./curl -V
|
||||
curl 7.61.1 (x86_64-pc-linux-gnu) libcurl/7.61.1 OpenSSL/1.0.2k zlib/1.2.7
|
||||
Release-Date: 2018-09-05
|
||||
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
|
||||
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL libz UnixSockets HTTPS-proxy
|
||||
|
||||
|
||||
|
||||
Windows:
|
||||
|
||||
详见源码包winbuild目录下的说明
|
||||
|
||||
复制zlib的头文件zconf.h、zlib.h到E:\src_package\zlib_install_debug\include
|
||||
复制zlib的编译后库文件到E:\src_package\zlib_install_debug\lib
|
||||
|
||||
nmake /f Makefile.vc WITH_DEVEL=E:\src_package\zlib_install_debug WITH_ZLIB=dll mode=dll VC=14 MACHINE=x64 DEBUG=yes
|
||||
|
||||
若希望Debug、Release版本统一文件名,即Debug版本不带“_debug”,则修改MakefileBuild.vc文件
|
||||
BASE_NAME_DEBUG、BASE_NAME_STATIC_DEBUG去掉“_debug”
|
||||
|
||||
release同理。
|
||||
nmake /f Makefile.vc WITH_DEVEL=E:\src_package\zlib_install_release WITH_ZLIB=dll mode=dll VC=14 MACHINE=x64 DEBUG=no
|
||||
|
||||
支持信息如下:
|
||||
E:\src_package\curl-7.61.1\builds\libcurl-vc14-x64-debug-dll-zlib-dll-ipv6-sspi-winssl\bin>curl.exe -V
|
||||
curl 7.61.1 (x86_64-pc-win32) libcurl/7.61.1 WinSSL zlib/1.2.11 WinIDN
|
||||
Release-Date: 2018-09-05
|
||||
Protocols: dict file ftp ftps gopher http https imap imaps ldap pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
|
||||
Features: AsynchDNS IDN IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL libz
|
||||
|
||||
BIN
platform/src/3rd/src_package/curl/curl-7.61.1.zip
Normal file
BIN
platform/src/3rd/src_package/curl/curl-7.61.1.zip
Normal file
Binary file not shown.
30
platform/src/3rd/src_package/hikvision/00_ReadMe.txt
Normal file
30
platform/src/3rd/src_package/hikvision/00_ReadMe.txt
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
Written by YiKenan on 2020/06/04
|
||||
--------------------------------------------------------------------
|
||||
|
||||
本目录为海康威视网络SDK,用于集成海康威视门禁(人脸、指纹识别)设备
|
||||
|
||||
版本:CH-HCNetSDKV6.1.4.42_build20200527_win64
|
||||
|
||||
本库不开源,没有源码,且完整SDK包较为臃肿,故不在本目录保存,需要时可去海康威视官网下载。
|
||||
|
||||
部署路径:
|
||||
ISCS6000_HOME\platform\平台名\hikvision
|
||||
|
||||
头文件路径:
|
||||
ISCS6000_HOME\src\3rd\include\hikvision
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
部署路径单独使用一个目录,原因如下:
|
||||
1、文件较多,单独使用一个目录便于识别用途及管理。
|
||||
2、该SDK使用了一些开源库(比如zlib、OpenSSL),我们自己也使用了,混用可能导致版本问题。
|
||||
|
||||
如何解决动态库路径问题:
|
||||
1、Windows下使用Manifests方案,参考文档:
|
||||
https://docs.microsoft.com/zh-cn/windows/win32/dlls/dynamic-link-library-search-order?redirectedfrom=MSDN
|
||||
https://docs.microsoft.com/en-us/windows/win32/sbscs/manifests
|
||||
https://www.cnblogs.com/morebread/p/4953497.html
|
||||
部署路径下的hikvision.manifest文件是由我们自己创建的,编译时的连接器参数在头文件目录中的pri中定义。
|
||||
|
||||
2、Linux、Unix下使用rpath实现,编译时的连接器参数在头文件目录中的pri中定义。
|
||||
12
platform/src/3rd/src_package/hiredis/README.txt
Normal file
12
platform/src/3rd/src_package/hiredis/README.txt
Normal file
@ -0,0 +1,12 @@
|
||||
说明:分别是hiredis和它的异步依赖event的压缩包
|
||||
|
||||
libevent编译:
|
||||
./configure --prefix=/home/ykn/3rd_src/install/libevent/ --with-pic LDFLAGS="-Wl,-rpath,'\$\$ORIGIN' $LDFLAGS"
|
||||
make
|
||||
make install
|
||||
|
||||
hiredis编译:
|
||||
直接make即可
|
||||
|
||||
原版不支持windows,所以各平台头文件分开部署,比如CentOS下头文件部署在:
|
||||
ISCS6000_HOME\src\3rd\platform\centos7\include
|
||||
BIN
platform/src/3rd/src_package/hiredis/hiredis-0.14.0.tar.gz
Normal file
BIN
platform/src/3rd/src_package/hiredis/hiredis-0.14.0.tar.gz
Normal file
Binary file not shown.
Binary file not shown.
7863
platform/src/3rd/src_package/hiredis/ubuntu18_libevent_config.log
Normal file
7863
platform/src/3rd/src_package/hiredis/ubuntu18_libevent_config.log
Normal file
File diff suppressed because it is too large
Load Diff
BIN
platform/src/3rd/src_package/hiredis/windows/hiredis-master.zip
Normal file
BIN
platform/src/3rd/src_package/hiredis/windows/hiredis-master.zip
Normal file
Binary file not shown.
468
platform/src/3rd/src_package/hiredis/windows/net.c
Normal file
468
platform/src/3rd/src_package/hiredis/windows/net.c
Normal file
@ -0,0 +1,468 @@
|
||||
/* Extracted from anet.c to work properly with Hiredis error reporting.
|
||||
*
|
||||
* Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fmacros.h"
|
||||
#include <sys/types.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#ifndef _WIN32
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#ifndef _WIN32
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "sds.h"
|
||||
#ifdef _WIN32
|
||||
#include "win32_hiredis.h"
|
||||
#include "mstcpip.h"
|
||||
#endif
|
||||
|
||||
/* Defined in hiredis.c */
|
||||
void __redisSetError(redisContext *c, int type, const char *str);
|
||||
|
||||
static void redisContextCloseFd(redisContext *c) {
|
||||
if (c && c->fd >= 0) {
|
||||
close(c->fd);
|
||||
c->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {
|
||||
char buf[128] = { 0 };
|
||||
size_t len = 0;
|
||||
|
||||
if (prefix != NULL)
|
||||
len = snprintf(buf,sizeof(buf),"%s: ",prefix);
|
||||
strerror_r(errno,buf+len,sizeof(buf)-len);
|
||||
__redisSetError(c,type,buf);
|
||||
}
|
||||
|
||||
static int redisSetReuseAddr(redisContext *c) {
|
||||
int on = 1;
|
||||
if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
static int redisCreateSocket(redisContext *c, int type) {
|
||||
int s;
|
||||
if ((s = socket(type, SOCK_STREAM, 0)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
c->fd = s;
|
||||
if (type == AF_INET) {
|
||||
if (redisSetReuseAddr(c) == REDIS_ERR) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
static int redisSetBlocking(redisContext *c, int blocking) {
|
||||
int flags;
|
||||
|
||||
/* Set the socket nonblocking.
|
||||
* Note that fcntl(2) for F_GETFL and F_SETFL can't be
|
||||
* interrupted by a signal. */
|
||||
if ((flags = fcntl(c->fd, F_GETFL,0)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (blocking)
|
||||
flags &= ~O_NONBLOCK;
|
||||
else
|
||||
flags |= O_NONBLOCK;
|
||||
|
||||
if (fcntl(c->fd, F_SETFL, flags) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)");
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisKeepAlive(redisContext *c, int interval) {
|
||||
int val = 1;
|
||||
int fd = c->fd;
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
val = interval;
|
||||
|
||||
#ifdef _OSX
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#else
|
||||
#ifndef __sun
|
||||
#ifdef _WIN32
|
||||
{
|
||||
struct tcp_keepalive settings;
|
||||
DWORD bytesReturned;
|
||||
WSAOVERLAPPED overlapped;
|
||||
settings.onoff = 1;
|
||||
settings.keepalivetime = interval*1000;
|
||||
settings.keepaliveinterval = interval*1000/3;
|
||||
overlapped.hEvent = NULL;
|
||||
FDAPI_WSAIoctl(fd,
|
||||
SIO_KEEPALIVE_VALS,
|
||||
&settings,
|
||||
sizeof(struct tcp_keepalive),
|
||||
NULL,
|
||||
0,
|
||||
&bytesReturned,
|
||||
&overlapped,
|
||||
NULL);
|
||||
}
|
||||
#else
|
||||
val = interval;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
val = interval/3;
|
||||
if (val == 0) val = 1;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
val = 3;
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
static int redisSetTcpNoDelay(redisContext *c) {
|
||||
int yes = 1;
|
||||
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)");
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)
|
||||
|
||||
static int redisContextWaitReady(redisContext *c, const struct timeval *timeout) {
|
||||
struct pollfd wfd[1];
|
||||
PORT_LONG msec;
|
||||
|
||||
msec = -1;
|
||||
wfd[0].fd = c->fd;
|
||||
wfd[0].events = POLLOUT;
|
||||
|
||||
/* Only use timeout when not NULL. */
|
||||
if (timeout != NULL) {
|
||||
if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {
|
||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000);
|
||||
|
||||
if (msec < 0 || msec > INT_MAX) {
|
||||
msec = INT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
if (errno == EINPROGRESS) {
|
||||
int res;
|
||||
|
||||
if ((res = poll(wfd, 1, (int) msec)) == -1) { WIN_PORT_FIX /* cast (int) */
|
||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
} else if (res == 0) {
|
||||
errno = ETIMEDOUT;
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (redisCheckSocketError(c) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
redisContextCloseFd(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
int redisCheckSocketError(redisContext *c) {
|
||||
int err = 0;
|
||||
socklen_t errlen = sizeof(err);
|
||||
|
||||
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)");
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
errno = err;
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
int redisContextSetTimeout(redisContext *c, const struct timeval tv) {
|
||||
//< modify by yikenan
|
||||
#ifdef _WIN32
|
||||
DWORD msec = (tv.tv_sec * 1000) + ((tv.tv_usec + 999) / 1000);
|
||||
|
||||
if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&msec,sizeof(msec)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)");
|
||||
return REDIS_ERR;
|
||||
}
|
||||
if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&msec,sizeof(msec)) == -1) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)");
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#else
|
||||
if (setsockopt(c->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
|
||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "setsockopt(SO_RCVTIMEO)");
|
||||
return REDIS_ERR;
|
||||
}
|
||||
if (setsockopt(c->fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
|
||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "setsockopt(SO_SNDTIMEO)");
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#endif
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
int redisContextPreConnectTcp(
|
||||
redisContext *c,
|
||||
const char *addr,
|
||||
int port,
|
||||
struct timeval *timeout,
|
||||
SOCKADDR_STORAGE* ss) {
|
||||
int blocking = (c->flags & REDIS_BLOCK);
|
||||
|
||||
if (ParseStorageAddress(addr, port, ss) == FALSE) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (REDIS_OK != redisCreateSocket(c, ss->ss_family)) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
if (redisSetTcpNoDelay(c) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
if (blocking == 0) {
|
||||
if (redisSetBlocking(c, 0) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
||||
const struct timeval *timeout,
|
||||
const char *source_addr) {
|
||||
int s, rv;
|
||||
char _port[6]; /* strlen("65535"); */
|
||||
struct addrinfo hints, *servinfo, *bservinfo, *p, *b;
|
||||
int blocking = (c->flags & REDIS_BLOCK);
|
||||
|
||||
snprintf(_port, 6, "%d", port);
|
||||
memset(&hints,0,sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
/* Try with IPv6 if no IPv4 address was found. We do it in this order since
|
||||
* in a Redis client you can't afford to test if you have IPv6 connectivity
|
||||
* as this would add latency to every connect. Otherwise a more sensible
|
||||
* route could be: Use IPv6 if both addresses are available and there is IPv6
|
||||
* connectivity. */
|
||||
if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
|
||||
hints.ai_family = AF_INET6;
|
||||
if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
|
||||
__redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
for (p = servinfo; p != NULL; p = p->ai_next) {
|
||||
if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
|
||||
continue;
|
||||
|
||||
c->fd = s;
|
||||
if (redisSetBlocking(c,0) != REDIS_OK)
|
||||
goto error;
|
||||
if (source_addr) {
|
||||
int bound = 0;
|
||||
/* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */
|
||||
if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) {
|
||||
char buf[128];
|
||||
snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv));
|
||||
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
||||
goto error;
|
||||
}
|
||||
for (b = bservinfo; b != NULL; b = b->ai_next) {
|
||||
if (bind(s,b->ai_addr,(socklen_t)b->ai_addrlen) != -1) {
|
||||
bound = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
freeaddrinfo(bservinfo);
|
||||
if (!bound) {
|
||||
char buf[128];
|
||||
snprintf(buf,sizeof(buf),"Can't bind socket: %s",strerror(errno));
|
||||
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
|
||||
if (errno == EHOSTUNREACH) {
|
||||
redisContextCloseFd(c);
|
||||
continue;
|
||||
} else if (errno == EINPROGRESS && !blocking) {
|
||||
/* This is ok. */
|
||||
} else {
|
||||
if (redisContextWaitReady(c,timeout) != REDIS_OK)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (blocking && redisSetBlocking(c,1) != REDIS_OK)
|
||||
goto error;
|
||||
if (redisSetTcpNoDelay(c) != REDIS_OK)
|
||||
goto error;
|
||||
|
||||
c->flags |= REDIS_CONNECTED;
|
||||
rv = REDIS_OK;
|
||||
goto end;
|
||||
}
|
||||
if (p == NULL) {
|
||||
char buf[128];
|
||||
snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno));
|
||||
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
rv = REDIS_ERR;
|
||||
end:
|
||||
freeaddrinfo(servinfo);
|
||||
return rv; // Need to return REDIS_OK if alright
|
||||
}
|
||||
|
||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
||||
const struct timeval *timeout) {
|
||||
return _redisContextConnectTcp(c, addr, port, timeout, NULL);
|
||||
}
|
||||
|
||||
int redisContextConnectBindTcp(redisContext *c, const char *addr, int port,
|
||||
const struct timeval *timeout,
|
||||
const char *source_addr) {
|
||||
return _redisContextConnectTcp(c, addr, port, timeout, source_addr);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {
|
||||
(void) timeout;
|
||||
__redisSetError(c,REDIS_ERR_IO,
|
||||
sdscatprintf(sdsempty(),"Unix sockets are not suported on Windows platform. (%s)\n", path));
|
||||
|
||||
return REDIS_ERR;
|
||||
}
|
||||
#else
|
||||
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {
|
||||
int blocking = (c->flags & REDIS_BLOCK);
|
||||
struct sockaddr_un sa;
|
||||
|
||||
if (redisCreateSocket(c,AF_LOCAL) < 0)
|
||||
return REDIS_ERR;
|
||||
if (redisSetBlocking(c,0) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
sa.sun_family = AF_LOCAL;
|
||||
strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
|
||||
if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
|
||||
if (errno == EINPROGRESS && !blocking) {
|
||||
/* This is ok. */
|
||||
} else {
|
||||
if (redisContextWaitReady(c,timeout) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset socket to be blocking after connect(2). */
|
||||
if (blocking && redisSetBlocking(c,1) != REDIS_OK)
|
||||
return REDIS_ERR;
|
||||
|
||||
c->flags |= REDIS_CONNECTED;
|
||||
return REDIS_OK;
|
||||
}
|
||||
#endif
|
||||
14
platform/src/3rd/src_package/hiredis/windows/readme.txt
Normal file
14
platform/src/3rd/src_package/hiredis/windows/readme.txt
Normal file
@ -0,0 +1,14 @@
|
||||
易柯楠
|
||||
2020/05/27
|
||||
|
||||
原版不支持windows,使用微软修改的版本,下载自:
|
||||
https://github.com/microsoft/hiredis
|
||||
|
||||
编译说明:
|
||||
1、解压后工程文件在hiredis-master\msvs\vs-solutions\vs2015
|
||||
2、为了与我们的工程的运行库一致,将个子工程的 属性,C/C++,代码生成,运行库修改为多线程DLL
|
||||
3、修正Win下redisSetTimeout()时间不正确的Bug,见本目录net.c文件277行,或搜索yikenan
|
||||
4、编译生成
|
||||
|
||||
删除无用文件,将头文件部署在
|
||||
ISCS6000_HOME\src\3rd\platform\windows10\include\hiredis
|
||||
@ -0,0 +1,16 @@
|
||||
--- E:/svn/ISCS6000/Development_Repository/ISCS6000_HOME/src/3rd/src_package/log4cplus/log4cplus_original/log4cplus-REL_1_2_1-RC2/src/consoleappender.cxx Öܶþ 5Ô 29 10:02:10 2018
|
||||
+++ E:/svn/ISCS6000/Development_Repository/ISCS6000_HOME/src/3rd/src_package/log4cplus/log4cplus-REL_1_2_1-RC2/src/consoleappender.cxx Öܶþ 5Ô 29 10:17:01 2018
|
||||
@@ -29,0 +30 @@
|
||||
+#include "boost/locale.hpp"
|
||||
@@ -103,0 +105,8 @@ ConsoleAppender::append(const spi::InternalLogging
|
||||
+ log4cplus::tstring strMsg = event.getMessage();
|
||||
+ std::string strCodePage = boost::locale::util::get_system_locale();
|
||||
+ std::locale loc = boost::locale::generator().generate(strCodePage);
|
||||
+ log4cplus::tstring strTemp = boost::locale::conv::from_utf(strMsg, loc);
|
||||
+
|
||||
+ spi::InternalLoggingEvent objEv = event;
|
||||
+ objEv.setMessage(strTemp);
|
||||
+
|
||||
@@ -105 +114 @@ ConsoleAppender::append(const spi::InternalLogging
|
||||
- layout->formatAndAppend(output, event);
|
||||
+ layout->formatAndAppend(output, objEv);
|
||||
Binary file not shown.
114
platform/src/3rd/src_package/log4cplus/log4cplus.patch
Normal file
114
platform/src/3rd/src_package/log4cplus/log4cplus.patch
Normal file
@ -0,0 +1,114 @@
|
||||
diff -Naur log4cplus-REL_1_2_1-RC2/include/log4cplus/spi/loggingevent.h log4cplus-REL_1_2_1-RC2-modify/include/log4cplus/spi/loggingevent.h
|
||||
--- log4cplus-REL_1_2_1-RC2/include/log4cplus/spi/loggingevent.h 2017-07-12 02:03:51.000000000 +0800
|
||||
+++ log4cplus-REL_1_2_1-RC2-modify/include/log4cplus/spi/loggingevent.h 2018-08-28 15:00:45.500086834 +0800
|
||||
@@ -100,7 +100,8 @@
|
||||
|
||||
void setFunction (char const * func);
|
||||
void setFunction (log4cplus::tstring const &);
|
||||
-
|
||||
+
|
||||
+ void setMessage(const log4cplus::tstring& msg);
|
||||
|
||||
// public virtual methods
|
||||
/** The application supplied message of logging event. */
|
||||
diff -Naur log4cplus-REL_1_2_1-RC2/msvc10/log4cplus.props log4cplus-REL_1_2_1-RC2-modify/msvc10/log4cplus.props
|
||||
--- log4cplus-REL_1_2_1-RC2/msvc10/log4cplus.props 2017-07-12 02:03:51.000000000 +0800
|
||||
+++ log4cplus-REL_1_2_1-RC2-modify/msvc10/log4cplus.props 2018-08-28 16:15:59.921761955 +0800
|
||||
@@ -9,8 +9,8 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
- <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
- <PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x05010200;INSIDE_LOG4CPLUS;_SCL_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
+ <AdditionalIncludeDirectories>..\include;$(SolutionDir)..\..\..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
+ <PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0501;WINVER=0x0501;NTDDI_VERSION=0x05010200;INSIDE_LOG4CPLUS;_SCL_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;BOOST_ALL_NO_LIB=1;BOOST_ALL_DYN_LINK=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)$(ProjectName).pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||
@@ -29,9 +29,11 @@
|
||||
<EnableCOMDATFolding>false</EnableCOMDATFolding>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
<ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
|
||||
+ <AdditionalLibraryDirectories>$(SolutionDir)..\..\..\..\..\..\platform\$(ISCS6000_PLATFORM)_$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
+ <AdditionalDependencies>boost_locale.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<Lib>
|
||||
<AdditionalDependencies>ws2_32.lib</AdditionalDependencies>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
-</Project>
|
||||
\ 文件尾没有 newline 字符
|
||||
+</Project>
|
||||
diff -Naur log4cplus-REL_1_2_1-RC2/msvc10/log4cplus.vcxproj log4cplus-REL_1_2_1-RC2-modify/msvc10/log4cplus.vcxproj
|
||||
--- log4cplus-REL_1_2_1-RC2/msvc10/log4cplus.vcxproj 2017-07-12 02:03:51.000000000 +0800
|
||||
+++ log4cplus-REL_1_2_1-RC2-modify/msvc10/log4cplus.vcxproj 2018-08-28 16:34:50.387313747 +0800
|
||||
@@ -153,11 +153,11 @@
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
||||
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)D</TargetName>
|
||||
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug_Unicode|Win32'">$(ProjectName)UD</TargetName>
|
||||
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>
|
||||
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug_Unicode|Win32'">$(ProjectName)U</TargetName>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release_Unicode|Win32'">$(ProjectName)U</TargetName>
|
||||
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectName)D</TargetName>
|
||||
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug_Unicode|x64'">$(ProjectName)UD</TargetName>
|
||||
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectName)</TargetName>
|
||||
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug_Unicode|x64'">$(ProjectName)U</TargetName>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release_Unicode|x64'">$(ProjectName)U</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
@@ -1093,4 +1093,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
-</Project>
|
||||
\ 文件尾没有 newline 字符
|
||||
+</Project>
|
||||
diff -Naur log4cplus-REL_1_2_1-RC2/src/consoleappender.cxx log4cplus-REL_1_2_1-RC2-modify/src/consoleappender.cxx
|
||||
--- log4cplus-REL_1_2_1-RC2/src/consoleappender.cxx 2017-07-12 02:03:51.000000000 +0800
|
||||
+++ log4cplus-REL_1_2_1-RC2-modify/src/consoleappender.cxx 2018-08-28 15:07:34.453999214 +0800
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <log4cplus/spi/loggingevent.h>
|
||||
#include <log4cplus/thread/syncprims-pub-impl.h>
|
||||
#include <ostream>
|
||||
+#include "boost/locale.hpp"
|
||||
|
||||
|
||||
namespace log4cplus
|
||||
@@ -100,10 +101,18 @@
|
||||
void
|
||||
ConsoleAppender::append(const spi::InternalLoggingEvent& event)
|
||||
{
|
||||
+ log4cplus::tstring strMsg = event.getMessage();
|
||||
+ std::string strCodePage = boost::locale::util::get_system_locale();
|
||||
+ std::locale loc = boost::locale::generator().generate(strCodePage);
|
||||
+ log4cplus::tstring strTemp = boost::locale::conv::from_utf(strMsg, loc);
|
||||
+
|
||||
+ spi::InternalLoggingEvent objEvent = event;
|
||||
+ objEvent.setMessage(strTemp);
|
||||
+
|
||||
thread::MutexGuard guard (getOutputMutex ());
|
||||
|
||||
tostream& output = (logToStdErr ? tcerr : tcout);
|
||||
- layout->formatAndAppend(output, event);
|
||||
+ layout->formatAndAppend(output, objEvent);
|
||||
if(immediateFlush) {
|
||||
output.flush();
|
||||
}
|
||||
diff -Naur log4cplus-REL_1_2_1-RC2/src/loggingevent.cxx log4cplus-REL_1_2_1-RC2-modify/src/loggingevent.cxx
|
||||
--- log4cplus-REL_1_2_1-RC2/src/loggingevent.cxx 2017-07-12 02:03:51.000000000 +0800
|
||||
+++ log4cplus-REL_1_2_1-RC2-modify/src/loggingevent.cxx 2018-08-28 15:02:28.628034040 +0800
|
||||
@@ -213,6 +213,12 @@
|
||||
}
|
||||
|
||||
|
||||
+void
|
||||
+InternalLoggingEvent::setMessage(const log4cplus::tstring& msg)
|
||||
+{
|
||||
+ message = msg;
|
||||
+}
|
||||
+
|
||||
const log4cplus::tstring&
|
||||
InternalLoggingEvent::getMessage() const
|
||||
{
|
||||
@ -0,0 +1,8 @@
|
||||
--- E:/svn/ISCS6000/Development_Repository/ISCS6000_HOME/src/3rd/src_package/log4cplus/log4cplus_original/log4cplus-REL_1_2_1-RC2/src/loggingevent.cxx 周二 7月 11 11:03:50 2017
|
||||
+++ E:/svn/ISCS6000/Development_Repository/ISCS6000_HOME/src/3rd/src_package/log4cplus/log4cplus-REL_1_2_1-RC2/src/loggingevent.cxx 周二 5月 29 10:10:51 2018
|
||||
@@ -222,0 +223,5 @@ InternalLoggingEvent::getMessage() const
|
||||
+void InternalLoggingEvent::setMessage(const log4cplus::tstring& msg)
|
||||
+{
|
||||
+ message = msg;
|
||||
+}
|
||||
+
|
||||
@ -0,0 +1,4 @@
|
||||
--- E:/svn/ISCS6000/Development_Repository/ISCS6000_HOME/src/3rd/src_package/log4cplus/log4cplus_original/log4cplus-REL_1_2_1-RC2/include/log4cplus/spi/loggingevent.h 周二 7月 11 11:03:50 2017
|
||||
+++ E:/svn/ISCS6000/Development_Repository/ISCS6000_HOME/src/3rd/src_package/log4cplus/log4cplus-REL_1_2_1-RC2/include/log4cplus/spi/loggingevent.h 周二 5月 29 10:19:39 2018
|
||||
@@ -108,0 +109 @@ namespace log4cplus {
|
||||
+ void setMessage(const log4cplus::tstring& msg);
|
||||
14
platform/src/3rd/src_package/log4cplus/编译说明.txt
Normal file
14
platform/src/3rd/src_package/log4cplus/编译说明.txt
Normal file
@ -0,0 +1,14 @@
|
||||
1、log4cplus配置文件中的Locale、Encoding配置对控制台无效(也可能时用法不对),造成Window平台控制台乱码
|
||||
2、为了解决Window平台下控制台乱码,修改了部分代码,由于需要用到编码转换,暂时使用了boost的loacle库进行编码转换
|
||||
3、修改如下:
|
||||
a)修改工程配置,Debug版本的目标名去掉后缀D,保持debug和release版本的库名一致。
|
||||
b)修改工程配置,预处理器中增加宏定义:
|
||||
BOOST_ALL_NO_LIB=1
|
||||
BOOST_ALL_DYN_LINK=1
|
||||
c)修改工程配置,增加boost路径,链接boost_locale.lib
|
||||
d)修改源文件,修改内容查看consoleappender.cxx.patch、loggingevent.cxx.patch、loggingevent.h.patch
|
||||
4、将补丁文件log4cplus.patch打上
|
||||
windows平台打补丁命令:patch.exe -p1 --binary < ..\log4cplus.patch
|
||||
linux平台打补丁命令:patch.exe -p1 < ..\log4cplus.patch
|
||||
4、编译非Unicode版本
|
||||
|
||||
77
platform/src/3rd/src_package/oatpp/ReadMe.txt
Normal file
77
platform/src/3rd/src_package/oatpp/ReadMe.txt
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
writen by yikenan,2021-11-29
|
||||
|
||||
#########################################################################################################
|
||||
Linux:
|
||||
|
||||
1、CentOS下的cmake版本太低,需要安装高版本,见下方独立章节
|
||||
|
||||
2、mkdir build && cd build
|
||||
|
||||
3、作者建议使用静态库,作者称动态库并没有严格的测试,不保证动态库没有问题。
|
||||
我们遇到并解决的问题:https://github.com/oatpp/oatpp/issues/557
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=~/3rd/install_path/
|
||||
|
||||
4、make -j 4 && make install
|
||||
|
||||
5、编译任何组件,需添加CMAKE_PREFIX_PATH的定义,与CMAKE_INSTALL_PREFIX一致,这样可以自动找到依赖的核心库:
|
||||
-DCMAKE_PREFIX_PATH=~/3rd/install_path/
|
||||
|
||||
6、编译组件zlib,需要指定使用我们代码路径的zlib,设置如下:
|
||||
注意:路径改成你自己的路径,路径中的操作系统是否正确,务必使用绝对路径
|
||||
-DZLIB_INCLUDE_DIR=/home/ykn/00_svn/platform_home/platform/src/3rd/include -DZLIB_LIBRARY_RELEASE=/home/ykn/00_svn/platform_home/platform/centos7_debug/libz.so
|
||||
|
||||
麒麟:
|
||||
-DZLIB_INCLUDE_DIR=/home/ykn/00_svn/platform_home/platform/src/3rd/include -DZLIB_LIBRARY_RELEASE=/home/ykn/00_svn/platform_home/platform/kylin10d_debug/libz.so
|
||||
|
||||
|
||||
|
||||
|
||||
#########################################################################################################
|
||||
|
||||
Windows:
|
||||
|
||||
由于oatpp当前没有写导出(__declspec(dllexport)或.Def文件),所以只能编译静态库,如果编译为动态库将没有.lib文件。
|
||||
|
||||
1、mkdir build && cd build
|
||||
|
||||
2、用“VS2015 x64 本机工具命令提示符”运行命令。
|
||||
cmake .. -A x64 -DCMAKE_INSTALL_PREFIX=D:\3rd\install_path
|
||||
|
||||
3、使用vs打开生成的sln工程,进行编译,编译“INSTALL”子项目安装到CMAKE_INSTALL_PREFIX指定的路径。
|
||||
建议设置目标平台为新版win sdk,老的(8.1)没试。
|
||||
|
||||
4、编译任何组件,需添加CMAKE_PREFIX_PATH的定义,与CMAKE_INSTALL_PREFIX一致,这样可以自动找到依赖的核心库:
|
||||
-DCMAKE_PREFIX_PATH=D:\3rd\install_path
|
||||
|
||||
5、编译组件zlib,需要指定使用我们代码路径的zlib,设置如下:
|
||||
注意:路径改成你自己的路径,路径中的操作系统是否正确,务必使用绝对路径
|
||||
-DZLIB_INCLUDE_DIR=D:\00_snv\platform_home\platform\src\3rd\include
|
||||
-DZLIB_LIBRARY_DEBUG=D:\00_snv\platform_home\platform\windows10_debug\zlibwapi.lib
|
||||
-DZLIB_LIBRARY_RELEASE=D:\00_snv\platform_home\platform\windows10_release\zlibwapi.lib
|
||||
|
||||
|
||||
|
||||
最后:
|
||||
编译完所有的Debug后,将CMAKE_INSTALL_PREFIX路径改名为_debug,然后再编译Release。
|
||||
注意:组件直接用之前的vs工程,切换到Release后编译的话,会自动重新执行cmake,重新生成项目。建议清空build目录,手动重新执行cmake,及之前的步骤,以确保与之前一致。
|
||||
|
||||
|
||||
#########################################################################################################
|
||||
|
||||
CentOS下安装新版cmake:
|
||||
|
||||
1、启用scl源,离网状态下可直接去 pkgs.org 下载需要的软件包
|
||||
sudo yum install centos-release-scl-rh centos-release-scl
|
||||
|
||||
2、下载并安装以下软件包,见 cmake-sclo-rh-3.6/install.sh
|
||||
|
||||
#编译oatpp需要,与cmake无关
|
||||
rpm -ivh ./libatomic-4.8.5-44.el7.x86_64.rpm
|
||||
|
||||
rpm -ivh ./llvm-toolset-7-runtime-5.0.1-4.el7.x86_64.rpm
|
||||
rpm -ivh ./llvm-toolset-7-cmake-3.6.2-9.el7.x86_64.rpm ./llvm-toolset-7-cmake-data-3.6.2-9.el7.noarch.rpm
|
||||
|
||||
3、启用 cmake 环境,启用后命令为 cmake3
|
||||
scl enable llvm-toolset-7 bash
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
#written by yikn,2021/11/29
|
||||
|
||||
filepath=$(cd "$(dirname "$0")"; pwd)
|
||||
#echo $filepath
|
||||
|
||||
cd $filepath
|
||||
|
||||
#编译oatpp需要,与cmake无关
|
||||
rpm -ivh ./libatomic-4.8.5-44.el7.x86_64.rpm
|
||||
|
||||
rpm -ivh ./llvm-toolset-7-runtime-5.0.1-4.el7.x86_64.rpm
|
||||
rpm -ivh ./llvm-toolset-7-cmake-3.6.2-9.el7.x86_64.rpm ./llvm-toolset-7-cmake-data-3.6.2-9.el7.noarch.rpm
|
||||
|
||||
scl enable llvm-toolset-7 bash
|
||||
|
||||
@ -0,0 +1 @@
|
||||
rpm包省略,可去 https://pkgs.org/ 等网站下载
|
||||
BIN
platform/src/3rd/src_package/oatpp/oatpp-master-20220214.zip
Normal file
BIN
platform/src/3rd/src_package/oatpp/oatpp-master-20220214.zip
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
4
platform/src/3rd/src_package/openssl/Readme.txt
Normal file
4
platform/src/3rd/src_package/openssl/Readme.txt
Normal file
@ -0,0 +1,4 @@
|
||||
社区预编译版
|
||||
|
||||
https://kb.firedaemon.com/support/solutions/articles/4000121705
|
||||
当前采用的版本是1.1.1h
|
||||
BIN
platform/src/3rd/src_package/quazip/quazip-0.9.x.zip
Normal file
BIN
platform/src/3rd/src_package/quazip/quazip-0.9.x.zip
Normal file
Binary file not shown.
14
platform/src/3rd/src_package/quazip/readme.txt
Normal file
14
platform/src/3rd/src_package/quazip/readme.txt
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
quazip底层有一份minizip,在linux下默认导出了符号,会和外部的minizip冲突(xlsxio用到)
|
||||
故修改了quazip/quazip.pro(注意,不是最外层目录的quazip.pro,是下一级目录的)文件,增加了以下内容,默认不导出符号
|
||||
linux-g++* {
|
||||
QMAKE_CFLAGS += -fvisibility=hidden
|
||||
QMAKE_CXXFLAGS += -fvisibility=hidden
|
||||
}
|
||||
|
||||
|
||||
编译依赖
|
||||
zlib和qt
|
||||
1.进入解压目录
|
||||
2.qmake
|
||||
3.make
|
||||
22
platform/src/3rd/src_package/sigar/ReadMe.txt
Normal file
22
platform/src/3rd/src_package/sigar/ReadMe.txt
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
writen by yikenan,2020-03-17
|
||||
|
||||
********************************************************************************
|
||||
|
||||
直接编入我们的代码,无需生成为库文件,部署路径:
|
||||
3rd\compiled_in\sigar
|
||||
|
||||
原因:
|
||||
1、SIGAR最初设计给java使用,所以原作者提供的编译方式为ant。在各平台下搭建ant比较麻烦。
|
||||
|
||||
2、虽然其他人提供了一些编译方式,但质量参差不齐,各平台使用也不方便。
|
||||
|
||||
3、SIGAR作者已长期不维护,且当前已有一些编译不过的地方,需要修改代码。
|
||||
不如纳入我们的版本库,由我们自己维护。有什么改动,查看SVN也比较方便。
|
||||
|
||||
4、SIGAR的开源协议为Apache License V2,允许我们这么做。
|
||||
|
||||
所以,经研究原版编译方法,自己为SIGAR写了QT的prj工程文件,使用方法:
|
||||
在需要使用SIGAR的pro工程文件中,include sigar.pri即可,比如:
|
||||
|
||||
include($$PWD/../../3rd/compiled_in/sigar/sigar.pri)
|
||||
BIN
platform/src/3rd/src_package/sigar/sigar-master_20200228.zip
Normal file
BIN
platform/src/3rd/src_package/sigar/sigar-master_20200228.zip
Normal file
Binary file not shown.
45
platform/src/3rd/src_package/snmp++/ReadMe.txt
Normal file
45
platform/src/3rd/src_package/snmp++/ReadMe.txt
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
writen by yikenan,2020-02-28
|
||||
|
||||
********************************************************************************
|
||||
|
||||
特别注意:
|
||||
部署头文件时,libsnmp.h、config_snmp_pp.h、libagent.h需区分平台
|
||||
在最外层的3rd\include目录中,不应存在这3个文件
|
||||
|
||||
********************************************************************************
|
||||
|
||||
snmp++-3.3.12
|
||||
估计由于作者打包的疏漏,这个版本直接编译不过。
|
||||
作者在changelog中提到(见CHANGES.snmp++v3文件):
|
||||
- Fixed: md5.h: Removed the extern "C" declaration, as it not needed
|
||||
and does not allow to use namespaces.
|
||||
但是打包的文件中忘记去掉了md5c.cpp文件中的extern "C",注释掉即可编译通过。
|
||||
|
||||
********************************************************************************
|
||||
Linux编译:
|
||||
先编译snmp++,配置命令如下:
|
||||
./configure --prefix=/home/ykn/3rd_src/install/snmp++/ --with-pic --disable-rpath LDFLAGS="-Wl,-z,origin -Wl,-rpath,'\$\$ORIGIN' $LDFLAGS"
|
||||
make
|
||||
make install
|
||||
configure记录见ubuntu18_snmp++_config.log
|
||||
|
||||
arm架构下如果configure提示需指定build type,则增加参数
|
||||
--build=aarch64-unknown-linux-gnu
|
||||
|
||||
再编译agent++,需指定snmp++库的位置,配置命令如下:
|
||||
./configure --prefix=/home/ykn/3rd_src/install/agent++/ --with-libsnmp-prefix=/home/ykn/3rd_src/install/snmp++/ --with-pic --disable-rpath LDFLAGS="-Wl,-z,origin -Wl,-rpath,'\$\$ORIGIN' $LDFLAGS"
|
||||
make
|
||||
make install
|
||||
configure记录见ubuntu18_agent++_config.log
|
||||
|
||||
CentOS特别说明:
|
||||
1、比如按上面的将snmp++安装到了/home/ykn/3rd_src/install/snmp++/目录,必须将该目录下的lib目录改名为lib64,否则agent++的configure找不到库。
|
||||
2、由于FES需要用snmp++编译动态库,必须开启PIC特性,即在configure时带参 --with-pic 。ubuntu18(kernel 5.3 , gcc 7.5)未见此问题。
|
||||
|
||||
********************************************************************************
|
||||
Windows编译:
|
||||
见windows目录
|
||||
|
||||
********************************************************************************
|
||||
|
||||
BIN
platform/src/3rd/src_package/snmp++/agent++-4.2.0.tar.gz
Normal file
BIN
platform/src/3rd/src_package/snmp++/agent++-4.2.0.tar.gz
Normal file
Binary file not shown.
1
platform/src/3rd/src_package/snmp++/agent++2.pdf
Normal file
1
platform/src/3rd/src_package/snmp++/agent++2.pdf
Normal file
@ -0,0 +1 @@
|
||||
|
||||
4253
platform/src/3rd/src_package/snmp++/centos7_agent++_config.log
Normal file
4253
platform/src/3rd/src_package/snmp++/centos7_agent++_config.log
Normal file
File diff suppressed because it is too large
Load Diff
6437
platform/src/3rd/src_package/snmp++/centos7_snmp++_config.log
Normal file
6437
platform/src/3rd/src_package/snmp++/centos7_snmp++_config.log
Normal file
File diff suppressed because it is too large
Load Diff
362
platform/src/3rd/src_package/snmp++/md5c.cpp
Normal file
362
platform/src/3rd/src_package/snmp++/md5c.cpp
Normal file
@ -0,0 +1,362 @@
|
||||
/*_############################################################################
|
||||
_##
|
||||
_## md5c.cpp
|
||||
_##
|
||||
_## SNMP++ v3.3
|
||||
_## -----------------------------------------------
|
||||
_## Copyright (c) 2001-2013 Jochen Katz, Frank Fock
|
||||
_##
|
||||
_## This software is based on SNMP++2.6 from Hewlett Packard:
|
||||
_##
|
||||
_## Copyright (c) 1996
|
||||
_## Hewlett-Packard Company
|
||||
_##
|
||||
_## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
|
||||
_## Permission to use, copy, modify, distribute and/or sell this software
|
||||
_## and/or its documentation is hereby granted without fee. User agrees
|
||||
_## to display the above copyright notice and this license notice in all
|
||||
_## copies of the software and any documentation of the software. User
|
||||
_## agrees to assume all liability for the use of the software;
|
||||
_## Hewlett-Packard and Jochen Katz make no representations about the
|
||||
_## suitability of this software for any purpose. It is provided
|
||||
_## "AS-IS" without warranty of any kind, either express or implied. User
|
||||
_## hereby grants a royalty-free license to any and all derivatives based
|
||||
_## upon this software code base.
|
||||
_##
|
||||
_##########################################################################*/
|
||||
char md5c_cpp_version[]="#(@) SNMP++ $Id$";
|
||||
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm */
|
||||
|
||||
/* Copyright (C) 1991, RSA Data Security, Inc. All rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it
|
||||
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software
|
||||
or this function.
|
||||
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is"
|
||||
without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
*/
|
||||
|
||||
#include <libsnmp.h>
|
||||
|
||||
#include "snmp_pp/md5.h"
|
||||
|
||||
#if !defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
|
||||
|
||||
//#ifdef __cplusplus
|
||||
//extern "C" {
|
||||
//#endif
|
||||
|
||||
#ifdef SNMP_PP_NAMESPACE
|
||||
namespace Snmp_pp {
|
||||
#endif
|
||||
|
||||
/* Constants for MD5Transform routine.
|
||||
*/
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
|
||||
static void MD5Transform(UINT4 [4], const unsigned char [64]);
|
||||
static void Encode(unsigned char *, UINT4 *, unsigned int);
|
||||
static void Decode(UINT4 *, const unsigned char *, unsigned int);
|
||||
static void MD5_memcpy(POINTER, POINTER, unsigned int);
|
||||
static void MD5_memset(POINTER, int, unsigned int);
|
||||
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* F, G, H and I are basic MD5 functions.
|
||||
*/
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits.
|
||||
*/
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||
Rotation is separate from addition to prevent recomputation.
|
||||
*/
|
||||
#define FF(a, b, c, d, x, s, ac) { \
|
||||
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) { \
|
||||
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) { \
|
||||
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) { \
|
||||
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
/* MD5 initialization. Begins an MD5 operation, writing a new context.
|
||||
*/
|
||||
void MD5Init (MD5_CTX *context)
|
||||
{
|
||||
context->count[0] = context->count[1] = 0;
|
||||
|
||||
/* Load magic initialization constants.
|
||||
*/
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xefcdab89;
|
||||
context->state[2] = 0x98badcfe;
|
||||
context->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
/* MD5 block update operation. Continues an MD5 message-digest operation,
|
||||
processing another message block, and updating the context.
|
||||
*/
|
||||
void MD5Update (MD5_CTX *context, /* context */
|
||||
const unsigned char *input, /* input block */
|
||||
const unsigned int inputLen) /* length of input block */
|
||||
{
|
||||
unsigned int i, index, partLen;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
|
||||
|
||||
/* Update number of bits */
|
||||
if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
|
||||
context->count[1]++;
|
||||
context->count[1] += ((UINT4)inputLen >> 29);
|
||||
|
||||
partLen = 64 - index;
|
||||
|
||||
/* Transform as many times as possible.
|
||||
*/
|
||||
if (inputLen >= partLen) {
|
||||
MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen);
|
||||
MD5Transform (context->state, context->buffer);
|
||||
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
MD5Transform (context->state, &input[i]);
|
||||
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
|
||||
/* Buffer remaining input */
|
||||
MD5_memcpy
|
||||
((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
|
||||
}
|
||||
|
||||
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
|
||||
the message digest and zeroizing the context.
|
||||
*/
|
||||
void MD5Final (
|
||||
unsigned char digest[16], /* message digest */
|
||||
MD5_CTX *context) /* context */
|
||||
{
|
||||
unsigned char bits[8];
|
||||
unsigned int index, padLen;
|
||||
|
||||
/* Save number of bits */
|
||||
Encode (bits, context->count, 8);
|
||||
|
||||
/* Pad out to 56 mod 64.
|
||||
*/
|
||||
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
|
||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
MD5Update (context, PADDING, padLen);
|
||||
|
||||
/* Append length (before padding) */
|
||||
MD5Update (context, bits, 8);
|
||||
|
||||
/* Store state in digest */
|
||||
Encode (digest, context->state, 16);
|
||||
|
||||
/* Zeroize sensitive information.
|
||||
*/
|
||||
MD5_memset ((POINTER)context, 0, sizeof (*context));
|
||||
}
|
||||
|
||||
/* MD5 basic transformation. Transforms state based on block.
|
||||
*/
|
||||
static void MD5Transform (
|
||||
UINT4 state[4],
|
||||
const unsigned char block[64])
|
||||
{
|
||||
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
|
||||
Decode (x, block, 64);
|
||||
|
||||
/* Round 1 */
|
||||
FF ( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF ( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF ( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
|
||||
FF ( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF ( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF ( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF ( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF ( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF ( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF ( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF ( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF ( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF ( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF ( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF ( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF ( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG ( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG ( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG ( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG ( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG ( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG ( d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG ( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG ( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG ( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG ( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG ( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG ( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG ( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG ( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG ( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG ( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH ( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH ( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH ( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH ( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH ( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH ( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH ( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH ( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH ( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH ( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH ( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH ( b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
|
||||
HH ( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH ( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH ( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH ( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
II ( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
|
||||
II ( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
|
||||
II ( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II ( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II ( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II ( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II ( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II ( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II ( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II ( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II ( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
|
||||
II ( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II ( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II ( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II ( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II ( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
|
||||
/* Zeroize sensitive information.
|
||||
*/
|
||||
MD5_memset ((POINTER)x, 0, sizeof (x));
|
||||
}
|
||||
|
||||
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
|
||||
a multiple of 4.
|
||||
*/
|
||||
static void Encode (
|
||||
unsigned char *output,
|
||||
UINT4 *input,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = (unsigned char)(input[i] & 0xff);
|
||||
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
|
||||
a multiple of 4.
|
||||
*/
|
||||
static void Decode (
|
||||
UINT4 *output,
|
||||
const unsigned char *input,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
|
||||
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
|
||||
}
|
||||
|
||||
static void MD5_memcpy (
|
||||
POINTER output,
|
||||
POINTER input,
|
||||
unsigned int len)
|
||||
{
|
||||
memcpy(output, input, len);
|
||||
}
|
||||
|
||||
static void MD5_memset (
|
||||
POINTER output,
|
||||
int value,
|
||||
unsigned int len)
|
||||
{
|
||||
memset(output, value, len);
|
||||
}
|
||||
|
||||
#ifdef SNMP_PP_NAMESPACE
|
||||
} // end of namespace Snmp_pp
|
||||
#endif
|
||||
|
||||
//#ifdef __cplusplus
|
||||
//}
|
||||
//#endif
|
||||
|
||||
#endif // !defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
|
||||
BIN
platform/src/3rd/src_package/snmp++/snmp++-3.3.12.tar.gz
Normal file
BIN
platform/src/3rd/src_package/snmp++/snmp++-3.3.12.tar.gz
Normal file
Binary file not shown.
4096
platform/src/3rd/src_package/snmp++/ubuntu18_agent++_config.log
Normal file
4096
platform/src/3rd/src_package/snmp++/ubuntu18_agent++_config.log
Normal file
File diff suppressed because it is too large
Load Diff
6967
platform/src/3rd/src_package/snmp++/ubuntu18_snmp++_config.log
Normal file
6967
platform/src/3rd/src_package/snmp++/ubuntu18_snmp++_config.log
Normal file
File diff suppressed because it is too large
Load Diff
28
platform/src/3rd/src_package/snmp++/windows/ReadMe.txt
Normal file
28
platform/src/3rd/src_package/snmp++/windows/ReadMe.txt
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
writen by yikenan,2020-03-14
|
||||
|
||||
********************************************************************************
|
||||
|
||||
修改好的工程文件已存为 vs2013_yikenan.zip
|
||||
如果后期更新版本,请对比并修改 vs2013\SNMP++\include\ 下的文件
|
||||
|
||||
********************************************************************************
|
||||
|
||||
1、解压vs2013.zip,见里面README.win32文件说明,按要求建立目录结构。
|
||||
|
||||
2、使用工具对比vs2013\SNMP++\include\ 与 snmp++\include\ 下的3个文件,并做修改。
|
||||
根据config.h的宏定义,修改libsnmp.h,部署时无需config.h
|
||||
|
||||
4、删除snmp++\include\snmp_pp\config_snmp_pp.h文件,以确保使用上一步中的文件。
|
||||
|
||||
3、按libdes、SNMP++、AGENT++、AgentX++的顺序编译。
|
||||
|
||||
4、SNMP++的VS工程需要修改:
|
||||
属性页 - 配置属性 - VC++目录 - 包含目录 中的路径为本机实际路径。
|
||||
属性页 - 配置属性 - C/C++ - 预处理器 - 预处理器定义 中对各配置分别添加 _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
|
||||
原版release配置漏加了东西:
|
||||
预处理器定义中添加 HAVE_CONFIG_H 和 _CRT_SECURE_NO_WARNINGS
|
||||
属性页 - 配置属性 - C/C++ - 常规 - 附加包含目录 中添加 $(SolutionDir)\..\..\libdes
|
||||
|
||||
5、Agent++工程类似上文的SNMP++处理,有个别编译问题稍作代码修改即可。
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 508 KiB |
Binary file not shown.
BIN
platform/src/3rd/src_package/snmp++/windows/vs2013.zip
Normal file
BIN
platform/src/3rd/src_package/snmp++/windows/vs2013.zip
Normal file
Binary file not shown.
BIN
platform/src/3rd/src_package/snmp++/windows/vs2013_yikenan.zip
Normal file
BIN
platform/src/3rd/src_package/snmp++/windows/vs2013_yikenan.zip
Normal file
Binary file not shown.
35
platform/src/3rd/src_package/xlsxio/Readme.txt
Normal file
35
platform/src/3rd/src_package/xlsxio/Readme.txt
Normal file
@ -0,0 +1,35 @@
|
||||
简介:用于文件流读写xlsx文件,内存占用极小,处理100万个cell大概需要15-20秒
|
||||
|
||||
项目地址:https://github.com/brechtsanders/xlsxio
|
||||
|
||||
项目license:MIT
|
||||
|
||||
Windows编译方法参见官方的README,
|
||||
项目直接使用官方的预编译包(https://github.com/brechtsanders/xlsxio/releases/latest)后用msvc略加处理
|
||||
1. 解压文件xlsxio-master.zip
|
||||
2. 打开vsvarsall.bat amd64,并进入第一步的目录
|
||||
3. cd lib
|
||||
lib /def:libxlsxio_write.def /out:libxlsxio_write.lib /machine:x64
|
||||
lib /def:libxlsxio_read.def /out:libxlsxio_read.lib /machine:x64
|
||||
4. 将生成的libxlsxio_write.lib和libxlsxio_read.lib以及bin目录下的libxlsxio_read.dll和libxlsxio_write.dll放入platform目录下即可。
|
||||
|
||||
|
||||
|
||||
Linux编译方法
|
||||
|
||||
因为项目依赖的quazip底层也有一份minizip,编译quazip时需将quazip的minizip隐藏,详见quazip的pro编译配置
|
||||
|
||||
Linux底层依赖minizip
|
||||
1. 解压unzip101e.zip,解压后目录名改为minizip
|
||||
2. 将platfrom下的libz.so放入到解压后的文件夹
|
||||
3. Makefile替换为目录下的Makefile
|
||||
4. 编译生成libminizip.so
|
||||
|
||||
5. 解压xlsxio-master.zip,解压后目录和minizip目录同级
|
||||
6. mkdir builddir
|
||||
7. cd builddir
|
||||
8. cmake .. -DCMAKE_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,origin" -DCMAKE_INSTALL_RPATH="\$ORIGIN" -DCMAKE_BUILD_WITH_INSTALL_RPATH=TRUE -DMINIZIP_LIBRARIES="/home/ykn/3rd_src/xlsxio/minizip/libminizip.so" -DMINIZIP_INCLUDE_DIRS:PATH=../
|
||||
其中MINIZIP_LIBRARIES是libminizip.so所在的文件夹,MINIZIP_INCLUDE_DIRS是包含minizip目录的文件夹
|
||||
ubuntu18必须设置rpath包含$ORIGIN,猜测可执行程序的rpath不可用于其依赖的动态库,而CentOS7可以。
|
||||
9. make
|
||||
10. 将libxlsxio_write.so和libxlsxio_read.io即为目标文件
|
||||
BIN
platform/src/3rd/src_package/xlsxio/unzip101e.zip
Normal file
BIN
platform/src/3rd/src_package/xlsxio/unzip101e.zip
Normal file
Binary file not shown.
BIN
platform/src/3rd/src_package/xlsxio/xlsxio-master.zip
Normal file
BIN
platform/src/3rd/src_package/xlsxio/xlsxio-master.zip
Normal file
Binary file not shown.
32
platform/src/3rd/src_package/zlib/ReadMe.txt
Normal file
32
platform/src/3rd/src_package/zlib/ReadMe.txt
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
writen by yikenan,2018-10-24
|
||||
|
||||
CentOS 7:
|
||||
其configure脚本没有提供LDFLAGS参数,且zlib库只依赖c运行库,所以无需设置rpath
|
||||
|
||||
./configure -prefix=/opt/zlib
|
||||
gmake
|
||||
gmake install
|
||||
|
||||
拷贝install路径下的lib目录下的动态库至platform下的对应系统目录
|
||||
拷贝install路径下的include目录下的文件到ISCS_HOME/src/3rd/include目录
|
||||
|
||||
configure报告的信息如下:
|
||||
Checking for gcc...
|
||||
Checking for shared library support...
|
||||
Building shared library libz.so.1.2.11 with gcc.
|
||||
Checking for size_t... Yes.
|
||||
Checking for off64_t... Yes.
|
||||
Checking for fseeko... Yes.
|
||||
Checking for strerror... Yes.
|
||||
Checking for unistd.h... Yes.
|
||||
Checking for stdarg.h... Yes.
|
||||
Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf().
|
||||
Checking for vsnprintf() in stdio.h... Yes.
|
||||
Checking for return value of vsnprintf()... Yes.
|
||||
Checking for attribute(visibility) support... Yes.
|
||||
|
||||
|
||||
Windows:
|
||||
使用contrib\vstudio下的VS工程编译
|
||||
|
||||
BIN
platform/src/3rd/src_package/zlib/zlib-1.2.11.zip
Normal file
BIN
platform/src/3rd/src_package/zlib/zlib-1.2.11.zip
Normal file
Binary file not shown.
@ -0,0 +1,240 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsCardMng.cpp
|
||||
* @brief 人脸相关接口,放在 CAcsDeviceApiImpl 中太长,拆分出来
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "hikvision/HCNetSDK.h"
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
|
||||
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
|
||||
#include "CAcsDeviceApiImpl.h"
|
||||
#include "CAcsCardMng.h"
|
||||
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
CAcsCardMng::CAcsCardMng(CAcsDeviceApiImpl *pParent)
|
||||
: m_nReSendCnt(0), m_nCfgHandle(-1), m_pParent(pParent)
|
||||
{
|
||||
//< todo
|
||||
}
|
||||
|
||||
CAcsCardMng::~CAcsCardMng()
|
||||
{
|
||||
//< todo
|
||||
}
|
||||
|
||||
/******************************************************************************//**
|
||||
* @brief 分割线,下发卡
|
||||
**********************************************************************************/
|
||||
|
||||
|
||||
bool CAcsCardMng::setCardCfgToDevice()
|
||||
{
|
||||
NET_DVR_CARD_CFG_COND struCond;
|
||||
memset(&struCond, 0, sizeof(struCond));
|
||||
struCond.dwSize = sizeof(struCond);
|
||||
struCond.dwCardNum = (DWORD) (m_pParent->m_pListUserInfo->size());
|
||||
|
||||
struCond.byCheckCardNo = 1; //< 设备是否进行卡号校验
|
||||
struCond.wLocalControllerID = 0; //< 0代表是门禁主机
|
||||
|
||||
m_nCfgHandle = NET_DVR_StartRemoteConfig(m_pParent->m_nUserID, NET_DVR_SET_CARD_CFG_V50, &struCond,
|
||||
sizeof(struCond),
|
||||
setCardCfgToDeviceCallBack, this);
|
||||
if (m_nCfgHandle < 0)
|
||||
{
|
||||
LOGERROR("NET_DVR_SET_CARD_CFG_V50 failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
//发送第一张卡, 失败关闭连接
|
||||
if (!sendFirstCard())
|
||||
{
|
||||
LOGERROR("setCardCfgToDevice(): 下发首卡失败,返回失败!");
|
||||
|
||||
//< 上一级负责,这里注释掉
|
||||
//m_pParent->stopRemoteConfig_inThread();
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 后面的事情交给回调函数
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAcsCardMng::setCardCfgToDeviceCallBack(DWORD dwType, void *lpBuffer, DWORD dwBufLen, void *pCaller)
|
||||
{
|
||||
(void) dwBufLen;
|
||||
|
||||
if (nullptr == pCaller)
|
||||
{
|
||||
LOGERROR("setCardCfgToDeviceCallBack(): nullptr == pCaller");
|
||||
return;
|
||||
}
|
||||
|
||||
CAcsCardMng *pThis = (CAcsCardMng *) pCaller;
|
||||
|
||||
if (dwType != NET_SDK_CALLBACK_TYPE_STATUS)
|
||||
{
|
||||
LOGERROR("setCardCfgToDeviceCallBack(): 非预期的 dwType = %u", dwType);
|
||||
pThis->onSetCardCfgFinish(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const DWORD dwStatus = *(DWORD *) lpBuffer;
|
||||
|
||||
switch (dwStatus)
|
||||
{
|
||||
case NET_SDK_CALLBACK_STATUS_PROCESSING:
|
||||
{
|
||||
//< lpBuffer:4字节状态 + 32字节卡号
|
||||
char szCardNumber[ACS_CARD_NO_LEN + 1] = "\0";
|
||||
strncpy(szCardNumber, (char *) (lpBuffer) + 4, ACS_CARD_NO_LEN);
|
||||
LOGINFO("setCardCfgToDeviceCallBack(): 下发卡成功,卡号:%s", szCardNumber);
|
||||
|
||||
//< 设置结果为成功
|
||||
pThis->m_itCurrentUser->m_bSetCarSuccess = true;
|
||||
|
||||
pThis->sendNextCard();
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_STATUS_FAILED:
|
||||
{
|
||||
//< lpBuffer:4字节状态 + 4字节错误码 + 32字节卡号
|
||||
char szCardNumber[ACS_CARD_NO_LEN + 1] = "\0";
|
||||
DWORD dwErrCode = *((DWORD *) lpBuffer + 1);
|
||||
strncpy(szCardNumber, (char *) (lpBuffer) + 8, ACS_CARD_NO_LEN);
|
||||
LOGERROR("setCardCfgToDeviceCallBack(): Err: %u, CardNo: %s", dwErrCode, szCardNumber);
|
||||
|
||||
if (!pThis->reSendLastCard())
|
||||
{
|
||||
if (!pThis->sendNextCard())
|
||||
pThis->onSetCardCfgFinish(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_STATUS_SUCCESS:
|
||||
{
|
||||
LOGINFO("setCardCfgToDeviceCallBack(): SUCCESS");
|
||||
pThis->onSetCardCfgFinish(true);
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_STATUS_EXCEPTION:
|
||||
{
|
||||
LOGERROR("setCardCfgToDeviceCallBack(): EXCEPTION");
|
||||
pThis->onSetCardCfgFinish(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LOGERROR("setCardCfgToDeviceCallBack(): 非预期类型,dwStatus = %u", dwStatus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CAcsCardMng::sendCardCfg()
|
||||
{
|
||||
NET_DVR_CARD_CFG_V50 struCardCfg;
|
||||
memset(&struCardCfg, 0, sizeof(struCardCfg));
|
||||
struCardCfg.dwSize = sizeof(struCardCfg);
|
||||
|
||||
char szCardNo[128];
|
||||
sprintf(szCardNo, "%d", m_itCurrentUser->m_nId);
|
||||
strncpy((char *) struCardCfg.byCardNo, szCardNo, sizeof(struCardCfg.byCardNo) - 1);
|
||||
|
||||
struCardCfg.dwModifyParamType |= CARD_PARAM_CARD_VALID;
|
||||
struCardCfg.byCardValid = 1;
|
||||
|
||||
struCardCfg.dwModifyParamType |= CARD_PARAM_CARD_TYPE;
|
||||
struCardCfg.byCardType = 1;
|
||||
|
||||
struCardCfg.dwModifyParamType |= CARD_PARAM_DOOR_RIGHT;
|
||||
struCardCfg.byDoorRight[0] = 1;
|
||||
|
||||
struCardCfg.dwModifyParamType |= CARD_PARAM_RIGHT_PLAN;
|
||||
struCardCfg.wCardRightPlan[0][0] = 1;
|
||||
|
||||
struCardCfg.dwModifyParamType |= CARD_PARAM_EMPLOYEE_NO;
|
||||
struCardCfg.dwEmployeeNo = m_itCurrentUser->m_nId;
|
||||
|
||||
struCardCfg.dwModifyParamType |= CARD_PARAM_NAME;
|
||||
strncpy((char *) struCardCfg.byName, m_itCurrentUser->m_strName.c_str(), sizeof(struCardCfg.byName) - 1);
|
||||
|
||||
if (!NET_DVR_SendRemoteConfig(m_nCfgHandle, ENUM_ACS_SEND_DATA,
|
||||
(char *) &struCardCfg, sizeof(struCardCfg)))
|
||||
{
|
||||
LOGERROR("ENUM_ACS_SEND_DATA failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAcsCardMng::sendFirstCard()
|
||||
{
|
||||
m_itCurrentUser = m_pParent->m_pListUserInfo->begin();
|
||||
if (m_itCurrentUser == m_pParent->m_pListUserInfo->end())
|
||||
{
|
||||
LOGERROR("sendFirstCard(): m_itCurrentUser == m_pListUserInfo->cend(),非预期,检查程序!");
|
||||
return false;
|
||||
}
|
||||
m_nReSendCnt = 0;
|
||||
|
||||
return sendCardCfg();
|
||||
}
|
||||
|
||||
bool CAcsCardMng::reSendLastCard()
|
||||
{
|
||||
if (m_pParent->m_pListUserInfo->end() == m_itCurrentUser)
|
||||
return true;
|
||||
|
||||
LOGDEBUG("reSendLastCard(): m_nReSendCnt = %d", m_nReSendCnt);
|
||||
m_nReSendCnt++;
|
||||
if (m_nReSendCnt >= 5)
|
||||
return false;
|
||||
|
||||
return sendCardCfg();
|
||||
}
|
||||
|
||||
bool CAcsCardMng::sendNextCard()
|
||||
{
|
||||
if (m_itCurrentUser == m_pParent->m_pListUserInfo->end())
|
||||
return true;
|
||||
|
||||
++m_itCurrentUser;
|
||||
if (m_itCurrentUser == m_pParent->m_pListUserInfo->end())
|
||||
return true;
|
||||
|
||||
return sendCardCfg();
|
||||
}
|
||||
|
||||
void CAcsCardMng::onSetCardCfgFinish(bool bSuccess)
|
||||
{
|
||||
if (!bSuccess)
|
||||
{
|
||||
m_pParent->m_pParent->handleSetUserInfoResult(*(m_pParent->m_pListUserInfo), m_pParent->m_pCfgUserData);
|
||||
m_pParent->stopRemoteConfig();
|
||||
return;
|
||||
}
|
||||
|
||||
//< 启动下发指纹
|
||||
if (!(m_pParent->m_objFpMng.setFingerprintCfgToDevice()))
|
||||
{
|
||||
m_pParent->m_pParent->handleSetUserInfoResult(*(m_pParent->m_pListUserInfo), m_pParent->m_pCfgUserData);
|
||||
m_pParent->stopRemoteConfig();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,58 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsCardMng.h
|
||||
* @brief 卡相关接口,放在 CAcsDeviceApiImpl 中太长,拆分出来
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "app_bio_identify/acs_device_api/AcsDeviceApiCommon.h"
|
||||
|
||||
#if (defined(_WIN32))
|
||||
typedef unsigned long DWORD;
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
typedef unsigned int DWORD;
|
||||
#endif
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
class CAcsDeviceApiImpl;
|
||||
|
||||
class CAcsCardMng
|
||||
{
|
||||
friend class CAcsDeviceApiImpl;
|
||||
|
||||
public:
|
||||
CAcsCardMng(CAcsDeviceApiImpl *pParent);
|
||||
~CAcsCardMng();
|
||||
|
||||
//< 设置卡参数到设备
|
||||
bool setCardCfgToDevice();
|
||||
|
||||
private:
|
||||
|
||||
//< 设置卡参数到设备
|
||||
static void setCardCfgToDeviceCallBack(DWORD dwType, void *lpBuffer, DWORD dwBufLen, void *pCaller);
|
||||
bool sendCardCfg();
|
||||
bool sendFirstCard();
|
||||
bool reSendLastCard();
|
||||
bool sendNextCard();
|
||||
void onSetCardCfgFinish(bool bSuccess);
|
||||
|
||||
private:
|
||||
unsigned char m_nReSendCnt; //< 重发计数
|
||||
|
||||
//< 注意:任何时候都应该只有一个设置操作在执行
|
||||
long m_nCfgHandle; //< 当前设置操作的句柄
|
||||
|
||||
CAcsDeviceApiImpl *const m_pParent;
|
||||
|
||||
std::list<CUserInfo>::iterator m_itCurrentUser; //< 当前待下发的用户
|
||||
|
||||
};
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,117 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsDeviceApi.cpp
|
||||
* @brief 门禁设备(Access Control System Device)接口类
|
||||
* 使用门禁设备(海康威视)的人脸、指纹识别功能作为我们系统的认证方式
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
|
||||
#include "CAcsDeviceApiImpl.h"
|
||||
#include "CAcsDeviceApiImplFactory.h"
|
||||
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
CAcsDeviceApi::CAcsDeviceApi() :
|
||||
m_pImpl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
CAcsDeviceApi::~CAcsDeviceApi()
|
||||
{
|
||||
CAcsDeviceApiImplFactory::destoryAcsDeviceApiImpl(&m_pImpl);
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::initImpl()
|
||||
{
|
||||
if (nullptr != m_pImpl)
|
||||
return true;
|
||||
|
||||
m_pImpl = CAcsDeviceApiImplFactory::newAcsDeviceApiImpl(this);
|
||||
if (nullptr == m_pImpl)
|
||||
{
|
||||
LOGERROR("initImpl(): failed !");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::logInToDevice(const char *szIP, int nPort, const char *szUser, const char *szPwd)
|
||||
{
|
||||
if (!initImpl())
|
||||
return false;
|
||||
|
||||
return m_pImpl->logInToDevice(szIP, nPort, szUser, szPwd);
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::isLoggedIn() const
|
||||
{
|
||||
if (nullptr == m_pImpl)
|
||||
return false;
|
||||
|
||||
return m_pImpl->isLoggedIn();
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::logOutFromDevice(bool bForce)
|
||||
{
|
||||
if (!initImpl())
|
||||
return false;
|
||||
|
||||
return m_pImpl->logOutFromDevice(bForce);
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::isIdle() const
|
||||
{
|
||||
if (nullptr == m_pImpl)
|
||||
return true;
|
||||
|
||||
return m_pImpl->isIdle();
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::captureFingerprintInfo(void *pUserData)
|
||||
{
|
||||
if (!initImpl())
|
||||
return false;
|
||||
|
||||
return m_pImpl->captureFingerprintInfo(pUserData);
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::captureFaceInfo(void *pUserData)
|
||||
{
|
||||
if (!initImpl())
|
||||
return false;
|
||||
|
||||
return m_pImpl->captureFaceInfo(pUserData);
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::setUserInfoToDevice(const std::list<CUserInfo> &listUserInfo, void *pUserData)
|
||||
{
|
||||
if (!initImpl())
|
||||
return false;
|
||||
|
||||
return m_pImpl->setUserInfoToDevice(listUserInfo, pUserData);
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::enableIdentification(bool bEnable)
|
||||
{
|
||||
if (!initImpl())
|
||||
return false;
|
||||
|
||||
return m_pImpl->enableIdentification(bEnable);
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::enableListenEvents(bool bEnable)
|
||||
{
|
||||
if (!initImpl())
|
||||
return false;
|
||||
|
||||
return m_pImpl->enableListenEvents(bEnable);
|
||||
}
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,77 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsDeviceApi.cpp
|
||||
* @brief 门禁设备(Access Control System Device)接口类
|
||||
* 使用门禁设备(海康威视)的人脸、指纹识别功能作为我们系统的认证方式
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
|
||||
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
CAcsDeviceApi::CAcsDeviceApi() :
|
||||
m_pImpl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
CAcsDeviceApi::~CAcsDeviceApi()
|
||||
{
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::initImpl()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::logInToDevice(const char * /*szIP*/, int /*nPort*/, const char * /*szUser*/, const char * /*szPwd*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::isLoggedIn() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::logOutFromDevice(bool /*bForce*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::isIdle() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::captureFingerprintInfo(void * /*pUserData*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::captureFaceInfo(void * /*pUserData*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::setUserInfoToDevice(const std::list<CUserInfo> & /*listUserInfo*/, void * /*pUserData*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::enableIdentification(bool /*bEnable*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApi::enableListenEvents(bool /*bEnable*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,466 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsDeviceApiImpl.cpp
|
||||
* @brief 门禁设备(Access Control System Device)接口类实现
|
||||
* 使用门禁设备(海康威视)的人脸、指纹识别功能作为我们系统的认证方式
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
|
||||
#include "hikvision/HCNetSDK.h"
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
|
||||
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
|
||||
#include "CAcsDeviceApiImpl.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
CAcsDeviceApiImpl::CAcsDeviceApiImpl(CAcsDeviceApi *pParent) :
|
||||
m_nUserID(-1), m_nAlarmHandle(-1), m_pParent(pParent), m_pCfgUserData(nullptr), m_pListUserInfo(nullptr),
|
||||
m_objCardMng(this), m_objFaceMng(this), m_objFpMng(this)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CAcsDeviceApiImpl::~CAcsDeviceApiImpl()
|
||||
{
|
||||
logOutFromDevice(true);
|
||||
|
||||
delete m_pListUserInfo;
|
||||
m_pListUserInfo = nullptr;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::logInToDevice(const char *szIP, int nPort, const char *szUser, const char *szPwd)
|
||||
{
|
||||
if (m_nUserID >= 0)
|
||||
{
|
||||
LOGERROR("logInToDevice(): 已登录,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
NET_DVR_USER_LOGIN_INFO struLoginInfo;
|
||||
memset(&struLoginInfo, 0, sizeof(struLoginInfo));
|
||||
struLoginInfo.wPort = nPort;
|
||||
strncpy(struLoginInfo.sDeviceAddress, szIP, NET_DVR_DEV_ADDRESS_MAX_LEN - 1);
|
||||
strncpy(struLoginInfo.sUserName, szUser, NET_DVR_LOGIN_USERNAME_MAX_LEN - 1);
|
||||
strncpy(struLoginInfo.sPassword, szPwd, NET_DVR_LOGIN_PASSWD_MAX_LEN - 1);
|
||||
|
||||
NET_DVR_DEVICEINFO_V40 struDeviceInfoV40;
|
||||
m_nUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);
|
||||
if (m_nUserID < 0)
|
||||
{
|
||||
LOGERROR("NET_DVR_Login_V40 failed, ErrCode = %d , ErrStr = %s", NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::isLoggedIn() const
|
||||
{
|
||||
return m_nUserID >= 0;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::logOutFromDevice(bool bForce)
|
||||
{
|
||||
stopRemoteConfig_inThread();
|
||||
|
||||
if (m_nUserID >= 0)
|
||||
{
|
||||
//< 停止监听事件
|
||||
enableListenEvents(false);
|
||||
|
||||
if (FALSE == NET_DVR_Logout(m_nUserID))
|
||||
{
|
||||
LOGERROR("NET_DVR_Logout failed, ErrCode = %d , ErrStr = %s", NET_DVR_GetLastError(),
|
||||
NET_DVR_GetErrorMsg());
|
||||
if (!bForce)
|
||||
return false;
|
||||
}
|
||||
m_nUserID = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::isIdle() const
|
||||
{
|
||||
return m_objCardMng.m_nCfgHandle < 0
|
||||
&& m_objFaceMng.m_nCfgHandle < 0
|
||||
&& m_objFpMng.m_nCfgHandle < 0;
|
||||
}
|
||||
|
||||
static inline void _stopRemoteCfgHandle(long *pCfgHandle)
|
||||
{
|
||||
if (*pCfgHandle >= 0)
|
||||
{
|
||||
if (FALSE == NET_DVR_StopRemoteConfig(*pCfgHandle))
|
||||
{
|
||||
LOGERROR("NET_DVR_StopRemoteConfig failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
}
|
||||
*pCfgHandle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void CAcsDeviceApiImpl::stopRemoteConfig_inThread()
|
||||
{
|
||||
//< 最好注意一下顺序,先调用的后释放
|
||||
_stopRemoteCfgHandle(&(m_objFaceMng.m_nCfgHandle));
|
||||
_stopRemoteCfgHandle(&(m_objFpMng.m_nCfgHandle));
|
||||
_stopRemoteCfgHandle(&(m_objCardMng.m_nCfgHandle));
|
||||
|
||||
delete m_pListUserInfo;
|
||||
m_pListUserInfo = nullptr;
|
||||
|
||||
m_pCfgUserData = nullptr;
|
||||
}
|
||||
|
||||
void CAcsDeviceApiImpl::stopRemoteConfig()
|
||||
{
|
||||
std::thread thredTemp = std::thread(&CAcsDeviceApiImpl::stopRemoteConfig_inThread, this);
|
||||
thredTemp.detach();
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::captureFingerprintInfo(void *pUserData)
|
||||
{
|
||||
if (m_nUserID < 0)
|
||||
{
|
||||
LOGERROR("captureFingerprintInfo(): 未登录,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isIdle())
|
||||
{
|
||||
LOGERROR("captureFingerprintInfo(): 有操作正在执行,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pCfgUserData = pUserData;;
|
||||
return m_objFpMng.captureFingerprintInfo();
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::captureFaceInfo(void *pUserData)
|
||||
{
|
||||
if (m_nUserID < 0)
|
||||
{
|
||||
LOGERROR("captureFaceInfo(): 未登录,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isIdle())
|
||||
{
|
||||
LOGERROR("captureFaceInfo(): 有操作正在执行,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pCfgUserData = pUserData;;
|
||||
return m_objFaceMng.captureFaceInfo();
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::setUserInfoToDevice(const std::list<CUserInfo> &listUserInfo, void *pUserData)
|
||||
{
|
||||
if (m_nUserID < 0)
|
||||
{
|
||||
LOGERROR("setUserInfoToDevice(): 未登录,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isIdle())
|
||||
{
|
||||
LOGERROR("setUserInfoToDevice(): 有操作正在执行,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (listUserInfo.empty())
|
||||
{
|
||||
LOGWARN("setUserInfoToDevice(): 待下发用户列表为空,返回成功!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!clearDeviceParam())
|
||||
{
|
||||
LOGERROR("setUserInfoToDevice(): 清空设备配置失败,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!setRightPlanToDevice())
|
||||
{
|
||||
LOGERROR("setUserInfoToDevice(): 设置权限计划到设备失败,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
delete m_pListUserInfo;
|
||||
m_pListUserInfo = new std::list<CUserInfo>(listUserInfo);
|
||||
//< 先将结果全部设为false
|
||||
for (std::list<kbd_application::CUserInfo>::iterator itUser = m_pListUserInfo->begin();
|
||||
m_pListUserInfo->end() != itUser; ++itUser)
|
||||
{
|
||||
itUser->m_bSetCarSuccess = false;
|
||||
itUser->m_bSetFaceSuccess = false;
|
||||
|
||||
std::list<kbd_application::CFingerprintInfo> &listFp = itUser->m_listFingerprint;
|
||||
for (std::list<kbd_application::CFingerprintInfo>::iterator itFp = listFp.begin();
|
||||
listFp.end() != itFp; ++itFp)
|
||||
{
|
||||
itFp->m_bSetSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
m_pCfgUserData = pUserData;
|
||||
|
||||
if (!m_objCardMng.setCardCfgToDevice())
|
||||
{
|
||||
LOGERROR("setUserInfoToDevice(): 设置卡参数到设备失败,返回失败!");
|
||||
|
||||
stopRemoteConfig_inThread();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 启动成功,之后交给回调函数处理
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::clearDeviceParam()
|
||||
{
|
||||
NET_DVR_ACS_PARAM_TYPE struAcsParam;
|
||||
memset(&struAcsParam, 0, sizeof(struAcsParam));
|
||||
struAcsParam.dwSize = sizeof(struAcsParam);
|
||||
|
||||
struAcsParam.dwParamType |= ACS_PARAM_DOOR_STATUS_WEEK_PLAN;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_VERIFY_WEEK_PALN;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_CARD_RIGHT_WEEK_PLAN;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_DOOR_STATUS_HOLIDAY_PLAN;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_VERIFY_HOLIDAY_PALN;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_CARD_RIGHT_HOLIDAY_PLAN;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_DOOR_STATUS_HOLIDAY_GROUP;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_VERIFY_HOLIDAY_GROUP;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_CARD_RIGHT_HOLIDAY_GROUP;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_DOOR_STATUS_PLAN_TEMPLATE;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_VERIFY_PALN_TEMPLATE;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_CARD_RIGHT_PALN_TEMPLATE;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_CARD;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_GROUP;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_ANTI_SNEAK_CFG;
|
||||
struAcsParam.dwParamType |= ACS_PAPAM_EVENT_CARD_LINKAGE;
|
||||
struAcsParam.dwParamType |= ACS_PAPAM_CARD_PASSWD_CFG;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_PERSON_STATISTICS_CFG;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_BLACK_LIST_PICTURE;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_ID_BLACK_LIST;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_EXAM_INFO;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_EXAMINEE_INFO;
|
||||
struAcsParam.dwParamType |= ACS_PARAM_FAILED_FACE_INFO;
|
||||
|
||||
//< 就地控制器序号[1,255],0代表门禁主机
|
||||
struAcsParam.wLocalControllerID = 0;
|
||||
|
||||
if (FALSE == NET_DVR_RemoteControl(m_nUserID, NET_DVR_CLEAR_ACS_PARAM, &struAcsParam, sizeof(struAcsParam)))
|
||||
{
|
||||
LOGERROR("NET_DVR_CLEAR_ACS_PARAM failed, ErrCode = %d , ErrStr = %s", NET_DVR_GetLastError(),
|
||||
NET_DVR_GetErrorMsg());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::setRightPlanToDevice()
|
||||
{
|
||||
DWORD dwReturned = 0;
|
||||
|
||||
//< 先下发周计划
|
||||
{
|
||||
NET_DVR_WEEK_PLAN_COND struPlanCond;
|
||||
memset(&struPlanCond, 0, sizeof(struPlanCond));
|
||||
struPlanCond.dwSize = sizeof(struPlanCond);
|
||||
struPlanCond.dwWeekPlanNumber = 1; //< 周计划编号,从1开始
|
||||
struPlanCond.wLocalControllerID = 0; //< 就地控制器序号[1,64],0表示门禁主机
|
||||
|
||||
NET_DVR_WEEK_PLAN_CFG struPlanCfg;
|
||||
memset(&struPlanCfg, 0, sizeof(struPlanCfg));
|
||||
struPlanCfg.dwSize = sizeof(struPlanCfg);
|
||||
struPlanCfg.byEnable = 1;
|
||||
for (int i = 0; i < MAX_DAYS; ++i)
|
||||
{
|
||||
NET_DVR_SINGLE_PLAN_SEGMENT &struOnePlanCfg = struPlanCfg.struPlanCfg[i][0];
|
||||
struOnePlanCfg.byEnable = 1;
|
||||
//struOnePlanCfg.byDoorStatus = 0;
|
||||
|
||||
//< 验证方式:
|
||||
// 0- 无效,1- 休眠,2- 刷卡+密码(读卡器验证方式计划使用),3- 刷卡(读卡器验证方式计划使用),
|
||||
// 4- 刷卡或密码(读卡器验证方式计划使用),5- 指纹,6- 指纹+密码,7- 指纹或刷卡,8- 指纹+刷卡,
|
||||
// 9- 指纹+刷卡+密码(无先后顺序),10- 人脸或指纹或刷卡或密码,11- 人脸+指纹,12- 人脸+密码,
|
||||
// 13- 人脸+刷卡,14- 人脸,15- 工号+密码,16- 指纹或密码,17- 工号+指纹,18- 工号+指纹+密码,
|
||||
// 19- 人脸+指纹+刷卡,20- 人脸+密码+指纹,21- 工号+人脸,22- 人脸或人脸+刷卡,23-指纹或人脸,
|
||||
// 24-刷卡或人脸或密码, 25-刷卡或人脸,26-刷卡或人脸或指纹
|
||||
struOnePlanCfg.byVerifyMode = 23;
|
||||
|
||||
//< 即全天有效
|
||||
struOnePlanCfg.struTimeSegment.struBeginTime.byHour = 0;
|
||||
struOnePlanCfg.struTimeSegment.struBeginTime.byMinute = 0;
|
||||
struOnePlanCfg.struTimeSegment.struBeginTime.bySecond = 0;
|
||||
|
||||
struOnePlanCfg.struTimeSegment.struEndTime.byHour = 24;
|
||||
struOnePlanCfg.struTimeSegment.struEndTime.byMinute = 0;
|
||||
struOnePlanCfg.struTimeSegment.struEndTime.bySecond = 0;
|
||||
}
|
||||
|
||||
|
||||
if (FALSE == NET_DVR_SetDeviceConfig(m_nUserID, NET_DVR_SET_CARD_RIGHT_WEEK_PLAN_V50,
|
||||
1, &struPlanCond, sizeof(struPlanCond),
|
||||
&dwReturned, &struPlanCfg, sizeof(struPlanCfg)))
|
||||
{
|
||||
LOGERROR("NET_DVR_SET_CARD_RIGHT_WEEK_PLAN_V50 failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//< 再下发计划模板
|
||||
{
|
||||
NET_DVR_PLAN_TEMPLATE_COND struTemplateCond;
|
||||
memset(&struTemplateCond, 0, sizeof(struTemplateCond));
|
||||
struTemplateCond.dwSize = sizeof(struTemplateCond);
|
||||
struTemplateCond.dwPlanTemplateNumber = 1; //< 计划模板编号,从1开始
|
||||
struTemplateCond.wLocalControllerID = 0; //< 就地控制器序号[1,64],0表示门禁主机
|
||||
|
||||
NET_DVR_PLAN_TEMPLATE struTemplateCfg;
|
||||
memset(&struTemplateCfg, 0, sizeof(struTemplateCfg));
|
||||
struTemplateCfg.dwSize = sizeof(struTemplateCfg);
|
||||
struTemplateCfg.byEnable = 1;
|
||||
|
||||
strncpy((char *) struTemplateCfg.byTemplateName, "iscs6000", sizeof(struTemplateCfg.byTemplateName));
|
||||
struTemplateCfg.dwWeekPlanNo = 1; //< 与上面的周计划编号一致
|
||||
//struTemplateCfg.dwHolidayGroupNo[0] = 0; //< 不使用假日模板
|
||||
|
||||
if (FALSE == NET_DVR_SetDeviceConfig(m_nUserID, NET_DVR_SET_CARD_RIGHT_PLAN_TEMPLATE_V50,
|
||||
1, &struTemplateCond, sizeof(struTemplateCond),
|
||||
&dwReturned, &struTemplateCfg, sizeof(struTemplateCfg)))
|
||||
{
|
||||
LOGERROR("NET_DVR_SET_CARD_RIGHT_PLAN_TEMPLATE_V50 failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::enableIdentification(bool bEnable)
|
||||
{
|
||||
//< 即设置读卡器使能
|
||||
|
||||
if (m_nUserID < 0)
|
||||
{
|
||||
LOGERROR("enableIdentification(): 未登录,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isIdle())
|
||||
{
|
||||
LOGERROR("enableIdentification(): 有操作正在执行,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
NET_DVR_CARD_READER_CFG_V50 struReaderCfg;
|
||||
memset(&struReaderCfg, 0, sizeof(struReaderCfg));
|
||||
DWORD dwRet;
|
||||
|
||||
//< 获取读卡器参数
|
||||
//< 第三个参数 lChannel 表示读卡器编号,经测试应该是从1开始
|
||||
//< 下发指纹、人脸代码中的读卡器数组下标从0开始
|
||||
if (FALSE == NET_DVR_GetDVRConfig(m_nUserID, NET_DVR_GET_CARD_READER_CFG_V50, 1,
|
||||
&struReaderCfg, sizeof(struReaderCfg), &dwRet))
|
||||
{
|
||||
LOGERROR("NET_DVR_GET_CARD_READER_CFG_V50 failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
const BYTE byEnable_New = bEnable ? 1 : 0;
|
||||
if (byEnable_New == struReaderCfg.byEnable)
|
||||
return true; //< 无需下发
|
||||
|
||||
struReaderCfg.byEnable = byEnable_New;
|
||||
|
||||
//< 下发读卡器参数
|
||||
if (FALSE == NET_DVR_SetDVRConfig(m_nUserID, NET_DVR_SET_CARD_READER_CFG_V50, 1,
|
||||
&struReaderCfg, sizeof(struReaderCfg)))
|
||||
{
|
||||
LOGERROR("NET_DVR_SET_CARD_READER_CFG_V50 failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImpl::enableListenEvents(bool bEnable)
|
||||
{
|
||||
if (m_nUserID < 0)
|
||||
{
|
||||
LOGERROR("enableListenEvents(): 未登录,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isIdle())
|
||||
{
|
||||
LOGERROR("enableListenEvents(): 有操作正在执行,返回失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bEnable)
|
||||
{
|
||||
if (m_nAlarmHandle >= 0)
|
||||
{
|
||||
LOGINFO("enableListenEvents(): 已开启,无需重复开启");
|
||||
return true;
|
||||
}
|
||||
|
||||
NET_DVR_SETUPALARM_PARAM_V50 struParam;
|
||||
memset(&struParam, 0, sizeof(struParam));
|
||||
struParam.dwSize = sizeof(struParam);
|
||||
//< 0-客户端布防(支持实时事件+离线事件上传);1-实时布防(仅支持实时事件上传,不支持离线事件上传)
|
||||
struParam.byDeployType = 1;
|
||||
|
||||
m_nAlarmHandle = NET_DVR_SetupAlarmChan_V50(m_nUserID, &struParam, NULL, 0);
|
||||
|
||||
if (m_nAlarmHandle < 0)
|
||||
{
|
||||
LOGERROR("NET_DVR_SetupAlarmChan_V50 failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_nAlarmHandle < 0)
|
||||
{
|
||||
LOGINFO("enableListenEvents(): 已取消,无需重复取消");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (FALSE == NET_DVR_CloseAlarmChan_V30(m_nAlarmHandle))
|
||||
{
|
||||
LOGERROR("NET_DVR_CloseAlarmChan_V30 failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nAlarmHandle = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,85 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsDeviceApiImpl.h
|
||||
* @brief 门禁设备(Access Control System Device)接口类实现
|
||||
* 使用门禁设备(海康威视)的人脸、指纹识别功能作为我们系统的认证方式
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CAcsCardMng.h"
|
||||
#include "CAcsFaceMng.h"
|
||||
#include "CAcsFingerprintMng.h"
|
||||
|
||||
#if (defined(_WIN32))
|
||||
typedef unsigned long DWORD;
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
typedef unsigned int DWORD;
|
||||
#endif
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
class CAcsDeviceApi;
|
||||
|
||||
class CAcsDeviceApiImpl
|
||||
{
|
||||
friend class CAcsDeviceApiImplFactory;
|
||||
friend class CAcsCardMng;
|
||||
friend class CAcsFaceMng;
|
||||
friend class CAcsFingerprintMng;
|
||||
|
||||
public:
|
||||
~CAcsDeviceApiImpl();
|
||||
|
||||
bool logInToDevice(const char *szIP, int nPort, const char *szUser, const char *szPwd);
|
||||
|
||||
bool isLoggedIn() const;
|
||||
|
||||
bool logOutFromDevice(bool bForce);
|
||||
|
||||
bool isIdle() const;
|
||||
|
||||
bool captureFingerprintInfo(void *pUserData);
|
||||
|
||||
bool captureFaceInfo(void *pUserData);
|
||||
|
||||
bool setUserInfoToDevice(const std::list<CUserInfo> &listUserInfo, void *pUserData);
|
||||
|
||||
bool enableIdentification(bool bEnable);
|
||||
|
||||
bool enableListenEvents(bool bEnable);
|
||||
|
||||
private:
|
||||
//< 只能通过 CAcsDeviceApiImplFactory 生产
|
||||
CAcsDeviceApiImpl(CAcsDeviceApi *pParent);
|
||||
|
||||
//< 直接在调用线程执行
|
||||
void stopRemoteConfig_inThread();
|
||||
|
||||
//< 会新建一个线程执行
|
||||
void stopRemoteConfig();
|
||||
|
||||
//< 清空设备配置
|
||||
bool clearDeviceParam();
|
||||
|
||||
//< 设置权限计划到设备
|
||||
bool setRightPlanToDevice();
|
||||
|
||||
private:
|
||||
long m_nUserID; //< 登录后SDK返回的ID
|
||||
long m_nAlarmHandle; //< 告警监听句柄
|
||||
|
||||
CAcsDeviceApi *const m_pParent;
|
||||
void *m_pCfgUserData; //< 当前设置操作的用户数据指针
|
||||
std::list<CUserInfo> *m_pListUserInfo; //< 当前待下发的用户信息
|
||||
|
||||
CAcsCardMng m_objCardMng;
|
||||
CAcsFaceMng m_objFaceMng;
|
||||
CAcsFingerprintMng m_objFpMng;
|
||||
};
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,297 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsDeviceApiImplFactory.cpp
|
||||
* @brief CAcsDeviceApiImpl类的工厂
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#include "boost/filesystem.hpp"
|
||||
#include "boost/lexical_cast.hpp"
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
#include "pub_utility_api/FileUtil.h"
|
||||
|
||||
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
|
||||
#include "CAcsDeviceApiImplFactory.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
static const char *cn_szSdkDir = "hikvision\\";
|
||||
static const char *cn_szHikvisionLogDir = "..\\..\\log\\hikvision\\";
|
||||
#else
|
||||
static const char *cn_szSdkDir = "hikvision/";
|
||||
static const char *cn_szHikvisionLogDir = "../../log/hikvision/";
|
||||
#endif
|
||||
|
||||
volatile bool CAcsDeviceApiImplFactory::m_bInited = false;
|
||||
boost::mutex CAcsDeviceApiImplFactory::m_mutexGlobal;
|
||||
std::set<CAcsDeviceApiImpl *> CAcsDeviceApiImplFactory::m_setInstance;
|
||||
|
||||
void CAcsDeviceApiImplFactory::exceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)
|
||||
{
|
||||
(void) pUser;
|
||||
LOGERROR("hikvision exceptionCallBack(): dwType = %lu, lUserID = %ld, lHandle = %ld",
|
||||
(unsigned long) dwType, (long) lUserID, (long) lHandle);
|
||||
}
|
||||
|
||||
void CAcsDeviceApiImplFactory::certVerifyResultCallBack(DWORD uiResult, NET_DVR_CETTIFICATE_INFO lpCertificateInfo,
|
||||
void *pUserData)
|
||||
{
|
||||
(void) uiResult;
|
||||
(void) lpCertificateInfo;
|
||||
(void) pUserData;
|
||||
}
|
||||
|
||||
void CAcsDeviceApiImplFactory::messageCallBack(LONG lCommand, NET_DVR_ALARMER *pAlarmer,
|
||||
char *pAlarmInfo, DWORD dwBufLen, void *pUser)
|
||||
{
|
||||
(void) dwBufLen;
|
||||
(void) pUser;
|
||||
|
||||
if (nullptr == pAlarmer)
|
||||
{
|
||||
LOGERROR("messageCallBack(): nullptr == pAlarmer,忽略!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == pAlarmer->byUserIDValid)
|
||||
{
|
||||
LOGINFO("messageCallBack(): 0 == pAlarmer->byUserIDValid,忽略!");
|
||||
return;
|
||||
}
|
||||
|
||||
//< 找订阅该告警的实例
|
||||
CAcsDeviceApiImpl *pInst = nullptr;
|
||||
{
|
||||
const long nUserID = pAlarmer->lUserID;
|
||||
|
||||
//< 加锁
|
||||
boost::mutex::scoped_lock locker(m_mutexGlobal);
|
||||
for (std::set<CAcsDeviceApiImpl *>::iterator it = m_setInstance.begin(); m_setInstance.end() != it; ++it)
|
||||
{
|
||||
if (nUserID == (*it)->m_nUserID)
|
||||
{
|
||||
pInst = (*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nullptr == pInst)
|
||||
{
|
||||
LOGERROR("messageCallBack(): 未找到实例,检查程序!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (COMM_ALARM_ACS == lCommand)
|
||||
{
|
||||
NET_DVR_ACS_ALARM_INFO *pAcsAlmInfo = (NET_DVR_ACS_ALARM_INFO *) pAlarmInfo;
|
||||
|
||||
bool bOtherEventType = true;
|
||||
|
||||
if (MAJOR_EVENT == pAcsAlmInfo->dwMajor)
|
||||
{
|
||||
switch (pAcsAlmInfo->dwMinor)
|
||||
{
|
||||
case MINOR_FINGERPRINT_COMPARE_PASS:
|
||||
case MINOR_FACE_VERIFY_PASS:
|
||||
{
|
||||
bOtherEventType = false;
|
||||
|
||||
int nCardNo = -1;
|
||||
try
|
||||
{
|
||||
nCardNo = boost::lexical_cast<int>(pAcsAlmInfo->struAcsEventInfo.byCardNo);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
LOGERROR("messageCallBack(): 卡号转int失败, byCardNo: %s , Err: %s",
|
||||
pAcsAlmInfo->struAcsEventInfo.byCardNo, e.what());
|
||||
nCardNo = -1;
|
||||
}
|
||||
|
||||
if (nCardNo > 0)
|
||||
{
|
||||
pInst->m_pParent->handleIdentificationEvent(true, nCardNo, pAcsAlmInfo->dwPicDataLen,
|
||||
pAcsAlmInfo->pPicData);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MINOR_FINGERPRINT_COMPARE_FAIL:
|
||||
case MINOR_FACE_VERIFY_FAIL:
|
||||
{
|
||||
bOtherEventType = false;
|
||||
|
||||
pInst->m_pParent->handleIdentificationEvent(false, -1, pAcsAlmInfo->dwPicDataLen,
|
||||
pAcsAlmInfo->pPicData);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bOtherEventType)
|
||||
{
|
||||
LOGINFO("\npAcsAlmInfo: dwMajor=%d , dwMinor=0x%X , dwPicDataLen=%d , byCardNo=%s\n",
|
||||
pAcsAlmInfo->dwMajor, pAcsAlmInfo->dwMinor, pAcsAlmInfo->dwPicDataLen,
|
||||
pAcsAlmInfo->struAcsEventInfo.byCardNo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGINFO("messageCallBack(): lCommand == 0x%X ,非ACS告警,忽略!", lCommand);
|
||||
}
|
||||
}
|
||||
|
||||
bool CAcsDeviceApiImplFactory::initGlobal()
|
||||
{
|
||||
if (m_bInited)
|
||||
return true;
|
||||
|
||||
const std::string strCurDir = kbd_public::CFileUtil::getCurModuleDir();
|
||||
if (strCurDir.empty())
|
||||
{
|
||||
LOGERROR("initGlobal(): 获取程序所在路径失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 设置SDK路径,当HCNetSDK库的路径同可执行程序工作目录不同时需要设置
|
||||
{
|
||||
boost::filesystem::path objSdkDir = strCurDir;
|
||||
objSdkDir /= cn_szSdkDir;
|
||||
|
||||
NET_DVR_LOCAL_SDK_PATH struSdkPath;
|
||||
memset(&struSdkPath, 0, sizeof(struSdkPath));
|
||||
strncpy(struSdkPath.sPath, objSdkDir.string().c_str(), sizeof(struSdkPath.sPath) - 1);
|
||||
|
||||
if (FALSE == NET_DVR_SetSDKInitCfg(NET_SDK_INIT_CFG_SDK_PATH, &struSdkPath))
|
||||
{
|
||||
LOGERROR("NET_DVR_SetSDKInitCfg failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (FALSE == NET_DVR_Init())
|
||||
{
|
||||
LOGERROR("NET_DVR_Init failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
|
||||
NET_DVR_Cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 设置海康SDK日志路径
|
||||
{
|
||||
boost::filesystem::path objLogDir = strCurDir;
|
||||
objLogDir /= cn_szHikvisionLogDir;
|
||||
|
||||
LOGINFO("hikvision SDK log path : %s", objLogDir.string().c_str());
|
||||
|
||||
if (FALSE == NET_DVR_SetLogToFile(3, (char *) objLogDir.string().c_str(), TRUE))
|
||||
{
|
||||
LOGERROR("NET_DVR_SetLogToFile failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
//< 设置CA证书路径,当前不使用,只是为了避免SDK不停输出“GetCAPath, Failed, Invalid pPath”日志
|
||||
{
|
||||
boost::filesystem::path objCaDir = strCurDir;
|
||||
objCaDir /= cn_szSdkDir;
|
||||
|
||||
NET_DVR_LOCAL_CERTIFICATION struCA;
|
||||
memset(&struCA, 0, sizeof(struCA));
|
||||
strncpy(struCA.szLoadPath, objCaDir.string().c_str(), sizeof(struCA.szLoadPath) - 1);
|
||||
struCA.fnCB = (fnCertVerifyResultCallBack) certVerifyResultCallBack;
|
||||
|
||||
NET_DVR_SetSDKLocalCfg(NET_SDK_LOCAL_CFG_CERTIFICATION, &struCA);
|
||||
}
|
||||
|
||||
//< 若不设置,SDK默认值为3秒
|
||||
NET_DVR_SetConnectTime(1000, 1);
|
||||
|
||||
//< 若不设置,SDK默认值为5秒
|
||||
NET_DVR_SetRecvTimeOut(2000);
|
||||
|
||||
//< 不调用该接口时,SDK默认启动预览、透明通道和布防的重连功能,重连时间间隔为5秒。
|
||||
//NET_DVR_SetReconnect(10000, true);
|
||||
|
||||
NET_DVR_SetExceptionCallBack_V30(0, NULL, exceptionCallBack, NULL);
|
||||
|
||||
//< 设备告警、事件回调函数
|
||||
NET_DVR_SetDVRMessageCallBack_V51(0, messageCallBack, NULL);
|
||||
|
||||
if (m_setInstance.size() > 0)
|
||||
{
|
||||
LOGERROR("initGlobal(): 实例集合非空,检查程序!");
|
||||
m_setInstance.clear();
|
||||
}
|
||||
|
||||
m_bInited = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAcsDeviceApiImplFactory::releaseGlobal()
|
||||
{
|
||||
LOGINFO("releaseGlobal()");
|
||||
|
||||
NET_DVR_Cleanup();
|
||||
m_bInited = false;
|
||||
}
|
||||
|
||||
CAcsDeviceApiImpl *CAcsDeviceApiImplFactory::newAcsDeviceApiImpl(CAcsDeviceApi *pParent)
|
||||
{
|
||||
if (nullptr == pParent)
|
||||
{
|
||||
LOGERROR("newAcsDeviceApiImpl(): nullptr == pParent");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//< 加锁,注意生命周期
|
||||
boost::mutex::scoped_lock locker(m_mutexGlobal);
|
||||
|
||||
if (!initGlobal())
|
||||
return nullptr;
|
||||
|
||||
CAcsDeviceApiImpl *pInst = new CAcsDeviceApiImpl(pParent);
|
||||
|
||||
if (!(m_setInstance.insert(pInst).second))
|
||||
{
|
||||
LOGERROR("newAcsDeviceApiImpl(): 存在重复的实例,检查程序!");
|
||||
}
|
||||
|
||||
return pInst;
|
||||
}
|
||||
|
||||
void CAcsDeviceApiImplFactory::destoryAcsDeviceApiImpl(CAcsDeviceApiImpl **ppObj)
|
||||
{
|
||||
if (nullptr == ppObj)
|
||||
{
|
||||
LOGERROR("destoryAcsDeviceApiImpl(): nullptr == ppObj");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nullptr == *ppObj)
|
||||
return;
|
||||
|
||||
boost::mutex::scoped_lock locker(m_mutexGlobal);
|
||||
|
||||
if (1 != m_setInstance.erase(*ppObj))
|
||||
{
|
||||
LOGERROR("destoryAcsDeviceApiImpl(): 实例未纳入管理,检查程序!");
|
||||
}
|
||||
|
||||
delete *ppObj;
|
||||
*ppObj = nullptr;
|
||||
|
||||
if (m_setInstance.empty())
|
||||
releaseGlobal();
|
||||
}
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,52 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsDeviceApiImplFactory.h
|
||||
* @brief CAcsDeviceApiImpl类的工厂
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "boost/thread/mutex.hpp"
|
||||
#include "hikvision/HCNetSDK.h"
|
||||
|
||||
#include "CAcsDeviceApiImpl.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
class CAcsDeviceApi;
|
||||
|
||||
class CAcsDeviceApiImplFactory
|
||||
{
|
||||
public:
|
||||
static CAcsDeviceApiImpl *newAcsDeviceApiImpl(CAcsDeviceApi *pParent);
|
||||
static void destoryAcsDeviceApiImpl(CAcsDeviceApiImpl **ppObj);
|
||||
|
||||
private:
|
||||
static bool initGlobal();
|
||||
static void releaseGlobal();
|
||||
|
||||
//< 回调函数
|
||||
static void exceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser);
|
||||
static void certVerifyResultCallBack(DWORD uiResult, NET_DVR_CETTIFICATE_INFO lpCertificateInfo, void *pUserData);
|
||||
static void messageCallBack(LONG lCommand, NET_DVR_ALARMER *pAlarmer,
|
||||
char *pAlarmInfo, DWORD dwBufLen, void *pUser);
|
||||
|
||||
private:
|
||||
//< 是否已经全局初始化
|
||||
static volatile bool m_bInited;
|
||||
|
||||
//< 保护全局资源的锁
|
||||
static boost::mutex m_mutexGlobal;
|
||||
|
||||
//< 实例集合
|
||||
static std::set<CAcsDeviceApiImpl *> m_setInstance;
|
||||
};
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,438 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsFaceMng.cpp
|
||||
* @brief 人脸相关接口,放在 CAcsDeviceApiImpl 中太长,拆分出来
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
|
||||
#include "hikvision/HCNetSDK.h"
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
|
||||
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
|
||||
#include "CAcsDeviceApiImpl.h"
|
||||
#include "CAcsFaceMng.h"
|
||||
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
CAcsFaceMng::CAcsFaceMng(CAcsDeviceApiImpl *pParent)
|
||||
: m_nReSendCnt(0), m_nCfgHandle(-1), m_pParent(pParent)
|
||||
{
|
||||
//< todo
|
||||
}
|
||||
|
||||
CAcsFaceMng::~CAcsFaceMng()
|
||||
{
|
||||
//< todo
|
||||
}
|
||||
|
||||
void CAcsFaceMng::captureFaceInfoCallBack(DWORD dwType, void *pRecvDataBuffer,
|
||||
DWORD dwBufSize, void *pCaller)
|
||||
{
|
||||
if (nullptr == pCaller)
|
||||
{
|
||||
LOGERROR("captureFaceInfoCallBack(): nullptr == pCaller");
|
||||
return;
|
||||
}
|
||||
|
||||
CAcsFaceMng *pThis = (CAcsFaceMng *) pCaller;
|
||||
|
||||
switch (dwType)
|
||||
{
|
||||
case NET_SDK_CALLBACK_TYPE_STATUS:
|
||||
{
|
||||
DWORD dwTemp = *((DWORD *) pRecvDataBuffer);
|
||||
if (dwTemp == NET_SDK_CALLBACK_STATUS_PROCESSING)
|
||||
{
|
||||
LOGINFO("captureFaceInfoCallBack(): NET_SDK_CALLBACK_STATUS_PROCESSING");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dwTemp == NET_SDK_CALLBACK_STATUS_SUCCESS)
|
||||
{
|
||||
LOGINFO("captureFaceInfoCallBack(): NET_SDK_CALLBACK_STATUS_SUCCESS");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR("captureFaceInfoCallBack(): dwTemp = %u", dwTemp);
|
||||
if (dwBufSize > 4)
|
||||
{
|
||||
LOGERROR("captureFaceInfoCallBack(): ErrCode = %d", *((DWORD *) pRecvDataBuffer + 1));
|
||||
}
|
||||
|
||||
pThis->m_pParent->m_pParent->handleFaceInfo(false, 0, nullptr,
|
||||
pThis->m_pParent->m_pCfgUserData);
|
||||
}
|
||||
|
||||
pThis->m_pParent->stopRemoteConfig();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_TYPE_PROGRESS:
|
||||
{
|
||||
LOGINFO("captureFaceInfoCallBack(): NET_SDK_CALLBACK_TYPE_PROGRESS");
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_TYPE_DATA:
|
||||
{
|
||||
if (sizeof(LPNET_DVR_CAPTURE_FACE_CFG) > dwBufSize)
|
||||
{
|
||||
LOGERROR("captureFaceInfoCallBack(): 数据长度不正确!");
|
||||
}
|
||||
|
||||
LPNET_DVR_CAPTURE_FACE_CFG pCaptureFaceCfg = (NET_DVR_CAPTURE_FACE_CFG *) pRecvDataBuffer;
|
||||
|
||||
LOGINFO("captureFaceInfoCallBack(): 人脸数据 Template1 Size[%d] Template2 Size[%d] Picture Size[%d] infrared Size[%d]",
|
||||
pCaptureFaceCfg->dwFaceTemplate1Size, pCaptureFaceCfg->dwFaceTemplate2Size,
|
||||
pCaptureFaceCfg->dwFacePicSize, pCaptureFaceCfg->dwInfraredFacePicSize);
|
||||
|
||||
pThis->m_pParent->m_pParent->handleFaceInfo(true, pCaptureFaceCfg->dwFacePicSize,
|
||||
(const char *) pCaptureFaceCfg->pFacePicBuffer,
|
||||
pThis->m_pParent->m_pCfgUserData);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LOGERROR("captureFaceInfoCallBack(): 非预期类型 dwType = %u", dwType);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CAcsFaceMng::captureFaceInfo()
|
||||
{
|
||||
//< 上级已判断登录及空闲
|
||||
|
||||
NET_DVR_CAPTURE_FACE_COND struCaptureFaceCond;
|
||||
memset(&struCaptureFaceCond, 0, sizeof(struCaptureFaceCond));
|
||||
struCaptureFaceCond.dwSize = sizeof(struCaptureFaceCond);
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
m_nCfgHandle = NET_DVR_StartRemoteConfig(m_pParent->m_nUserID, NET_DVR_CAPTURE_FACE_INFO, &struCaptureFaceCond,
|
||||
sizeof(struCaptureFaceCond), captureFaceInfoCallBack,
|
||||
this);
|
||||
if (m_nCfgHandle < 0)
|
||||
{
|
||||
//< 由于装置一直在处理图像进行人脸识别,因此有一定概率失败的可能,增加重试
|
||||
if (NET_DVR_DVROPRATEFAILED == NET_DVR_GetLastError() && i < 20)
|
||||
{
|
||||
++i;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGERROR("NET_DVR_CAPTURE_FACE_INFO failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************//**
|
||||
* @brief 分割线,下发人脸
|
||||
**********************************************************************************/
|
||||
|
||||
|
||||
bool CAcsFaceMng::setFaceCfgToDevice()
|
||||
{
|
||||
DWORD nFaceNum = 0;
|
||||
for (std::list<CUserInfo>::const_iterator itUser = m_pParent->m_pListUserInfo->cbegin();
|
||||
itUser != m_pParent->m_pListUserInfo->cend(); ++itUser)
|
||||
{
|
||||
if (itUser->m_strFaceData.size() > 0)
|
||||
++nFaceNum;
|
||||
}
|
||||
|
||||
if (0 == nFaceNum)
|
||||
{
|
||||
LOGINFO("setFaceCfgToDevice(): 没有人脸需要下发");
|
||||
m_pParent->m_pParent->handleSetUserInfoResult(*(m_pParent->m_pListUserInfo), m_pParent->m_pCfgUserData);
|
||||
m_pParent->stopRemoteConfig();
|
||||
return true;
|
||||
}
|
||||
|
||||
NET_DVR_FACE_PARAM_COND struCond;
|
||||
memset(&struCond, 0, sizeof(struCond));
|
||||
struCond.dwSize = sizeof(struCond);
|
||||
struCond.byEnableCardReader[0] = 1;
|
||||
struCond.dwFaceNum = nFaceNum;
|
||||
|
||||
m_nCfgHandle = NET_DVR_StartRemoteConfig(m_pParent->m_nUserID, NET_DVR_SET_FACE_PARAM_CFG,
|
||||
&struCond, sizeof(struCond), setFaceCfgToDeviceCallBack, this);
|
||||
if (m_nCfgHandle < 0)
|
||||
{
|
||||
LOGERROR("NET_DVR_SET_FACE_PARAM_CFG failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
//发送第一张卡, 失败关闭连接
|
||||
if (!sendFirstFace())
|
||||
{
|
||||
LOGERROR("setFaceCfgToDevice(): 下发首卡失败,返回失败!");
|
||||
|
||||
//< 上一级负责,这里注释掉
|
||||
//m_pParent->stopRemoteConfig_inThread();
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 后面的事情交给回调函数
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAcsFaceMng::setFaceCfgToDeviceCallBack(DWORD dwType, void *lpBuffer, DWORD dwBufLen, void *pCaller)
|
||||
{
|
||||
(void) dwBufLen;
|
||||
|
||||
if (nullptr == pCaller)
|
||||
{
|
||||
LOGERROR("setFaceCfgToDeviceCallBack(): nullptr == pCaller");
|
||||
return;
|
||||
}
|
||||
|
||||
CAcsFaceMng *pThis = (CAcsFaceMng *) pCaller;
|
||||
|
||||
if (NET_SDK_CALLBACK_TYPE_STATUS == dwType)
|
||||
{
|
||||
const DWORD dwStatus = *(DWORD *) lpBuffer;
|
||||
|
||||
switch (dwStatus)
|
||||
{
|
||||
case NET_SDK_CALLBACK_STATUS_PROCESSING:
|
||||
{
|
||||
//< lpBuffer:4字节状态 + 32字节卡号
|
||||
char szCardNumber[ACS_CARD_NO_LEN + 1] = "\0";
|
||||
strncpy(szCardNumber, (char *) (lpBuffer) + 4, ACS_CARD_NO_LEN);
|
||||
LOGINFO("setFaceCfgToDeviceCallBack(): PROCESSING %s", szCardNumber);
|
||||
|
||||
//< 设置结果为成功
|
||||
pThis->m_itCurrentUser->m_bSetFaceSuccess = true;
|
||||
|
||||
pThis->sendNextFace();
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_STATUS_FAILED:
|
||||
{
|
||||
if (pThis->m_pParent->m_pListUserInfo->end() == pThis->m_itCurrentUser)
|
||||
{
|
||||
//< 所有人脸已处理完成,如果在海康SDK的接收超时时间后还没有执行 NET_DVR_StopRemoteConfig 释放
|
||||
//< 则会跑到此处,且lpBuffer的内容随机,应该是海康的问题,不做处理
|
||||
}
|
||||
else
|
||||
{
|
||||
//< lpBuffer:4字节状态 + 4字节错误码 + 32字节卡号
|
||||
char szCardNumber[ACS_CARD_NO_LEN + 1] = "\0";
|
||||
DWORD dwErrCode = *((DWORD *) lpBuffer + 1);
|
||||
strncpy(szCardNumber, (char *) (lpBuffer) + 8, ACS_CARD_NO_LEN);
|
||||
LOGERROR("setFaceCfgToDeviceCallBack(): Err: %u, CardNo: %s", dwErrCode, szCardNumber);
|
||||
|
||||
if (!pThis->reSendLastFace())
|
||||
{
|
||||
if (!pThis->sendNextFace())
|
||||
pThis->onSetFaceCfgFinish(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_STATUS_SUCCESS:
|
||||
{
|
||||
LOGINFO("setFaceCfgToDeviceCallBack(): SUCCESS");
|
||||
pThis->onSetFaceCfgFinish(true);
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_STATUS_EXCEPTION:
|
||||
{
|
||||
LOGERROR("setFaceCfgToDeviceCallBack(): EXCEPTION");
|
||||
pThis->onSetFaceCfgFinish(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LOGERROR("setFaceCfgToDeviceCallBack(): 非预期类型,dwStatus = %u", dwStatus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (NET_SDK_CALLBACK_TYPE_DATA == dwType)
|
||||
{
|
||||
NET_DVR_FACE_PARAM_STATUS struStatus;
|
||||
memset(&struStatus, 0, sizeof(struStatus));
|
||||
memcpy(&struStatus, lpBuffer, sizeof(struStatus));
|
||||
|
||||
bool bSendOK = false;
|
||||
|
||||
for (int i = 0; i < (int) sizeof(struStatus.byCardReaderRecvStatus); ++i)
|
||||
{
|
||||
switch (struStatus.byCardReaderRecvStatus[i])
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
bSendOK = true;
|
||||
break;
|
||||
case 2: LOGERROR("setFaceCfgToDeviceCallBack(): 重试或人脸质量差");
|
||||
break;
|
||||
case 3: LOGERROR("setFaceCfgToDeviceCallBack(): 内存已满");
|
||||
break;
|
||||
case 4: LOGERROR("setFaceCfgToDeviceCallBack(): 已存在该人脸");
|
||||
break;
|
||||
case 5: LOGERROR("setFaceCfgToDeviceCallBack(): 非法人脸ID");
|
||||
break;
|
||||
case 6: LOGERROR("setFaceCfgToDeviceCallBack(): 算法建模失败");
|
||||
break;
|
||||
case 7: LOGERROR("setFaceCfgToDeviceCallBack(): 未下发卡权限");
|
||||
break;
|
||||
case 8: LOGERROR("setFaceCfgToDeviceCallBack(): 未定义(保留)");
|
||||
break;
|
||||
case 9: LOGERROR("setFaceCfgToDeviceCallBack(): 人眼间距小");
|
||||
break;
|
||||
case 10: LOGERROR("setFaceCfgToDeviceCallBack(): 图片数据长度小于1KB");
|
||||
break;
|
||||
case 11: LOGERROR("setFaceCfgToDeviceCallBack(): 图片格式不符(png/jpg/bmp)");
|
||||
break;
|
||||
case 12: LOGERROR("setFaceCfgToDeviceCallBack(): 图片像素数量超过上限");
|
||||
break;
|
||||
case 13: LOGERROR("setFaceCfgToDeviceCallBack(): 图片像素数量低于下限");
|
||||
break;
|
||||
case 14: LOGERROR("setFaceCfgToDeviceCallBack(): 图片信息校验失败");
|
||||
break;
|
||||
case 15: LOGERROR("setFaceCfgToDeviceCallBack(): 图片解码失败");
|
||||
break;
|
||||
case 16: LOGERROR("setFaceCfgToDeviceCallBack(): 人脸检测失败");
|
||||
break;
|
||||
case 17: LOGERROR("setFaceCfgToDeviceCallBack(): 人脸评分失败");
|
||||
break;
|
||||
default: LOGERROR("setFaceCfgToDeviceCallBack(): 未知状态码 %d", struStatus.byCardReaderRecvStatus[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bSendOK)
|
||||
{
|
||||
LOGINFO("setFaceCfgToDeviceCallBack(): 下发人脸成功,卡号:%s,读卡器:%d",
|
||||
struStatus.byCardNo, struStatus.dwCardReaderNo);
|
||||
|
||||
//< 设置结果为成功
|
||||
pThis->m_itCurrentUser->m_bSetFaceSuccess = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR("setFaceCfgToDeviceCallBack(): 下发人脸失败,卡号:%s,读卡器:%d",
|
||||
struStatus.byCardNo, struStatus.dwCardReaderNo);
|
||||
}
|
||||
|
||||
pThis->sendNextFace();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR("setFaceCfgToDeviceCallBack(): 非预期的 dwType = %u", dwType);
|
||||
pThis->onSetFaceCfgFinish(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool CAcsFaceMng::sendFaceCfg()
|
||||
{
|
||||
NET_DVR_FACE_PARAM_CFG struFaceCfg;
|
||||
memset(&struFaceCfg, 0, sizeof(struFaceCfg));
|
||||
struFaceCfg.dwSize = sizeof(struFaceCfg);
|
||||
|
||||
char szCardNo[128];
|
||||
sprintf(szCardNo, "%d", m_itCurrentUser->m_nId);
|
||||
strncpy((char *) struFaceCfg.byCardNo, szCardNo, sizeof(struFaceCfg.byCardNo) - 1);
|
||||
|
||||
struFaceCfg.dwFaceLen = (DWORD) (m_itCurrentUser->m_strFaceData.size());
|
||||
struFaceCfg.pFaceBuffer = (char *) (m_itCurrentUser->m_strFaceData.data());
|
||||
|
||||
struFaceCfg.byEnableCardReader[0] = 1;
|
||||
struFaceCfg.byFaceID = 1;
|
||||
struFaceCfg.byFaceDataType = 1; //< 人脸数据类型:0- 模板(默认),1- 图片
|
||||
|
||||
if (!NET_DVR_SendRemoteConfig(m_nCfgHandle, ENUM_ACS_INTELLIGENT_IDENTITY_DATA,
|
||||
(char *) &struFaceCfg, sizeof(struFaceCfg)))
|
||||
{
|
||||
LOGERROR("ENUM_ACS_INTELLIGENT_IDENTITY_DATA failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAcsFaceMng::sendFirstFace()
|
||||
{
|
||||
bool bFind = false;
|
||||
for (m_itCurrentUser = m_pParent->m_pListUserInfo->begin();
|
||||
m_itCurrentUser != m_pParent->m_pListUserInfo->end(); ++m_itCurrentUser)
|
||||
{
|
||||
if (m_itCurrentUser->m_strFaceData.size() > 0)
|
||||
{
|
||||
bFind = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bFind)
|
||||
{
|
||||
LOGERROR("sendFirstFace(): 未找到人脸数据,检查程序!");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nReSendCnt = 0;
|
||||
|
||||
return sendFaceCfg();
|
||||
}
|
||||
|
||||
bool CAcsFaceMng::reSendLastFace()
|
||||
{
|
||||
if (m_pParent->m_pListUserInfo->end() == m_itCurrentUser)
|
||||
return true;
|
||||
|
||||
LOGDEBUG("reSendLastFace(): m_nReSendCnt = %d", m_nReSendCnt);
|
||||
m_nReSendCnt++;
|
||||
if (m_nReSendCnt >= 5)
|
||||
return false;
|
||||
|
||||
return sendFaceCfg();
|
||||
}
|
||||
|
||||
bool CAcsFaceMng::sendNextFace()
|
||||
{
|
||||
if (m_itCurrentUser == m_pParent->m_pListUserInfo->end())
|
||||
return true;
|
||||
|
||||
++m_itCurrentUser;
|
||||
if (m_itCurrentUser == m_pParent->m_pListUserInfo->end())
|
||||
return true;
|
||||
|
||||
return sendFaceCfg();
|
||||
}
|
||||
|
||||
void CAcsFaceMng::onSetFaceCfgFinish(bool bSuccess)
|
||||
{
|
||||
(void) bSuccess;
|
||||
|
||||
//< todo 测试代码
|
||||
//std::this_thread::sleep_for(std::chrono::milliseconds(6000));
|
||||
|
||||
m_pParent->m_pParent->handleSetUserInfoResult(*(m_pParent->m_pListUserInfo), m_pParent->m_pCfgUserData);
|
||||
m_pParent->stopRemoteConfig();
|
||||
|
||||
//< 无需再启动后续步骤
|
||||
}
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,62 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsFaceMng.h
|
||||
* @brief 人脸相关接口,放在 CAcsDeviceApiImpl 中太长,拆分出来
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "app_bio_identify/acs_device_api/AcsDeviceApiCommon.h"
|
||||
|
||||
#if (defined(_WIN32))
|
||||
typedef unsigned long DWORD;
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
typedef unsigned int DWORD;
|
||||
#endif
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
class CAcsFaceMng
|
||||
{
|
||||
friend class CAcsDeviceApiImpl;
|
||||
|
||||
public:
|
||||
CAcsFaceMng(CAcsDeviceApiImpl *pParent);
|
||||
~CAcsFaceMng();
|
||||
|
||||
bool captureFaceInfo();
|
||||
|
||||
//< 设置人脸参数到设备
|
||||
bool setFaceCfgToDevice();
|
||||
|
||||
private:
|
||||
|
||||
//< 人脸采集回调函数
|
||||
static void captureFaceInfoCallBack(DWORD dwType, void *pRecvDataBuffer,
|
||||
DWORD dwBufSize, void *pCaller);
|
||||
|
||||
//< 设置人脸参数到设备
|
||||
static void setFaceCfgToDeviceCallBack(DWORD dwType, void *lpBuffer, DWORD dwBufLen, void *pCaller);
|
||||
bool sendFaceCfg();
|
||||
bool sendFirstFace();
|
||||
bool reSendLastFace();
|
||||
bool sendNextFace();
|
||||
void onSetFaceCfgFinish(bool bSuccess);
|
||||
|
||||
private:
|
||||
unsigned char m_nReSendCnt; //< 重发计数
|
||||
|
||||
//< 注意:任何时候都应该只有一个设置操作在执行
|
||||
long m_nCfgHandle; //< 当前设置操作的句柄
|
||||
|
||||
CAcsDeviceApiImpl *const m_pParent;
|
||||
|
||||
std::list<CUserInfo>::iterator m_itCurrentUser; //< 当前待下发的用户
|
||||
|
||||
};
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,510 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsFingerprintMng.cpp
|
||||
* @brief 指纹相关接口,放在 CAcsDeviceApiImpl 中太长,拆分出来
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
|
||||
#include "hikvision/HCNetSDK.h"
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
|
||||
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
|
||||
#include "CAcsDeviceApiImpl.h"
|
||||
#include "CAcsFingerprintMng.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
CAcsFingerprintMng::CAcsFingerprintMng(CAcsDeviceApiImpl *pParent)
|
||||
: m_nReSendCnt(0), m_nCfgHandle(-1), m_pParent(pParent)
|
||||
{
|
||||
//< todo
|
||||
}
|
||||
|
||||
CAcsFingerprintMng::~CAcsFingerprintMng()
|
||||
{
|
||||
//< todo
|
||||
}
|
||||
|
||||
void CAcsFingerprintMng::captureFingerprintInfoCallBack(DWORD dwType, void *pRecvDataBuffer,
|
||||
DWORD dwBufSize, void *pCaller)
|
||||
{
|
||||
if (nullptr == pCaller)
|
||||
{
|
||||
LOGERROR("captureFingerprintInfoCallBack(): nullptr == pCaller");
|
||||
return;
|
||||
}
|
||||
|
||||
CAcsFingerprintMng *pThis = (CAcsFingerprintMng *) pCaller;
|
||||
|
||||
switch (dwType)
|
||||
{
|
||||
case NET_SDK_CALLBACK_TYPE_STATUS:
|
||||
{
|
||||
DWORD dwTemp = *((DWORD *) pRecvDataBuffer);
|
||||
if (dwTemp == NET_SDK_CALLBACK_STATUS_PROCESSING)
|
||||
{
|
||||
LOGINFO("captureFingerprintInfoCallBack(): NET_SDK_CALLBACK_STATUS_PROCESSING");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dwTemp == NET_SDK_CALLBACK_STATUS_SUCCESS)
|
||||
{
|
||||
LOGINFO("captureFingerprintInfoCallBack(): NET_SDK_CALLBACK_STATUS_SUCCESS");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR("captureFingerprintInfoCallBack(): dwTemp = %u", dwTemp);
|
||||
if (dwBufSize > 4)
|
||||
{
|
||||
LOGERROR("captureFingerprintInfoCallBack(): ErrCode = %d", *((DWORD *) pRecvDataBuffer + 1));
|
||||
}
|
||||
|
||||
pThis->m_pParent->m_pParent->handleFingerprintInfo(false, 0, nullptr,
|
||||
pThis->m_pParent->m_pCfgUserData);
|
||||
}
|
||||
|
||||
pThis->m_pParent->stopRemoteConfig();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_TYPE_PROGRESS:
|
||||
{
|
||||
LOGINFO("captureFingerprintInfoCallBack(): NET_SDK_CALLBACK_TYPE_PROGRESS");
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_TYPE_DATA:
|
||||
{
|
||||
if (sizeof(NET_DVR_CAPTURE_FINGERPRINT_CFG) > dwBufSize)
|
||||
{
|
||||
LOGERROR("captureFingerprintInfoCallBack(): 数据长度不正确!");
|
||||
}
|
||||
|
||||
LPNET_DVR_CAPTURE_FINGERPRINT_CFG pCaptureFingerPrintCfg = (NET_DVR_CAPTURE_FINGERPRINT_CFG *) pRecvDataBuffer;
|
||||
|
||||
LOGINFO("captureFingerprintInfoCallBack(): 指纹数据 Size[%d] Picture Size[%d]",
|
||||
pCaptureFingerPrintCfg->dwFingerPrintDataSize, pCaptureFingerPrintCfg->dwFingerPrintPicSize);
|
||||
|
||||
pThis->m_pParent->m_pParent->handleFingerprintInfo(true, pCaptureFingerPrintCfg->dwFingerPrintDataSize,
|
||||
(const char *) pCaptureFingerPrintCfg->byFingerData,
|
||||
pThis->m_pParent->m_pCfgUserData);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LOGERROR("captureFingerprintInfoCallBack(): 非预期类型 dwType = %u", dwType);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CAcsFingerprintMng::captureFingerprintInfo()
|
||||
{
|
||||
//< 上级已判断登录及空闲
|
||||
|
||||
NET_DVR_CAPTURE_FINGERPRINT_COND struCaptureFingerPrintCond;
|
||||
memset(&struCaptureFingerPrintCond, 0, sizeof(struCaptureFingerPrintCond));
|
||||
|
||||
struCaptureFingerPrintCond.dwSize = sizeof(struCaptureFingerPrintCond);
|
||||
struCaptureFingerPrintCond.byFingerPrintPicType = 0;
|
||||
struCaptureFingerPrintCond.byFingerNo = 1;
|
||||
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
m_nCfgHandle = NET_DVR_StartRemoteConfig(m_pParent->m_nUserID, NET_DVR_CAPTURE_FINGERPRINT_INFO,
|
||||
&struCaptureFingerPrintCond,
|
||||
sizeof(struCaptureFingerPrintCond), captureFingerprintInfoCallBack,
|
||||
this);
|
||||
|
||||
if (m_nCfgHandle < 0)
|
||||
{
|
||||
//< 如果刚有人刷了指纹,或正有人刷指纹,会有一定概率失败的可能,增加重试
|
||||
if (NET_DVR_DVROPRATEFAILED == NET_DVR_GetLastError() && i < 20)
|
||||
{
|
||||
++i;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGERROR("NET_DVR_CAPTURE_FINGERPRINT_INFO failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************//**
|
||||
* @brief 分割线,下发指纹
|
||||
**********************************************************************************/
|
||||
|
||||
|
||||
bool CAcsFingerprintMng::setFingerprintCfgToDevice()
|
||||
{
|
||||
DWORD nFpNum = 0;
|
||||
for (std::list<CUserInfo>::const_iterator itUser = m_pParent->m_pListUserInfo->cbegin();
|
||||
itUser != m_pParent->m_pListUserInfo->cend(); ++itUser)
|
||||
{
|
||||
const std::list<CFingerprintInfo> &listFp = itUser->m_listFingerprint;
|
||||
for (std::list<CFingerprintInfo>::const_iterator itFp = listFp.cbegin(); itFp != listFp.cend(); ++itFp)
|
||||
{
|
||||
if (itFp->isValid())
|
||||
++nFpNum;
|
||||
else
|
||||
{
|
||||
LOGWARN("setFingerprintCfgToDevice(): 跳过无效指纹:用户ID:%d,用户名:%s,指纹ID:%d",
|
||||
itUser->m_nId, itUser->m_strName.c_str(), itFp->m_nId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == nFpNum)
|
||||
{
|
||||
LOGINFO("setFingerprintCfgToDevice(): 没有指纹需要下发,转到下发人脸");
|
||||
return m_pParent->m_objFaceMng.setFaceCfgToDevice();
|
||||
}
|
||||
|
||||
NET_DVR_FINGER_PRINT_INFO_COND_V50 struCond;
|
||||
memset(&struCond, 0, sizeof(struCond));
|
||||
struCond.dwSize = sizeof(struCond);
|
||||
struCond.byEnableCardReader[0] = 1;
|
||||
struCond.dwFingerPrintNum = nFpNum;
|
||||
struCond.byCallbackMode = 0;
|
||||
|
||||
m_nCfgHandle = NET_DVR_StartRemoteConfig(m_pParent->m_nUserID, NET_DVR_SET_FINGERPRINT_CFG_V50,
|
||||
&struCond, sizeof(struCond), setFpCfgToDeviceCallBack, this);
|
||||
if (m_nCfgHandle < 0)
|
||||
{
|
||||
LOGERROR("NET_DVR_SET_FINGERPRINT_CFG_V50 failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
|
||||
//发送第一张卡, 失败关闭连接
|
||||
if (!sendFirstFp())
|
||||
{
|
||||
LOGERROR("setFingerprintCfgToDevice(): 下发首卡失败,返回失败!");
|
||||
|
||||
//< 上一级负责,这里注释掉
|
||||
//m_pParent->stopRemoteConfig_inThread();
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 后面的事情交给回调函数
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAcsFingerprintMng::setFpCfgToDeviceCallBack(DWORD dwType, void *lpBuffer, DWORD dwBufLen, void *pCaller)
|
||||
{
|
||||
(void) dwBufLen;
|
||||
|
||||
if (nullptr == pCaller)
|
||||
{
|
||||
LOGERROR("setFpCfgToDeviceCallBack(): nullptr == pCaller");
|
||||
return;
|
||||
}
|
||||
|
||||
CAcsFingerprintMng *pThis = (CAcsFingerprintMng *) pCaller;
|
||||
|
||||
if (NET_SDK_CALLBACK_TYPE_STATUS == dwType)
|
||||
{
|
||||
const DWORD dwStatus = *(DWORD *) lpBuffer;
|
||||
|
||||
switch (dwStatus)
|
||||
{
|
||||
case NET_SDK_CALLBACK_STATUS_PROCESSING:
|
||||
{
|
||||
//< lpBuffer:4字节状态 + 32字节卡号
|
||||
char szCardNumber[ACS_CARD_NO_LEN + 1] = "\0";
|
||||
strncpy(szCardNumber, (char *) (lpBuffer) + 4, ACS_CARD_NO_LEN);
|
||||
LOGINFO("setFpCfgToDeviceCallBack(): PROCESSING %s", szCardNumber);
|
||||
|
||||
//< 设置结果为成功
|
||||
pThis->m_itCurrentFp->m_bSetSuccess = true;
|
||||
|
||||
pThis->sendNextFp();
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_STATUS_FAILED:
|
||||
{
|
||||
if (pThis->m_pParent->m_pListUserInfo->end() == pThis->m_itCurrentUser)
|
||||
{
|
||||
//< 所有指纹已处理完成,如果在海康SDK的接收超时时间后还没有执行 NET_DVR_StopRemoteConfig 释放
|
||||
//< 则会跑到此处,且lpBuffer的内容随机,应该是海康的问题,不做处理
|
||||
}
|
||||
else
|
||||
{
|
||||
//< lpBuffer:4字节状态 + 4字节错误码 + 32字节卡号
|
||||
char szCardNumber[ACS_CARD_NO_LEN + 1] = "\0";
|
||||
DWORD dwErrCode = *((DWORD *) lpBuffer + 1);
|
||||
strncpy(szCardNumber, (char *) (lpBuffer) + 8, ACS_CARD_NO_LEN);
|
||||
LOGERROR("setFpCfgToDeviceCallBack(): Err: %u, CardNo: %s", dwErrCode, szCardNumber);
|
||||
|
||||
if (!pThis->reSendLastFp())
|
||||
{
|
||||
if (!pThis->sendNextFp())
|
||||
pThis->onSetFpCfgFinish(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_STATUS_SUCCESS:
|
||||
{
|
||||
LOGINFO("setFpCfgToDeviceCallBack(): SUCCESS");
|
||||
pThis->onSetFpCfgFinish(true);
|
||||
}
|
||||
break;
|
||||
case NET_SDK_CALLBACK_STATUS_EXCEPTION:
|
||||
{
|
||||
LOGERROR("setFpCfgToDeviceCallBack(): EXCEPTION");
|
||||
pThis->onSetFpCfgFinish(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LOGERROR("setFpCfgToDeviceCallBack(): 非预期类型,dwStatus = %u", dwStatus);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (NET_SDK_CALLBACK_TYPE_DATA == dwType)
|
||||
{
|
||||
NET_DVR_FINGER_PRINT_STATUS_V50 struStatus;
|
||||
memset(&struStatus, 0, sizeof(struStatus));
|
||||
memcpy(&struStatus, lpBuffer, sizeof(struStatus));
|
||||
|
||||
bool bSendOK = false;
|
||||
|
||||
//< byRecvStatus 设备错误状态:
|
||||
// 0-成功,1-手指编号错误,2-指纹类型错误,3-卡号错误(卡号规格不符合设备要求),
|
||||
// 4-指纹未关联工号或卡号(工号或卡号字段为空),5-工号不存在,6-指纹数据长度为0,
|
||||
// 7-读卡器编号错误,8-工号错误,9-首次认证值非法,10-其他参数错误
|
||||
if (struStatus.byRecvStatus == 0)
|
||||
{
|
||||
for (int i = 0; i < (int) sizeof(struStatus.byCardReaderRecvStatus); ++i)
|
||||
{
|
||||
//< byCardReaderRecvStatus 指纹读卡器状态,数组下标表示读卡器序号,数组值:
|
||||
// 0- 失败,1- 成功,2- 该指纹模组不在线,3- 重试或指纹质量差,
|
||||
// 4- 内存已满,5- 已存在该指纹,6- 已存在该指纹ID,7- 非法指纹ID,
|
||||
// 8- 该指纹模组无需配置,9- 指纹类型不支持
|
||||
if (1 == struStatus.byCardReaderRecvStatus[i])
|
||||
{
|
||||
bSendOK = true;
|
||||
}
|
||||
else if (8 == struStatus.byCardReaderRecvStatus[i])
|
||||
{
|
||||
//无需打印任何信息
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR("setFpCfgToDeviceCallBack(): 读卡器失败信息: byCardNo %s, CardReader %d, "
|
||||
"byCardReaderRecvStatus %d, dwCardReaderNo: %d, byErrorMsg: %s",
|
||||
struStatus.byCardNo, i, struStatus.byCardReaderRecvStatus[i], struStatus.dwCardReaderNo,
|
||||
struStatus.byErrorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bSendOK = false;
|
||||
switch (struStatus.byRecvStatus)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1: LOGERROR("setFpCfgToDeviceCallBack(): 手指编号错误");
|
||||
break;
|
||||
case 2: LOGERROR("setFpCfgToDeviceCallBack(): 指纹类型错误");
|
||||
break;
|
||||
case 3: LOGERROR("setFpCfgToDeviceCallBack(): 卡号错误(卡号规格不符合设备要求)");
|
||||
break;
|
||||
case 4: LOGERROR("setFpCfgToDeviceCallBack(): 指纹未关联工号或卡号(工号或卡号字段为空)");
|
||||
break;
|
||||
case 5: LOGERROR("setFpCfgToDeviceCallBack(): 工号不存在");
|
||||
break;
|
||||
case 6: LOGERROR("setFpCfgToDeviceCallBack(): 指纹数据长度为0");
|
||||
break;
|
||||
case 7: LOGERROR("setFpCfgToDeviceCallBack(): 读卡器编号错误");
|
||||
break;
|
||||
case 8: LOGERROR("setFpCfgToDeviceCallBack(): 工号错误");
|
||||
break;
|
||||
case 9: LOGERROR("setFpCfgToDeviceCallBack(): 首次认证值非法");
|
||||
break;
|
||||
case 10: LOGERROR("setFpCfgToDeviceCallBack(): 其他参数错误");
|
||||
break;
|
||||
default: LOGERROR("setFpCfgToDeviceCallBack(): 未知状态码 %d", struStatus.byRecvStatus);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bSendOK)
|
||||
{
|
||||
LOGINFO("setFpCfgToDeviceCallBack(): 下发指纹成功,卡号:%s,指纹号:%d,读卡器:%d",
|
||||
struStatus.byCardNo, struStatus.byFingerPrintID, struStatus.dwCardReaderNo);
|
||||
|
||||
//< 设置结果为成功
|
||||
pThis->m_itCurrentFp->m_bSetSuccess = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR("setFpCfgToDeviceCallBack(): 下发指纹失败,卡号:%s,指纹号:%d,读卡器:%d",
|
||||
struStatus.byCardNo, struStatus.byFingerPrintID, struStatus.dwCardReaderNo);
|
||||
}
|
||||
|
||||
pThis->sendNextFp();
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR("setFpCfgToDeviceCallBack(): 非预期的 dwType = %u", dwType);
|
||||
pThis->onSetFpCfgFinish(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool CAcsFingerprintMng::sendFpCfg()
|
||||
{
|
||||
NET_DVR_FINGER_PRINT_CFG_V50 struFpCfg;
|
||||
memset(&struFpCfg, 0, sizeof(struFpCfg));
|
||||
struFpCfg.dwSize = sizeof(struFpCfg);
|
||||
|
||||
char szCardNo[128];
|
||||
sprintf(szCardNo, "%d", m_itCurrentUser->m_nId);
|
||||
strncpy((char *) struFpCfg.byCardNo, szCardNo, sizeof(struFpCfg.byCardNo) - 1);
|
||||
strncpy((char *) struFpCfg.byEmployeeNo, szCardNo, sizeof(struFpCfg.byEmployeeNo) - 1);
|
||||
|
||||
struFpCfg.dwFingerPrintLen = (DWORD) (m_itCurrentFp->m_strData.size());
|
||||
if (struFpCfg.dwFingerPrintLen > MAX_FINGER_PRINT_LEN)
|
||||
{
|
||||
LOGERROR("sendFpCfg(): 指纹数据长度超限,降低为最大长度");
|
||||
struFpCfg.dwFingerPrintLen = MAX_FINGER_PRINT_LEN;
|
||||
}
|
||||
|
||||
struFpCfg.byEnableCardReader[0] = 1;
|
||||
struFpCfg.byFingerPrintID = m_itCurrentFp->m_nId;
|
||||
struFpCfg.byFingerType = 0;
|
||||
|
||||
memcpy(&struFpCfg.byFingerData, m_itCurrentFp->m_strData.data(), struFpCfg.dwFingerPrintLen);
|
||||
|
||||
if (!NET_DVR_SendRemoteConfig(m_nCfgHandle, ENUM_ACS_SEND_DATA,
|
||||
(char *) &struFpCfg, sizeof(struFpCfg)))
|
||||
{
|
||||
LOGERROR("ENUM_ACS_SEND_DATA failed, ErrCode = %d , ErrStr = %s",
|
||||
NET_DVR_GetLastError(), NET_DVR_GetErrorMsg());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAcsFingerprintMng::sendFirstFp()
|
||||
{
|
||||
bool bFind = false;
|
||||
for (m_itCurrentUser = m_pParent->m_pListUserInfo->begin();
|
||||
m_itCurrentUser != m_pParent->m_pListUserInfo->end(); ++m_itCurrentUser)
|
||||
{
|
||||
std::list<CFingerprintInfo> &listFp = m_itCurrentUser->m_listFingerprint;
|
||||
for (m_itCurrentFp = listFp.begin(); m_itCurrentFp != listFp.end(); ++m_itCurrentFp)
|
||||
{
|
||||
if (m_itCurrentFp->isValid())
|
||||
{
|
||||
bFind = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFind)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bFind)
|
||||
{
|
||||
LOGERROR("sendFirstFp(): 未找到指纹数据,检查程序!");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nReSendCnt = 0;
|
||||
|
||||
return sendFpCfg();
|
||||
}
|
||||
|
||||
bool CAcsFingerprintMng::reSendLastFp()
|
||||
{
|
||||
if (m_pParent->m_pListUserInfo->end() == m_itCurrentUser)
|
||||
return true;
|
||||
|
||||
LOGDEBUG("reSendLastFp(): m_nReSendCnt = %d", m_nReSendCnt);
|
||||
m_nReSendCnt++;
|
||||
if (m_nReSendCnt >= 5)
|
||||
return false;
|
||||
|
||||
return sendFpCfg();
|
||||
}
|
||||
|
||||
bool CAcsFingerprintMng::sendNextFp()
|
||||
{
|
||||
if (m_pParent->m_pListUserInfo->end() == m_itCurrentUser)
|
||||
return true;
|
||||
|
||||
if (m_itCurrentFp != m_itCurrentUser->m_listFingerprint.end())
|
||||
++m_itCurrentFp;
|
||||
|
||||
bool bFind = false;
|
||||
|
||||
while (1)
|
||||
{
|
||||
std::list<CFingerprintInfo> &listFp = m_itCurrentUser->m_listFingerprint;
|
||||
for (/* 空 */; m_itCurrentFp != listFp.end(); ++m_itCurrentFp)
|
||||
{
|
||||
if (m_itCurrentFp->isValid())
|
||||
{
|
||||
bFind = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bFind)
|
||||
break;
|
||||
else
|
||||
{
|
||||
++m_itCurrentUser;
|
||||
if (m_pParent->m_pListUserInfo->end() == m_itCurrentUser)
|
||||
break;
|
||||
else
|
||||
m_itCurrentFp = m_itCurrentUser->m_listFingerprint.begin();
|
||||
}
|
||||
}
|
||||
|
||||
if (!bFind)
|
||||
return true;
|
||||
|
||||
return sendFpCfg();
|
||||
}
|
||||
|
||||
void CAcsFingerprintMng::onSetFpCfgFinish(bool bSuccess)
|
||||
{
|
||||
if (!bSuccess)
|
||||
{
|
||||
m_pParent->m_pParent->handleSetUserInfoResult(*(m_pParent->m_pListUserInfo), m_pParent->m_pCfgUserData);
|
||||
m_pParent->stopRemoteConfig();
|
||||
return;
|
||||
}
|
||||
|
||||
//< 启动下发人脸
|
||||
if (!(m_pParent->m_objFaceMng.setFaceCfgToDevice()))
|
||||
{
|
||||
m_pParent->m_pParent->handleSetUserInfoResult(*(m_pParent->m_pListUserInfo), m_pParent->m_pCfgUserData);
|
||||
m_pParent->stopRemoteConfig();
|
||||
}
|
||||
}
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,66 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsFingerprintMng.h
|
||||
* @brief 指纹相关接口,放在 CAcsDeviceApiImpl 中太长,拆分出来
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date 2020/7/16
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "app_bio_identify/acs_device_api/AcsDeviceApiCommon.h"
|
||||
|
||||
#if (defined(_WIN32))
|
||||
typedef unsigned long DWORD;
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
typedef unsigned int DWORD;
|
||||
#endif
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
class CAcsDeviceApiImpl;
|
||||
|
||||
class CAcsFingerprintMng
|
||||
{
|
||||
friend class CAcsDeviceApiImpl;
|
||||
|
||||
public:
|
||||
CAcsFingerprintMng(CAcsDeviceApiImpl *pParent);
|
||||
~CAcsFingerprintMng();
|
||||
|
||||
//< 采集指纹
|
||||
bool captureFingerprintInfo();
|
||||
|
||||
//< 设置指纹参数到设备
|
||||
bool setFingerprintCfgToDevice();
|
||||
|
||||
private:
|
||||
|
||||
//< 采集指纹回调函数
|
||||
static void captureFingerprintInfoCallBack(DWORD dwType, void *pRecvDataBuffer,
|
||||
DWORD dwBufSize, void *pCaller);
|
||||
|
||||
//< 设置指纹参数到设备
|
||||
static void setFpCfgToDeviceCallBack(DWORD dwType, void *lpBuffer, DWORD dwBufLen, void *pCaller);
|
||||
bool sendFpCfg();
|
||||
bool sendFirstFp();
|
||||
bool reSendLastFp();
|
||||
bool sendNextFp();
|
||||
void onSetFpCfgFinish(bool bSuccess);
|
||||
|
||||
private:
|
||||
unsigned char m_nReSendCnt; //< 重发计数
|
||||
|
||||
//< 注意:任何时候都应该只有一个设置操作在执行
|
||||
long m_nCfgHandle; //< 当前设置操作的句柄
|
||||
|
||||
CAcsDeviceApiImpl *const m_pParent;
|
||||
|
||||
std::list<CUserInfo>::iterator m_itCurrentUser; //< 当前待下发的用户
|
||||
std::list<CFingerprintInfo>::iterator m_itCurrentFp; //< 当前待下发的指纹
|
||||
|
||||
};
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,56 @@
|
||||
|
||||
QT -= gui core
|
||||
CONFIG -= qt
|
||||
|
||||
TEMPLATE = lib
|
||||
TARGET = acs_device_api
|
||||
|
||||
LIBS += -lboost_system -lboost_filesystem -lboost_chrono -llog4cplus \
|
||||
-lpub_logger_api -lpub_utility_api
|
||||
|
||||
DEFINES += ACS_DEVICE_API_EXPORTS
|
||||
win32{
|
||||
DEFINES += _CRT_SECURE_NO_WARNINGS
|
||||
}
|
||||
|
||||
HEADERS += $$PWD/../../../include/application/app_bio_identify/acs_device_api/AcsDeviceApiCommon.h \
|
||||
$$PWD/../../../include/application/app_bio_identify/acs_device_api/AcsDeviceApiExport.h \
|
||||
$$PWD/../../../include/application/app_bio_identify/acs_device_api/CAcsDeviceApi.h \
|
||||
|
||||
# 当前海康sdk只有X86版本
|
||||
contains(QMAKE_HOST.arch, x86_64){
|
||||
|
||||
HEADERS += CAcsDeviceApiImpl.h \
|
||||
CAcsDeviceApiImplFactory.h \
|
||||
CAcsCardMng.h \
|
||||
CAcsFaceMng.h \
|
||||
CAcsFingerprintMng.h
|
||||
|
||||
SOURCES += CAcsDeviceApi.cpp \
|
||||
CAcsDeviceApiImpl.cpp \
|
||||
CAcsDeviceApiImplFactory.cpp \
|
||||
CAcsCardMng.cpp \
|
||||
CAcsFaceMng.cpp \
|
||||
CAcsFingerprintMng.cpp
|
||||
}
|
||||
else{
|
||||
SOURCES += CAcsDeviceApiFake.cpp
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
COMMON_PRI=$$PWD/../../../common.pri
|
||||
exists($$COMMON_PRI) {
|
||||
include($$COMMON_PRI)
|
||||
}else {
|
||||
error("FATAL error: can not find common.pri")
|
||||
}
|
||||
|
||||
#必须在common.pri之后包含,pri内部已判断QMAKE_HOST.arch
|
||||
#-------------------------------------------------------------------
|
||||
HIKVISION_PRI=$$PWD/../../../3rd/include/hikvision/hikvision.pri
|
||||
exists($$HIKVISION_PRI) {
|
||||
include($$HIKVISION_PRI)
|
||||
}else {
|
||||
error("FATAL error: can not find hikvision.pri")
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
|
||||
#各子工程按书写顺序编译,清注意各子工程的依赖关系,被依赖的库应写在前面。
|
||||
|
||||
TEMPLATE = subdirs
|
||||
CONFIG += ordered
|
||||
|
||||
SUBDIRS += acs_device_api \
|
||||
app_bio_identify_srv
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file BisCommon.cpp
|
||||
* @brief 生物识别服务,通用定义等
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#include "BisCommon.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,17 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file BisCommon.h
|
||||
* @brief 生物识别服务,通用定义等
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
|
||||
} //< namespace kbd_application
|
||||
|
||||
@ -0,0 +1,348 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsDevice.cpp
|
||||
* @brief ACS设备类
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
//< 屏蔽Protobuff编译告警
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4100)
|
||||
#endif
|
||||
|
||||
#include "BioIdentifyMsg.pb.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include "common/Common.h"
|
||||
#include "common/MessageChannel.h"
|
||||
#include "pub_logger_api/logger.h"
|
||||
#include "pub_utility_api/I18N.h"
|
||||
#include "pub_utility_api/TimeUtil.h"
|
||||
|
||||
#include "CAcsWorkThread.h"
|
||||
#include "CAcsDevice.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
CAcsDevice::CAcsDevice(CAcsWorkThread *pParent, const char *szTagName,
|
||||
const char *szIP, int nPort, const char *szUser, const char *szPwd)
|
||||
: m_nPort(nPort), m_strIp(szIP), m_strUser(szUser), m_strPwd(szPwd), m_strTagName(szTagName),
|
||||
m_enState(EN_STATE_UNCONNECTED), m_pParent(pParent),
|
||||
m_nStateStartTime(0)
|
||||
{
|
||||
}
|
||||
|
||||
CAcsDevice::~CAcsDevice()
|
||||
{
|
||||
logOutFromDevice();
|
||||
|
||||
m_ptrIdResult.reset();
|
||||
}
|
||||
|
||||
void CAcsDevice::handleFaceInfo(bool bSuccess, size_t nDataLen, const char *pData, void *pUserData)
|
||||
{
|
||||
(void) bSuccess;
|
||||
(void) nDataLen;
|
||||
(void) pData;
|
||||
(void) pUserData;
|
||||
LOGERROR("handleFaceInfo(): 服务程序不应运行至此处,检查程序!");
|
||||
}
|
||||
|
||||
void CAcsDevice::handleFingerprintInfo(bool bSuccess, size_t nDataLen, const char *pData, void *pUserData)
|
||||
{
|
||||
(void) bSuccess;
|
||||
(void) nDataLen;
|
||||
(void) pData;
|
||||
(void) pUserData;
|
||||
LOGERROR("handleFingerprintInfo(): 服务程序不应运行至此处,检查程序!");
|
||||
}
|
||||
|
||||
void CAcsDevice::handleSetUserInfoResult(const std::list<kbd_application::CUserInfo> &listUserInfo, void *pUserData)
|
||||
{
|
||||
(void) listUserInfo;
|
||||
(void) pUserData;
|
||||
LOGERROR("handleSetUserInfoResult(): 服务程序不应运行至此处,检查程序!");
|
||||
}
|
||||
|
||||
void CAcsDevice::handleIdentificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData)
|
||||
{
|
||||
if (!bPass)
|
||||
{
|
||||
LOGINFO("handleIdentificationEvent(): 忽略不成功的的认证事件");
|
||||
return;
|
||||
}
|
||||
|
||||
//< 加锁
|
||||
boost::mutex::scoped_lock locker(m_mutexIdResult);
|
||||
|
||||
if (nullptr == m_ptrIdResult)
|
||||
{
|
||||
m_ptrIdResult.reset(new CIdResult(bPass, nUserID, nPicDataLen, pPicData));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGINFO("handleIdentificationEvent(): 上一个结果未处理,忽略本结果。bPass = %s, nUserID = %d, nPicDataLen = %lld",
|
||||
bPass ? "true" : "false", nUserID, (long long) nPicDataLen);
|
||||
}
|
||||
}
|
||||
|
||||
bool CAcsDevice::handle_MT_BIS_START_ID_REQ(const kbd_net::CMbMessage &objMbMsgReq)
|
||||
{
|
||||
LOGINFO("handle_MT_BIS_START_ID_REQ(): 收到请求,开始处理!");
|
||||
|
||||
bool bRet = false;
|
||||
std::string strRep(" ");
|
||||
|
||||
switch (m_enState)
|
||||
{
|
||||
case EN_STATE_UNCONNECTED:
|
||||
bRet = false;
|
||||
strRep = I18N("设备未连接,请检查设备是否在线!");
|
||||
break;
|
||||
case EN_STATE_IDLE:
|
||||
{
|
||||
//< 清空结果,防止脏数据
|
||||
{
|
||||
//< 加锁
|
||||
boost::mutex::scoped_lock locker(m_mutexIdResult);
|
||||
m_ptrIdResult.reset();
|
||||
}
|
||||
|
||||
if (enableIdentification(true))
|
||||
{
|
||||
bRet = true;
|
||||
strRep = I18N("启用设备成功,请在设备上认证!");
|
||||
|
||||
//< 设置消息,用于回复
|
||||
m_objMbMsgReq = objMbMsgReq;
|
||||
|
||||
//< 切换状态
|
||||
m_enState = EN_STATE_WAITE_RESULT;
|
||||
m_nStateStartTime = kbd_public::getMonotonicMsec();
|
||||
}
|
||||
else
|
||||
{
|
||||
bRet = false;
|
||||
strRep = I18N("启用设备失败,请检查设备是否在线!");
|
||||
|
||||
//< 登出,切换状态
|
||||
logOutFromDevice(true);
|
||||
m_enState = EN_STATE_UNCONNECTED;
|
||||
m_nStateStartTime = 0; //< 可立刻触发重连
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EN_STATE_WAITE_RESULT:
|
||||
bRet = false;
|
||||
strRep = I18N("设备被占用,请稍后再试!");
|
||||
break;
|
||||
default:
|
||||
{
|
||||
bRet = false;
|
||||
strRep = I18N("未知错误!");
|
||||
|
||||
LOGERROR("handle_MT_BIS_START_ID_REQ(): m_enState = %d ,非法状态,检查程序!", (int) m_enState);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
LOGINFO("handle_MT_BIS_START_ID_REQ(): ACS设备TAG: %s, 回复内容: %s", m_strTagName.c_str(), strRep.c_str());
|
||||
|
||||
//< 回复消息
|
||||
{
|
||||
kbd_net::CMbMessage objMsgRep;
|
||||
objMsgRep.setSubject(CN_AppId_COMAPP, CH_BIS_TO_APP);
|
||||
objMsgRep.setMsgType(kbd_idlfile::MT_BIS_START_ID_REP);
|
||||
objMsgRep.setData(strRep);
|
||||
objMsgRep.setPara1(bRet ? 0 : 1);
|
||||
|
||||
//< objMsgRep 内容将被取走
|
||||
m_pParent->m_pMbComm->replyMsg(objMsgRep, objMbMsgReq);
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
bool CAcsDevice::handle_MT_BIS_CANCEL_ID(const kbd_net::CMbMessage &objMbMsgReq)
|
||||
{
|
||||
LOGINFO("handle_MT_BIS_CANCEL_ID(): 收到请求,开始处理!");
|
||||
|
||||
if (nullptr == m_objMbMsgReq.getSrcComm() || nullptr == objMbMsgReq.getSrcComm())
|
||||
{
|
||||
LOGINFO("handle_MT_BIS_CANCEL_ID(): getSrcComm()为空,忽略!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 != strcmp(m_objMbMsgReq.getSrcComm(), objMbMsgReq.getSrcComm()))
|
||||
{
|
||||
LOGINFO("handle_MT_BIS_CANCEL_ID(): 不是当前请求端发的消息,忽略!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 清空请求原始消息
|
||||
m_objMbMsgReq.clear();
|
||||
|
||||
//< 设置状态
|
||||
m_enState = EN_STATE_IDLE;
|
||||
m_nStateStartTime = kbd_public::getMonotonicMsec();
|
||||
|
||||
//< 关闭认证
|
||||
enableIdentification(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAcsDevice::processStateMachine()
|
||||
{
|
||||
const boost::int64_t nTimeNow = kbd_public::getMonotonicMsec();
|
||||
|
||||
switch (m_enState)
|
||||
{
|
||||
case EN_STATE_UNCONNECTED:
|
||||
{
|
||||
//< 防止过于频繁连接,会耗时较多
|
||||
if (m_nStateStartTime + 5000 < nTimeNow)
|
||||
{
|
||||
m_nStateStartTime = nTimeNow;
|
||||
|
||||
if (logInToDevice(m_strIp.c_str(), m_nPort, m_strUser.c_str(), m_strPwd.c_str()))
|
||||
{
|
||||
enableListenEvents(true);
|
||||
m_enState = EN_STATE_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGINFO("processStateMachine(): logInToDevice() failed, IP = %s, Port = %d",
|
||||
m_strIp.c_str(), m_nPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EN_STATE_IDLE:
|
||||
{
|
||||
//< 是否需要关闭认证
|
||||
bool bNeedDisableId = false;
|
||||
|
||||
//< 检查有没有非预期的认证结果,有可能是外部开启了认证
|
||||
{
|
||||
//< 加锁
|
||||
boost::mutex::scoped_lock locker(m_mutexIdResult);
|
||||
if (nullptr != m_ptrIdResult)
|
||||
{
|
||||
bNeedDisableId = true;
|
||||
m_ptrIdResult.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (bNeedDisableId)
|
||||
{
|
||||
enableIdentification(false);
|
||||
LOGINFO("processStateMachine(): 收到非预期的认证结果,可能是外部开启的认证,已关闭认证。");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EN_STATE_WAITE_RESULT:
|
||||
{
|
||||
CIdResultPtr ptrIdResult;
|
||||
|
||||
//< 检查是否有结果
|
||||
{
|
||||
//< 加锁
|
||||
boost::mutex::scoped_lock locker(m_mutexIdResult);
|
||||
|
||||
ptrIdResult = m_ptrIdResult;
|
||||
m_ptrIdResult.reset();
|
||||
}
|
||||
|
||||
//< 待回复的消息,非isValid表示还没有结果,无需回复
|
||||
kbd_net::CMbMessage objMsgRep;
|
||||
|
||||
if (nullptr == ptrIdResult)
|
||||
{
|
||||
//< 检查是否超时
|
||||
if (m_nStateStartTime + 30000 < nTimeNow)
|
||||
{
|
||||
std::string strRep = I18N("认证超时。");
|
||||
|
||||
objMsgRep.setSubject(CN_AppId_COMAPP, CH_BIS_TO_APP);
|
||||
objMsgRep.setMsgType(kbd_idlfile::MT_BIS_ID_RESULT);
|
||||
objMsgRep.setData(strRep);
|
||||
objMsgRep.setPara1(1); //< 0表示成功,其他值表示失败
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ptrIdResult->m_bPass)
|
||||
{
|
||||
kbd_idlfile::SBisIdResult objIdResult;
|
||||
objIdResult.set_user_id(ptrIdResult->m_nUserID);
|
||||
objIdResult.set_acs_dev_tag(m_strTagName);
|
||||
|
||||
if (ptrIdResult->m_strPicData.size() > 0)
|
||||
{
|
||||
//< 注意,内容被换走
|
||||
objIdResult.mutable_pic_data()->swap(ptrIdResult->m_strPicData);
|
||||
|
||||
//< 图片几乎不可压缩,关闭
|
||||
objMsgRep.m_enZipWhenSend = kbd_net::EN_MB_ZIP_DISABLE;
|
||||
}
|
||||
|
||||
objMsgRep.setSubject(CN_AppId_COMAPP, CH_BIS_TO_APP);
|
||||
objMsgRep.setMsgType(kbd_idlfile::MT_BIS_ID_RESULT);
|
||||
objMsgRep.setData(objIdResult);
|
||||
objMsgRep.setPara1(0); //< 0表示成功,其他值表示失败
|
||||
}
|
||||
else
|
||||
{
|
||||
//< 认证未成功,不处理,有超时机制
|
||||
LOGERROR("processStateMachine(): 不成功的认证在回调函数中已过滤,不应该运行到此处,检查程序!");
|
||||
}
|
||||
}
|
||||
|
||||
if (objMsgRep.isValid())
|
||||
{
|
||||
//< 回复消息
|
||||
if (m_objMbMsgReq.isValid())
|
||||
{
|
||||
//< objMsgRep 内容将被取走
|
||||
m_pParent->m_pMbComm->replyMsg(objMsgRep, m_objMbMsgReq);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGERROR("processStateMachine(): 请求认证的原始消息无效,请检查程序!");
|
||||
}
|
||||
|
||||
//< 清空请求原始消息
|
||||
m_objMbMsgReq.clear();
|
||||
|
||||
//< 设置状态
|
||||
m_enState = EN_STATE_IDLE;
|
||||
m_nStateStartTime = nTimeNow;
|
||||
|
||||
//< 关闭认证
|
||||
enableIdentification(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} //< namespace kbd_application
|
||||
@ -0,0 +1,108 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsDevice.h
|
||||
* @brief ACS设备类
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "boost/shared_ptr.hpp"
|
||||
#include "boost/thread/mutex.hpp"
|
||||
|
||||
#include "net_msg_bus_api/MsgBusApi.h"
|
||||
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
class CAcsWorkThread;
|
||||
|
||||
class CAcsDevice : private kbd_application::CAcsDeviceApi
|
||||
{
|
||||
public:
|
||||
CAcsDevice(CAcsWorkThread *pParent, const char *szTagName,
|
||||
const char *szIP, int nPort, const char *szUser, const char *szPwd);
|
||||
~CAcsDevice();
|
||||
|
||||
//< 处理消息,返回成功或失败
|
||||
bool handle_MT_BIS_START_ID_REQ(const kbd_net::CMbMessage &objMbMsgReq);
|
||||
bool handle_MT_BIS_CANCEL_ID(const kbd_net::CMbMessage &objMbMsgReq);
|
||||
|
||||
//< 处理状态机
|
||||
void processStateMachine();
|
||||
|
||||
private:
|
||||
enum EnState
|
||||
{
|
||||
EN_STATE_UNCONNECTED = 0, //< 尚未登录到设备
|
||||
EN_STATE_IDLE, //< 空闲
|
||||
EN_STATE_WAITE_RESULT, //< 等待认证结果
|
||||
};
|
||||
|
||||
class CIdResult
|
||||
{
|
||||
public:
|
||||
CIdResult()
|
||||
: m_bPass(false), m_nUserID(-1)
|
||||
{
|
||||
};
|
||||
|
||||
CIdResult(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData)
|
||||
: m_bPass(bPass), m_nUserID(nUserID), m_strPicData(pPicData, nPicDataLen)
|
||||
{
|
||||
};
|
||||
|
||||
~CIdResult()
|
||||
{
|
||||
};
|
||||
|
||||
bool m_bPass;
|
||||
int m_nUserID;
|
||||
std::string m_strPicData;
|
||||
};
|
||||
typedef boost::shared_ptr<CIdResult> CIdResultPtr;
|
||||
|
||||
private:
|
||||
void handleFaceInfo(bool bSuccess, size_t nDataLen, const char *pData, void *pUserData) override;
|
||||
|
||||
void handleFingerprintInfo(bool bSuccess, size_t nDataLen, const char *pData, void *pUserData) override;
|
||||
|
||||
void handleSetUserInfoResult(const std::list<kbd_application::CUserInfo> &listUserInfo, void *pUserData) override;
|
||||
|
||||
void handleIdentificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData) override;
|
||||
|
||||
public:
|
||||
const int m_nPort;
|
||||
const std::string m_strIp;
|
||||
const std::string m_strUser;
|
||||
const std::string m_strPwd;
|
||||
|
||||
//< 该ACS设备在本系统内的唯一标识
|
||||
const std::string m_strTagName;
|
||||
|
||||
private:
|
||||
//< 当前状态
|
||||
EnState m_enState;
|
||||
|
||||
CAcsWorkThread *const m_pParent;
|
||||
|
||||
//< 当前状态开始时间,用于计算超时,开机后时间
|
||||
boost::int64_t m_nStateStartTime;
|
||||
|
||||
//< 请求认证的原始消息,用于回复
|
||||
kbd_net::CMbMessage m_objMbMsgReq;
|
||||
|
||||
//< 认证结果
|
||||
CIdResultPtr m_ptrIdResult;
|
||||
|
||||
//< CAcsDeviceApi 的回调函数由其内部线程调用,防止与外部线程冲突
|
||||
boost::mutex m_mutexIdResult;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<CAcsDevice> CAcsDevicePtr;
|
||||
|
||||
} //< namespace kbd_application
|
||||
|
||||
@ -0,0 +1,280 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsWorkThread.h
|
||||
* @brief 处理ACS设备的相关工作
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#include "boost/typeof/typeof.hpp"
|
||||
#include "boost/lexical_cast.hpp"
|
||||
|
||||
//< 屏蔽Protobuff编译告警
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4100)
|
||||
#endif
|
||||
|
||||
#include "BioIdentifyMsg.pb.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
#include "common/Common.h"
|
||||
#include "common/MessageChannel.h"
|
||||
|
||||
#include "CAcsWorkThread.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
CAcsWorkThread::CAcsWorkThread() :
|
||||
CTimerThreadBase("CAcsWorkThread", 0),
|
||||
m_bIsRunning(false), m_nCfgVer_acs_device_info(0),
|
||||
m_pMbComm(nullptr), m_pMbMsgRcv(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CAcsWorkThread::~CAcsWorkThread()
|
||||
{
|
||||
suspendThread();
|
||||
quit();
|
||||
|
||||
delete m_pMbComm;
|
||||
delete m_pMbMsgRcv;
|
||||
}
|
||||
|
||||
|
||||
bool CAcsWorkThread::resumeThread()
|
||||
{
|
||||
if (isThreadRunning())
|
||||
return true;
|
||||
|
||||
if (!m_objRtdb_acs_device_info.open(CN_AppName_COMAPP.c_str(), "acs_device_info"))
|
||||
{
|
||||
LOGERROR("resumeThread(): 打开实时库 acs_device_info 表失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_objRtdb_acs_device_node_map.open(CN_AppName_COMAPP.c_str(), "acs_device_node_map"))
|
||||
{
|
||||
LOGERROR("resumeThread(): 打开实时库 acs_device_node_map 表失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 加载配置
|
||||
refreshCfg();
|
||||
|
||||
if (nullptr == m_pMbComm)
|
||||
m_pMbComm = new kbd_net::CMbCommunicator();
|
||||
|
||||
//< 订阅
|
||||
if (!m_pMbComm->addSub(0, CH_APP_TO_BIS))
|
||||
{
|
||||
LOGERROR("添加订阅失败!");
|
||||
|
||||
delete m_pMbComm;
|
||||
m_pMbComm = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nullptr == m_pMbMsgRcv)
|
||||
m_pMbMsgRcv = new kbd_net::CMbMessage();
|
||||
|
||||
m_bIsRunning = true;
|
||||
resume();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CAcsWorkThread::suspendThread()
|
||||
{
|
||||
m_bIsRunning = false;
|
||||
suspend();
|
||||
|
||||
//< 销毁通讯器
|
||||
delete m_pMbComm;
|
||||
m_pMbComm = nullptr;
|
||||
|
||||
//< 销毁消息
|
||||
delete m_pMbMsgRcv;
|
||||
m_pMbMsgRcv = nullptr;
|
||||
|
||||
//< 清空ACS设备实例
|
||||
{
|
||||
m_mapAcsDevice.clear();
|
||||
m_nCfgVer_acs_device_info = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CAcsWorkThread::isThreadRunning() const
|
||||
{
|
||||
return m_bIsRunning && isRunning();
|
||||
}
|
||||
|
||||
void CAcsWorkThread::refreshCfg()
|
||||
{
|
||||
//< todo 获取当前版本号,并与之前对比
|
||||
if (0 != m_nCfgVer_acs_device_info)
|
||||
return;
|
||||
m_nCfgVer_acs_device_info = 1;
|
||||
|
||||
m_mapAcsDevice.clear();
|
||||
|
||||
kbd_dbms::CVarType rdbVal_TAG_NAME, rdbVal_IP_ADDR, rdbVal_MNG_PORT, rdbVal_MNG_USER, rdbVal_MNG_PASSWD;
|
||||
|
||||
//< 锁表
|
||||
kbd_dbms::CTableLockGuard tableLock(m_objRtdb_acs_device_info);
|
||||
|
||||
const int nRcdCnt = m_objRtdb_acs_device_info.getRecordCount();
|
||||
for (int nRcdIdx = 0; nRcdIdx < nRcdCnt; ++nRcdIdx)
|
||||
{
|
||||
if (!m_objRtdb_acs_device_info.getColumnValueByIndex(nRcdIdx, "tag_name", rdbVal_TAG_NAME))
|
||||
{
|
||||
LOGERROR("refreshCfg(): 获取列值 tag_name 失败,跳过!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_objRtdb_acs_device_info.getColumnValueByIndex(nRcdIdx, "ip_addr", rdbVal_IP_ADDR))
|
||||
{
|
||||
LOGERROR("refreshCfg(): 获取列值 ip_addr 失败,跳过!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_objRtdb_acs_device_info.getColumnValueByIndex(nRcdIdx, "mng_port", rdbVal_MNG_PORT))
|
||||
{
|
||||
LOGERROR("refreshCfg(): 获取列值 mng_port 失败,跳过!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_objRtdb_acs_device_info.getColumnValueByIndex(nRcdIdx, "mng_user", rdbVal_MNG_USER))
|
||||
{
|
||||
LOGERROR("refreshCfg(): 获取列值 mng_user 失败,跳过!");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_objRtdb_acs_device_info.getColumnValueByIndex(nRcdIdx, "mng_passwd", rdbVal_MNG_PASSWD))
|
||||
{
|
||||
LOGERROR("refreshCfg(): 获取列值 mng_passwd 失败,跳过!");
|
||||
continue;
|
||||
}
|
||||
|
||||
CAcsDevicePtr ptrDev(new CAcsDevice(this, rdbVal_TAG_NAME.c_str(),
|
||||
rdbVal_IP_ADDR.c_str(), rdbVal_MNG_PORT.toInt(),
|
||||
rdbVal_MNG_USER.c_str(), rdbVal_MNG_PASSWD.c_str()));
|
||||
|
||||
if (false == m_mapAcsDevice.insert(std::make_pair(ptrDev->m_strTagName, ptrDev)).second)
|
||||
{
|
||||
LOGERROR("refreshCfg(): ACS设备TagName重复,非预期,检查程序!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CAcsWorkThread::execute()
|
||||
{
|
||||
if (!m_bIsRunning)
|
||||
return;
|
||||
|
||||
//< 刷新配置
|
||||
refreshCfg();
|
||||
|
||||
//< 处理消息
|
||||
for (int i = 0; m_bIsRunning && (i < 100); ++i)
|
||||
{
|
||||
if (!m_pMbComm->recvMsg(*m_pMbMsgRcv, 100))
|
||||
break;
|
||||
|
||||
handleOneMbMsg();
|
||||
}
|
||||
|
||||
//< 处理状态机
|
||||
for (BOOST_AUTO(itDev, m_mapAcsDevice.begin()); m_bIsRunning && m_mapAcsDevice.end() != itDev; ++itDev)
|
||||
{
|
||||
itDev->second->processStateMachine();
|
||||
}
|
||||
}
|
||||
|
||||
void CAcsWorkThread::handleOneMbMsg()
|
||||
{
|
||||
LOGINFO("handleOneMbMsg(): 收到来自节点 %s 的消息", m_pMbMsgRcv->getSrcHost());
|
||||
|
||||
if (CH_APP_TO_BIS != m_pMbMsgRcv->getChannelID())
|
||||
{
|
||||
LOGERROR("handleOneMbMsg(): 非预期的通道, 忽略,消息内容如下:\n%s", m_pMbMsgRcv->printInfoToStr().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string strRcvData((char *) m_pMbMsgRcv->getDataPtr(), m_pMbMsgRcv->getDataSize());
|
||||
if (strRcvData != "BIS")
|
||||
{
|
||||
LOGERROR("handleOneMbMsg(): 非预期的消息内容,忽略,消息内容如下:\n%s", m_pMbMsgRcv->printInfoToStr().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::string strSrcNode = m_pMbMsgRcv->getSrcHost();
|
||||
strSrcNode.resize(64); //< 注意,必须与列定义一致
|
||||
|
||||
kbd_dbms::CVarType rdbVal_ACS_DEVICE_TAG;
|
||||
|
||||
//< 查找该节点的ACS设备
|
||||
{
|
||||
//< 锁表
|
||||
kbd_dbms::CTableLockGuard tableLock(m_objRtdb_acs_device_node_map);
|
||||
|
||||
const int nRcdIdx = m_objRtdb_acs_device_node_map.searchRecordByKey(strSrcNode.c_str());
|
||||
if (nRcdIdx < 0)
|
||||
{
|
||||
LOGWARN("handleOneMbMsg(): 节点 %s 未配置ACS设备,忽略本请求。", strSrcNode.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_objRtdb_acs_device_node_map.getColumnValueByIndex(nRcdIdx, "acs_device_tag", rdbVal_ACS_DEVICE_TAG))
|
||||
{
|
||||
LOGERROR("handleOneMbMsg(): 获取列值 acs_device_tag 失败!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO(itDev, m_mapAcsDevice.find(rdbVal_ACS_DEVICE_TAG.toStdString()));
|
||||
if (m_mapAcsDevice.end() == itDev)
|
||||
{
|
||||
LOGERROR("handleOneMbMsg(): 未找到ACS设备实例,TagName = %s", rdbVal_ACS_DEVICE_TAG.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (m_pMbMsgRcv->getMsgType())
|
||||
{
|
||||
case kbd_idlfile::MT_BIS_START_ID_REQ:
|
||||
itDev->second->handle_MT_BIS_START_ID_REQ(*m_pMbMsgRcv);
|
||||
break;
|
||||
case kbd_idlfile::MT_BIS_CANCEL_ID:
|
||||
itDev->second->handle_MT_BIS_CANCEL_ID(*m_pMbMsgRcv);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LOGERROR("handleOneMbMsg(): 非预期的消息类型, 忽略,消息内容如下:\n%s", m_pMbMsgRcv->printInfoToStr().c_str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} //< namespace kbd_application
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CAcsWorkThread.h
|
||||
* @brief 处理ACS设备的相关工作
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "pub_utility_api/TimerThreadBase.h"
|
||||
#include "net_msg_bus_api/MsgBusApi.h"
|
||||
#include "rdb_api/CRdbAccess.h"
|
||||
|
||||
#include "CAcsDevice.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
class CAcsWorkThread : private kbd_public::CTimerThreadBase
|
||||
{
|
||||
friend class CAcsDevice;
|
||||
|
||||
public:
|
||||
CAcsWorkThread();
|
||||
|
||||
virtual ~CAcsWorkThread();
|
||||
|
||||
//< 线程正在运行时调用,安全,返回true
|
||||
bool resumeThread();
|
||||
|
||||
bool suspendThread();
|
||||
|
||||
bool isThreadRunning() const;
|
||||
|
||||
private:
|
||||
void execute() override;
|
||||
|
||||
void refreshCfg();
|
||||
|
||||
void handleOneMbMsg();
|
||||
|
||||
private:
|
||||
volatile bool m_bIsRunning;
|
||||
|
||||
//< 实时库 acs_device_info 表的配置版本号,当前实时库暂不支持,计划中会有
|
||||
int m_nCfgVer_acs_device_info;
|
||||
|
||||
kbd_net::CMbCommunicator *m_pMbComm; //< 消息总线通讯器
|
||||
kbd_net::CMbMessage *m_pMbMsgRcv; //< 接收的消息总线消息
|
||||
|
||||
//< 实时库访问接口
|
||||
kbd_dbms::CRdbAccess m_objRtdb_acs_device_info;
|
||||
kbd_dbms::CRdbAccess m_objRtdb_acs_device_node_map;
|
||||
|
||||
std::map<std::string, CAcsDevicePtr> m_mapAcsDevice;
|
||||
};
|
||||
|
||||
} //< namespace kbd_application
|
||||
|
||||
@ -0,0 +1,350 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CBioIdentifySrv.cpp
|
||||
* @brief 生物识别服务,服务框架
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#include "boost/program_options.hpp"
|
||||
#include "boost/algorithm/string/predicate.hpp"
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
#include "pub_utility_api/I18N.h"
|
||||
#include "pub_utility_api/SingleProcInstance.h"
|
||||
#include "pub_sysinfo_api/SysInfoApi.h"
|
||||
#include "net_msg_bus_api/MsgBusApi.h"
|
||||
|
||||
#include "CBioIdentifySrv.h"
|
||||
|
||||
|
||||
#define BIS_PROC_NAME "app_bio_identify_srv"
|
||||
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
CBioIdentifySrv::CBioIdentifySrv()
|
||||
: m_enRunModel(RM_NORMAL),
|
||||
m_nDomainID(0),
|
||||
m_strNodeName(""),
|
||||
m_ptrRedunSw(nullptr),
|
||||
m_ptrProcMng(nullptr),
|
||||
m_ptrRedundantMng(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CBioIdentifySrv::~CBioIdentifySrv()
|
||||
{
|
||||
stop();
|
||||
|
||||
kbd_public::StopLogSystem();
|
||||
}
|
||||
|
||||
|
||||
//< @param int & nStatus 错误码
|
||||
bool CBioIdentifySrv::start(int argc, char *argv[], int & /*nStatus*/)
|
||||
{
|
||||
assert(!m_ptrRedunSw); //< nullptr
|
||||
|
||||
//< 参数解析
|
||||
if (!parseCommandLine(argc, argv))
|
||||
{
|
||||
std::cerr << "参数解析失败" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 启动日志
|
||||
kbd_public::StartLogSystem(CN_AppName_COMAPP.c_str(), BIS_PROC_NAME);
|
||||
|
||||
//< 判断是否已启动
|
||||
if (isAlreadyRunning())
|
||||
{
|
||||
LOGFATAL(BIS_PROC_NAME" 已启动,不可重复启动,本实例退出!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 加载系统建模信息
|
||||
if (!loadSysInfo())
|
||||
{
|
||||
LOGFATAL("加载系统建模信息失败,程序启动失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 消息总线
|
||||
if (!kbd_net::initMsgBus(BIS_PROC_NAME, "", true))
|
||||
{
|
||||
LOGFATAL("初始化消息总线失败,程序启动失败!");
|
||||
return false;
|
||||
}
|
||||
|
||||
//< 初始化翻译
|
||||
if (kbd_public::initI18N("/app_bio_identify_srv/translate", "app_bio_identify_srv"))
|
||||
{
|
||||
LOGDEBUG(I18N_C("I18N output test:\n This is src hardcode. \n int = [%d] , str = [%s]\n"), 123, "test");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGWARN("国际化初始化失败!");
|
||||
}
|
||||
|
||||
//< CAcsWorkThread 由 m_ptrRedunSw 管理
|
||||
|
||||
//< 初始化 m_ptrRedunSw
|
||||
m_ptrRedunSw.reset(new CBisRedunSw());
|
||||
|
||||
switch (m_enRunModel)
|
||||
{
|
||||
case RM_NORMAL:
|
||||
{
|
||||
//< 进程管理
|
||||
{
|
||||
std::string strStartArgs;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
if (i != 1)
|
||||
{
|
||||
strStartArgs += " ";
|
||||
}
|
||||
|
||||
strStartArgs += argv[i];
|
||||
}
|
||||
|
||||
kbd_sys::SProcessInfoKey objProcInfo;
|
||||
objProcInfo.nAppId = CN_AppId_COMAPP;
|
||||
objProcInfo.nDomainId = m_nDomainID;
|
||||
objProcInfo.strNodeName = m_strNodeName;
|
||||
objProcInfo.strProcName = BIS_PROC_NAME;
|
||||
objProcInfo.strProcParam = strStartArgs;
|
||||
|
||||
m_ptrProcMng = kbd_sys::getProcMngInstance(objProcInfo);
|
||||
if (!m_ptrProcMng)
|
||||
{
|
||||
LOGFATAL("getProcMngInstance return nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ptrProcMng->setCallback(this);
|
||||
}
|
||||
|
||||
//< 冗余管理
|
||||
{
|
||||
m_ptrRedundantMng = kbd_sys::getRedundantMngInstance(m_nDomainID, CN_AppId_COMAPP, m_strNodeName);
|
||||
if (!m_ptrRedundantMng)
|
||||
{
|
||||
LOGERROR("getRedundantMngInstance return nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ptrRedundantMng->setCallback(m_ptrRedunSw);
|
||||
}
|
||||
|
||||
//< 更新进程管理状态
|
||||
updateProcInfo(true, false, false);
|
||||
}
|
||||
break;
|
||||
case RM_NO_PROC_MNG_MASTER:
|
||||
{
|
||||
if (kbdSuccess != m_ptrRedunSw->redundantSwitch(true, false))
|
||||
{
|
||||
LOGFATAL("以主机模式启动失败!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RM_NO_PROC_MNG_SLAVE:
|
||||
{
|
||||
if (kbdSuccess != m_ptrRedunSw->redundantSwitch(false, true))
|
||||
{
|
||||
LOGFATAL("以备机模式启动失败!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LOGFATAL("非预期的启动模式,程序启动失败!");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
LOGINFO(BIS_PROC_NAME" is now running ...");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CBioIdentifySrv::stop()
|
||||
{
|
||||
LOGINFO(BIS_PROC_NAME" is now exiting ...");
|
||||
|
||||
//< 取消冗余切换,防止正在退出时发生冗余切换
|
||||
if (m_ptrRedundantMng)
|
||||
{
|
||||
//LOGDEBUG("Release m_ptrRedundantMng ...");
|
||||
|
||||
m_ptrRedundantMng->unsetCallback();
|
||||
m_ptrRedundantMng.reset();
|
||||
|
||||
//LOGDEBUG("Release m_ptrRedundantMng complete !");
|
||||
}
|
||||
|
||||
//< 释放 m_ptrRedunSw
|
||||
if (m_ptrRedunSw)
|
||||
{
|
||||
//LOGDEBUG("Release m_ptrRedunSw ...");
|
||||
|
||||
m_ptrRedunSw.reset();
|
||||
|
||||
//LOGDEBUG("Release m_ptrRedunSw complete !");
|
||||
}
|
||||
|
||||
//< 取消进程管理回调
|
||||
//if (m_ptrProcMng)
|
||||
//{
|
||||
// m_ptrProcMng->unsetCallback();
|
||||
//}
|
||||
|
||||
//< 清理业务线程
|
||||
//< 更新进程管理状态
|
||||
if (m_ptrProcMng)
|
||||
{
|
||||
//LOGDEBUG("Release m_ptrProcMng ...");
|
||||
|
||||
updateProcInfo(false, false, false);
|
||||
m_ptrProcMng.reset();
|
||||
|
||||
//LOGDEBUG("Release m_ptrProcMng complete !");
|
||||
}
|
||||
|
||||
//< 停止消息总线
|
||||
kbd_net::releaseMsgBus();
|
||||
|
||||
//< 停止日志系统
|
||||
//< 移到析构函数中,防止日志库停止后,又写日志,从而使log4cplus提示找不到logger
|
||||
//kbd_public::StopLogSystem();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int CBioIdentifySrv::toQuit()
|
||||
{
|
||||
shutdown();
|
||||
return kbdSuccess;
|
||||
}
|
||||
|
||||
|
||||
int CBioIdentifySrv::updateProcInfo(bool bActive, bool bMaster, bool bSlave)
|
||||
{
|
||||
if (m_ptrProcMng)
|
||||
{
|
||||
return m_ptrProcMng->updateProcessInfo(bActive, bMaster, bSlave);
|
||||
}
|
||||
|
||||
return kbdFailed;
|
||||
}
|
||||
|
||||
|
||||
bool CBioIdentifySrv::isAlreadyRunning()
|
||||
{
|
||||
return kbd_public::CSingleProcInstance::hasInstanceRunning(BIS_PROC_NAME);
|
||||
}
|
||||
|
||||
|
||||
bool CBioIdentifySrv::parseCommandLine(int argc, char *argv[])
|
||||
{
|
||||
namespace po = boost::program_options;
|
||||
po::options_description desc("usage");
|
||||
po::variables_map vm;
|
||||
try
|
||||
{
|
||||
desc.add_options()
|
||||
("app"",a", po::value<std::string>(), "\t""The APP name, can only ran as COMAPP")
|
||||
("no_proc_mng_master"",m", "\t""Run as master without ProcMng and RedundantMng")
|
||||
("no_proc_mng_slave"",s", "\t""Run as slave without ProcMng and RedundantMng")
|
||||
("help"",h", "\t""Print this info");
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
if (vm.count("help"))
|
||||
{
|
||||
std::cout << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vm.count("no_proc_mng_master") && vm.count("no_proc_mng_slave"))
|
||||
{
|
||||
std::cout << "no_proc_mng_master and no_proc_mng_slave can not use at the same time !" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 != vm.count("app")
|
||||
&& !(boost::algorithm::iequals(vm["app"].as<std::string>(), CN_AppName_COMAPP)))
|
||||
{
|
||||
std::cout << "Can only ran as COMAPP app !" << std::endl;
|
||||
//return false;
|
||||
}
|
||||
|
||||
if (vm.count("no_proc_mng_master"))
|
||||
{
|
||||
m_enRunModel = RM_NO_PROC_MNG_MASTER;
|
||||
}
|
||||
else if (vm.count("no_proc_mng_slave"))
|
||||
{
|
||||
m_enRunModel = RM_NO_PROC_MNG_SLAVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_enRunModel = RM_NORMAL;
|
||||
}
|
||||
}
|
||||
catch (std::exception &ex)
|
||||
{
|
||||
std::cerr << ex.what() << std::endl;
|
||||
std::cout << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "未知错误" << std::endl;
|
||||
std::cout << desc << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBioIdentifySrv::loadSysInfo()
|
||||
{
|
||||
kbd_public::CSysInfoInterfacePtr sysInfoPtr;
|
||||
if (kbd_public::createSysInfoInstance(sysInfoPtr) == false)
|
||||
{
|
||||
LOGERROR("loadSysInfo(): createSysInfoInstance() return false !");
|
||||
return false;
|
||||
}
|
||||
|
||||
kbd_public::SRunAppInfo objRunAppInfo;
|
||||
int nRc = sysInfoPtr->getLocalRunAppInfoById(CN_AppId_COMAPP, objRunAppInfo);
|
||||
if (kbdSuccess != nRc)
|
||||
{
|
||||
LOGERROR("loadSysInfo(): getLocalRunAppInfoByName failed !");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nDomainID = objRunAppInfo.nDomainId;
|
||||
m_strNodeName = objRunAppInfo.strLocalNodeName;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CBioIdentifySrv::getDomainID() const
|
||||
{
|
||||
return m_nDomainID;
|
||||
}
|
||||
|
||||
} //< namespace kbd_application
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CBioIdentifySrv.h
|
||||
* @brief 生物识别服务,服务框架
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pub_utility_api/BaseService.h"
|
||||
#include "sys_proc_mng_api/ProcMngInterface.h"
|
||||
|
||||
#include "CBisRedunSw.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
class CBioIdentifySrv : public kbd_public::CBaseService, kbd_sys::CProcessQuitInterface
|
||||
{
|
||||
public:
|
||||
CBioIdentifySrv();
|
||||
~CBioIdentifySrv();
|
||||
|
||||
//< 设置进程状态
|
||||
int updateProcInfo(bool bActive, bool bMaster, bool bSlave);
|
||||
|
||||
int getDomainID() const;
|
||||
|
||||
private:
|
||||
|
||||
//< 见父类CBaseService说明
|
||||
bool start(int argc, char *argv[], int &nStatus) override;
|
||||
|
||||
//< 见父类CBaseService说明
|
||||
bool stop() override;
|
||||
|
||||
//< 见父类CProcessQuitInterface说明
|
||||
int toQuit() override;
|
||||
|
||||
bool isAlreadyRunning();
|
||||
|
||||
bool parseCommandLine(int argc, char *argv[]);
|
||||
|
||||
bool loadSysInfo();
|
||||
|
||||
enum enRunModel
|
||||
{
|
||||
RM_NORMAL = 0, //< 正常模式
|
||||
RM_NO_PROC_MNG_MASTER, //< 不注册进程管理、冗余管理,主机模式
|
||||
RM_NO_PROC_MNG_SLAVE, //< 不注册进程管理、冗余管理,备机模式
|
||||
};
|
||||
|
||||
private:
|
||||
enRunModel m_enRunModel;
|
||||
|
||||
int m_nDomainID; //< 本域ID
|
||||
std::string m_strNodeName; //< 本机节点名
|
||||
|
||||
CCBisRedunSwPtr m_ptrRedunSw;
|
||||
kbd_sys::CProcMngInterfacePtr m_ptrProcMng;
|
||||
kbd_sys::CRedundantMngInterfacePtr m_ptrRedundantMng;
|
||||
};
|
||||
|
||||
} //< namespace kbd_application
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CBisRedunSw.cpp
|
||||
* @brief 生物识别服务,冗余切换类
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#include "CBioIdentifySrv.h"
|
||||
|
||||
#include "CBisRedunSw.h"
|
||||
|
||||
extern kbd_application::CBioIdentifySrv *g_pBioIdentifySrv;
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
CBisRedunSw::CBisRedunSw()
|
||||
{
|
||||
}
|
||||
|
||||
CBisRedunSw::~CBisRedunSw()
|
||||
{
|
||||
//< m_objAcsWorkThread 析构时会 quit()
|
||||
}
|
||||
|
||||
int CBisRedunSw::redundantSwitch(bool bMaster, bool bSlave)
|
||||
{
|
||||
//< 当前逻辑 bSlave 无需使用
|
||||
|
||||
if (bMaster)
|
||||
{
|
||||
m_objAcsWorkThread.resumeThread();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_objAcsWorkThread.suspendThread();
|
||||
}
|
||||
|
||||
g_pBioIdentifySrv->updateProcInfo(true, m_objAcsWorkThread.isThreadRunning(), bSlave);
|
||||
|
||||
return kbdSuccess;
|
||||
}
|
||||
|
||||
} //< namespace kbd_application
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file CBisRedunSw.h
|
||||
* @brief 生物识别服务,冗余切换类
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sys_node_mng_api/NodeMngInterface.h"
|
||||
|
||||
#include "CAcsWorkThread.h"
|
||||
|
||||
namespace kbd_application
|
||||
{
|
||||
|
||||
class CBisRedunSw : public ::kbd_sys::CRedundantSwitchInterface
|
||||
{
|
||||
public:
|
||||
CBisRedunSw();
|
||||
virtual ~CBisRedunSw();
|
||||
|
||||
public:
|
||||
//< 见父类CRedundantSwitchInterface说明
|
||||
int redundantSwitch(bool bMaster, bool bSlave) override;
|
||||
|
||||
private:
|
||||
CAcsWorkThread m_objAcsWorkThread;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<CBisRedunSw> CCBisRedunSwPtr;
|
||||
|
||||
} //< namespace kbd_application
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file Main.cpp
|
||||
* @brief 生物识别服务程序入口
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#include "CBioIdentifySrv.h"
|
||||
|
||||
kbd_application::CBioIdentifySrv *g_pBioIdentifySrv = nullptr;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
kbd_application::CBioIdentifySrv objApp;
|
||||
g_pBioIdentifySrv = &objApp;
|
||||
return objApp.main(argc, argv);
|
||||
}
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
|
||||
QT -= gui core
|
||||
CONFIG -= qt
|
||||
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = app_bio_identify_srv
|
||||
|
||||
LIBS += -lboost_chrono -lboost_system -lboost_program_options -lboost_locale -lprotobuf -llog4cplus \
|
||||
-lpub_logger_api -lpub_utility_api -lpub_sysinfo_api \
|
||||
-lsys_proc_mng_api -lsys_node_mng_api \
|
||||
-lnet_msg_bus_api -lrdb_api -lacs_device_api
|
||||
|
||||
|
||||
HEADERS += $$PWD/../../../idl_files/BioIdentifyMsg.pb.h \
|
||||
BisCommon.h \
|
||||
CAcsDevice.h \
|
||||
CAcsWorkThread.h \
|
||||
CBioIdentifySrv.h \
|
||||
CBisRedunSw.h
|
||||
|
||||
SOURCES += Main.cpp \
|
||||
BisCommon.cpp \
|
||||
CAcsDevice.cpp \
|
||||
CAcsWorkThread.cpp \
|
||||
CBioIdentifySrv.cpp \
|
||||
CBisRedunSw.cpp
|
||||
|
||||
include($$PWD/../../../idl_files/idl_files.pri)
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
COMMON_PRI=$$PWD/../../../common.pri
|
||||
exists($$COMMON_PRI) {
|
||||
include($$COMMON_PRI)
|
||||
}else {
|
||||
error("FATAL error: can not find common.pri")
|
||||
}
|
||||
|
||||
#必须在common.pri之后包含
|
||||
#-------------------------------------------------------------------
|
||||
HIKVISION_PRI=$$PWD/../../../3rd/include/hikvision/hikvision.pri
|
||||
exists($$HIKVISION_PRI) {
|
||||
include($$HIKVISION_PRI)
|
||||
}else {
|
||||
error("FATAL error: can not find hikvision.pri")
|
||||
}
|
||||
|
||||
@ -0,0 +1,149 @@
|
||||
|
||||
/******************************************************************************//**
|
||||
* @file
|
||||
* @brief
|
||||
* @author yikenan
|
||||
* @version 1.0
|
||||
* @date
|
||||
**********************************************************************************/
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "boost/thread.hpp"
|
||||
#include "boost/chrono.hpp"
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
|
||||
#include "net_msg_bus_api/MsgBusApi.h"
|
||||
#include "perm_mng_api/PermMngApi.h"
|
||||
|
||||
static volatile bool g_bNeedExit = false;
|
||||
|
||||
static void signalCallback(int /*sig*/)
|
||||
{
|
||||
std::cout << "signalCallback()" << std::endl;
|
||||
|
||||
g_bNeedExit = true;
|
||||
}
|
||||
|
||||
void test()
|
||||
{
|
||||
kbd_service::CPermMngApiPtr ptrPermMng = kbd_service::getPermMngInstance("PUBLIC");
|
||||
|
||||
ptrPermMng->PermDllInit();
|
||||
ptrPermMng->startBioIdentify();
|
||||
|
||||
int nRc;
|
||||
std::string strUserName, strTempPasswd, strAcsDevTag, strPic, strErr;
|
||||
while (!g_bNeedExit)
|
||||
{
|
||||
strUserName.clear();
|
||||
strTempPasswd.clear();
|
||||
strAcsDevTag.clear();
|
||||
strPic.clear();
|
||||
strErr.clear();
|
||||
|
||||
nRc = ptrPermMng->getBioIdentifyResult(strUserName, strTempPasswd, strAcsDevTag, strPic, strErr);
|
||||
switch (nRc)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
std::cout << "getBioIdentifyResult return 0" << std::endl;
|
||||
|
||||
std::cout << "strUserName : \t" << strUserName << std::endl;
|
||||
std::cout << "strTempPasswd : \t" << strTempPasswd << std::endl;
|
||||
std::cout << "strAcsDevTag : \t" << strAcsDevTag << std::endl;
|
||||
std::cout << "strPic.size() : \t" << strPic.size() << std::endl;
|
||||
std::cout << "strErr : \t" << strErr << std::endl;
|
||||
|
||||
std::vector<SUsergIdName> vecUsergInfo;
|
||||
ptrPermMng->GetUsergByUserName(strUserName, vecUsergInfo);
|
||||
|
||||
if (vecUsergInfo.empty())
|
||||
{
|
||||
std::cout << "GetUsergByUserName failed" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 == ptrPermMng->SysLogin(strUserName, strTempPasswd, vecUsergInfo[0].userg_id, 60,
|
||||
"PUBLIC"))
|
||||
{
|
||||
std::cout << "SysLogin success" << std::endl;
|
||||
ptrPermMng->SysLogout();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "SysLogin failed" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
g_bNeedExit = true;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
std::cout << "getBioIdentifyResult return 1" << std::endl;
|
||||
std::cout << "strErr : \t" << strErr << std::endl;
|
||||
g_bNeedExit = true;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
std::cout << "getBioIdentifyResult return 2" << std::endl;
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(1));
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
std::cout << "getBioIdentifyResult return 3" << std::endl;
|
||||
std::cout << "strErr : \t" << strErr << std::endl;
|
||||
g_bNeedExit = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char ** /*argv[]*/)
|
||||
{
|
||||
signal(SIGTERM, signalCallback);
|
||||
signal(SIGINT, signalCallback);
|
||||
#ifdef WIN32
|
||||
signal(SIGBREAK, signalCallback);
|
||||
#else
|
||||
signal(SIGQUIT, signalCallback);
|
||||
#endif
|
||||
|
||||
//< 启动日志
|
||||
kbd_public::StartLogSystem("default", "test_bis_client");
|
||||
|
||||
LOGINFO("Log system OK !");
|
||||
|
||||
//< 初始化消息总线库
|
||||
if (!(kbd_net::initMsgBus("net_msg_bus_test_client", "1")))
|
||||
{
|
||||
std::cout << "Initialize message bus failed, exit !" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Initialize message bus successed !" << std::endl;
|
||||
}
|
||||
|
||||
test();
|
||||
|
||||
boost::this_thread::sleep_for(boost::chrono::seconds(2));
|
||||
|
||||
//< 释放消息总线库
|
||||
kbd_net::releaseMsgBus();
|
||||
|
||||
//< 停止日志系统
|
||||
kbd_public::StopLogSystem();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
|
||||
QT -= gui core
|
||||
CONFIG -= qt
|
||||
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = test_bis_client
|
||||
|
||||
LIBS += -lboost_system -lboost_thread -lboost_chrono -llog4cplus -lpub_logger_api -lnet_msg_bus_api -lperm_mng_api
|
||||
|
||||
win32{
|
||||
LIBS += -lboost_date_time
|
||||
}
|
||||
else{
|
||||
LIBS += -lpthread
|
||||
}
|
||||
|
||||
|
||||
#HEADERS +=
|
||||
|
||||
SOURCES += main.cpp
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
COMMON_PRI=$$PWD/../../../../common.pri
|
||||
exists($$COMMON_PRI) {
|
||||
include($$COMMON_PRI)
|
||||
}else {
|
||||
error("FATAL error: can not find common.pri")
|
||||
}
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "pub_logger_api/logger.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
kbd_public::StartLogSystem("", "");
|
||||
|
||||
LOGINFO("test_hk_acs start !");
|
||||
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
a.exec();
|
||||
}
|
||||
|
||||
kbd_public::StopLogSystem();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,384 @@
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
using namespace kbd_application;
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent), ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
qRegisterMetaType<std::string>("std::string");
|
||||
qRegisterMetaType<std::list<kbd_application::CUserInfo>>("std::list<kbd_application::CUserInfo>");
|
||||
qRegisterMetaType<size_t>("size_t");
|
||||
|
||||
connect(this, SIGNAL(faceInfoFinish(bool, std::string, void * )),
|
||||
this, SLOT(on_faceInfoFinish(bool, std::string, void * )));
|
||||
|
||||
connect(this, SIGNAL(fingerprintInfoFinish(bool, std::string, void * )),
|
||||
this, SLOT(on_fingerprintInfoFinish(bool, std::string, void * )));
|
||||
|
||||
connect(this, SIGNAL(setUserInfoFinish(std::list<kbd_application::CUserInfo>, void * )),
|
||||
this, SLOT(on_setUserInfoFinish(std::list<kbd_application::CUserInfo>, void * )));
|
||||
|
||||
connect(this, SIGNAL(identificationEvent(bool, int, size_t, const char *)),
|
||||
this, SLOT(on_identificationEvent(bool, int, size_t, const char *)));
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
//< 接口库内部包含线程,继承本类的子类析构前,建议显式调用 logOutFromDevice 函数退出登录,
|
||||
//< 以便内部线程停止处理,防止析构过程中内部线程调用回调处理函数,导致问题
|
||||
logOutFromDevice();
|
||||
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::handleFaceInfo(bool bSuccess, size_t nDataLen, const char *pData, void *pUserData)
|
||||
{
|
||||
std::string strData(pData, nDataLen);
|
||||
emit faceInfoFinish(bSuccess, strData, pUserData);
|
||||
}
|
||||
|
||||
void MainWindow::handleFingerprintInfo(bool bSuccess, size_t nDataLen, const char *pData, void *pUserData)
|
||||
{
|
||||
std::string strData(pData, nDataLen);
|
||||
emit fingerprintInfoFinish(bSuccess, strData, pUserData);
|
||||
}
|
||||
|
||||
void MainWindow::handleSetUserInfoResult(const std::list<kbd_application::CUserInfo> &listUserInfo, void *pUserData)
|
||||
{
|
||||
emit setUserInfoFinish(listUserInfo, pUserData);
|
||||
}
|
||||
|
||||
void MainWindow::handleIdentificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData)
|
||||
{
|
||||
emit identificationEvent(bPass, nUserID, nPicDataLen, pPicData);
|
||||
}
|
||||
|
||||
void MainWindow::on_faceInfoFinish(bool bSuccess, std::string strData, void *pUserData)
|
||||
{
|
||||
std::string *pStrData = (std::string *) pUserData;
|
||||
QPushButton *pBtn = nullptr;
|
||||
|
||||
if (&m_strUser1_Face == pStrData)
|
||||
{
|
||||
pBtn = ui->btnCapUser1Face;
|
||||
}
|
||||
else if (&m_strUser2_Face == pStrData)
|
||||
{
|
||||
pBtn = ui->btnCapUser2Face;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "老实交代,从哪里调用过来的!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bSuccess)
|
||||
{
|
||||
QMessageBox::information(this, "", "采集成功!");
|
||||
*pStrData = strData;
|
||||
pBtn->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "采集失败!");
|
||||
pStrData->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_fingerprintInfoFinish(bool bSuccess, std::string strData, void *pUserData)
|
||||
{
|
||||
std::string *pStrData = (std::string *) pUserData;
|
||||
QPushButton *pBtn = nullptr;
|
||||
|
||||
if (&m_strUser1_Fp1 == pStrData)
|
||||
{
|
||||
pBtn = ui->btnCapUser1Fp1;
|
||||
}
|
||||
else if (&m_strUser1_Fp2 == pStrData)
|
||||
{
|
||||
pBtn = ui->btnCapUser1Fp2;
|
||||
}
|
||||
else if (&m_strUser2_Fp1 == pStrData)
|
||||
{
|
||||
pBtn = ui->btnCapUser2Fp1;
|
||||
}
|
||||
else if (&m_strUser2_Fp2 == pStrData)
|
||||
{
|
||||
pBtn = ui->btnCapUser2Fp2;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "老实交代,从哪里调用过来的!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bSuccess)
|
||||
{
|
||||
QMessageBox::information(this, "", "采集成功!");
|
||||
*pStrData = strData;
|
||||
pBtn->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "采集失败!");
|
||||
pStrData->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_setUserInfoFinish(std::list<kbd_application::CUserInfo> listUserInfo, void *pUserData)
|
||||
{
|
||||
(void) pUserData;
|
||||
|
||||
bool bSuccess = true;
|
||||
|
||||
for (std::list<kbd_application::CUserInfo>::const_iterator itUser = listUserInfo.cbegin();
|
||||
listUserInfo.cend() != itUser; ++itUser)
|
||||
{
|
||||
if (!itUser->m_bSetCarSuccess)
|
||||
{
|
||||
bSuccess = false;
|
||||
//< 测试程序简化处理,真实程序建议列表展示,不要弹窗,可能很多
|
||||
QMessageBox::critical(this, "",
|
||||
QString("用户下发失败,用户id=%1,用户名=%2").arg(itUser->m_nId).arg(itUser->m_strName.c_str()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (itUser->m_strFaceData.size() > 0 && !itUser->m_bSetFaceSuccess)
|
||||
{
|
||||
bSuccess = false;
|
||||
//< 测试程序简化处理,真实程序建议列表展示,不要弹窗,可能很多
|
||||
QMessageBox::critical(this, "", QString("人脸下发失败,用户id=%1,用户名=%2").arg(itUser->m_nId).arg(
|
||||
itUser->m_strName.c_str()));
|
||||
}
|
||||
|
||||
const std::list<kbd_application::CFingerprintInfo> &listFp = itUser->m_listFingerprint;
|
||||
for (std::list<kbd_application::CFingerprintInfo>::const_iterator itFp = listFp.cbegin();
|
||||
listFp.cend() != itFp; ++itFp)
|
||||
{
|
||||
if (!itFp->m_bSetSuccess)
|
||||
{
|
||||
bSuccess = false;
|
||||
//< 测试程序简化处理,真实程序建议列表展示,不要弹窗,可能很多
|
||||
QMessageBox::critical(this, "", QString("指纹下发失败,用户id=%1,用户名=%2,指纹id=%3")
|
||||
.arg(itUser->m_nId).arg(itUser->m_strName.c_str()).arg((int) (itFp->m_nId)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bSuccess)
|
||||
{
|
||||
QMessageBox::information(this, "", "下装成功!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_identificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData)
|
||||
{
|
||||
(void) pPicData;
|
||||
QMessageBox::information(this, "认证事件", QString("bPass=%1, nUserID=%2, nPicDataLen=%3")
|
||||
.arg(bPass).arg(nUserID).arg(nPicDataLen));
|
||||
}
|
||||
|
||||
void MainWindow::on_btnLogin_clicked()
|
||||
{
|
||||
if (logInToDevice("192.168.79.135", 8000, "admin", "kbdct@0755"))
|
||||
{
|
||||
QMessageBox::information(this, "", "登录成功!");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "登录失败!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnLogout_clicked()
|
||||
{
|
||||
if (logOutFromDevice())
|
||||
{
|
||||
QMessageBox::information(this, "", "登出成功!");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "登出失败!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnCapUser1Face_clicked()
|
||||
{
|
||||
if (captureFaceInfo(&m_strUser1_Face))
|
||||
{
|
||||
QMessageBox::information(this, "", "开始采集,请在设备上按提示操作!");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "启动采集失败!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnCapUser1Fp1_clicked()
|
||||
{
|
||||
if (captureFingerprintInfo(&m_strUser1_Fp1))
|
||||
{
|
||||
QMessageBox::information(this, "", "开始采集,请在设备上按提示操作!");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "启动采集失败!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnCapUser1Fp2_clicked()
|
||||
{
|
||||
if (captureFingerprintInfo(&m_strUser1_Fp2))
|
||||
{
|
||||
QMessageBox::information(this, "", "开始采集,请在设备上按提示操作!");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "启动采集失败!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnCapUser2Face_clicked()
|
||||
{
|
||||
if (captureFaceInfo(&m_strUser2_Face))
|
||||
{
|
||||
QMessageBox::information(this, "", "开始采集,请在设备上按提示操作!");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "启动采集失败!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnCapUser2Fp1_clicked()
|
||||
{
|
||||
if (captureFingerprintInfo(&m_strUser2_Fp1))
|
||||
{
|
||||
QMessageBox::information(this, "", "开始采集,请在设备上按提示操作!");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "启动采集失败!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnCapUser2Fp2_clicked()
|
||||
{
|
||||
if (captureFingerprintInfo(&m_strUser2_Fp2))
|
||||
{
|
||||
QMessageBox::information(this, "", "开始采集,请在设备上按提示操作!");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "启动采集失败!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnSetToDev_clicked()
|
||||
{
|
||||
std::list<CUserInfo> listUserInfo(2);
|
||||
|
||||
{
|
||||
std::list<CUserInfo>::iterator it = listUserInfo.begin();
|
||||
|
||||
//< 无效的指纹本不应该传入给下发函数,这里为了测试接口库处理异常的能力,所以不判是否有效,都传入
|
||||
|
||||
it->m_nId = 1;
|
||||
it->m_strName = "yikenan";
|
||||
it->m_strFaceData = m_strUser1_Face;
|
||||
it->m_listFingerprint.emplace_back(1, m_strUser1_Fp1);
|
||||
it->m_listFingerprint.emplace_back(2, m_strUser1_Fp2);
|
||||
|
||||
++it;
|
||||
it->m_nId = 2;
|
||||
it->m_strName = "易柯楠";
|
||||
it->m_strFaceData = m_strUser2_Face;
|
||||
it->m_listFingerprint.emplace_back(1, m_strUser2_Fp1);
|
||||
it->m_listFingerprint.emplace_back(2, m_strUser2_Fp2);
|
||||
}
|
||||
|
||||
if (setUserInfoToDevice(listUserInfo, nullptr))
|
||||
{
|
||||
QMessageBox::information(this, "", "开始下装,请稍等");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "启动下装失败!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnClearLocal_clicked()
|
||||
{
|
||||
m_strUser1_Face.clear();
|
||||
m_strUser1_Fp1.clear();
|
||||
m_strUser1_Fp2.clear();
|
||||
|
||||
m_strUser2_Face.clear();
|
||||
m_strUser2_Fp1.clear();
|
||||
m_strUser2_Fp2.clear();
|
||||
|
||||
ui->btnCapUser1Face->setEnabled(true);
|
||||
ui->btnCapUser1Fp1->setEnabled(true);
|
||||
ui->btnCapUser1Fp2->setEnabled(true);
|
||||
|
||||
ui->btnCapUser2Face->setEnabled(true);
|
||||
ui->btnCapUser2Fp1->setEnabled(true);
|
||||
ui->btnCapUser2Fp2->setEnabled(true);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::on_btnEnableIdentification_clicked()
|
||||
{
|
||||
if (enableIdentification(true))
|
||||
{
|
||||
QMessageBox::information(this, "", "设置成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "设置失败");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnDisableIdentification_clicked()
|
||||
{
|
||||
if (enableIdentification(false))
|
||||
{
|
||||
QMessageBox::information(this, "", "设置成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "设置失败");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnStartListen_clicked()
|
||||
{
|
||||
if (enableListenEvents(true))
|
||||
{
|
||||
QMessageBox::information(this, "", "设置成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "设置失败");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_btnStopListen_clicked()
|
||||
{
|
||||
if (enableListenEvents(false))
|
||||
{
|
||||
QMessageBox::information(this, "", "设置成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "", "设置失败");
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,91 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class MainWindow : public QMainWindow, private kbd_application::CAcsDeviceApi
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
private:
|
||||
void handleFaceInfo(bool bSuccess, size_t nDataLen, const char *pData, void *pUserData) override;
|
||||
|
||||
void handleFingerprintInfo(bool bSuccess, size_t nDataLen, const char *pData, void *pUserData) override;
|
||||
|
||||
void handleSetUserInfoResult(const std::list<kbd_application::CUserInfo> &listUserInfo, void *pUserData) override;
|
||||
|
||||
void handleIdentificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData) override;
|
||||
|
||||
signals:
|
||||
void faceInfoFinish(bool bSuccess, std::string strData, void *pUserData);
|
||||
|
||||
void fingerprintInfoFinish(bool bSuccess, std::string strData, void *pUserData);
|
||||
|
||||
void setUserInfoFinish(std::list<kbd_application::CUserInfo> listUserInfo, void *pUserData);
|
||||
|
||||
void identificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData);
|
||||
|
||||
private slots:
|
||||
|
||||
void on_faceInfoFinish(bool bSuccess, std::string strData, void *pUserData);
|
||||
|
||||
void on_fingerprintInfoFinish(bool bSuccess, std::string strData, void *pUserData);
|
||||
|
||||
void on_setUserInfoFinish(std::list<kbd_application::CUserInfo> listUserInfo, void *pUserData);
|
||||
|
||||
void on_identificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData);
|
||||
|
||||
void on_btnLogin_clicked();
|
||||
|
||||
void on_btnLogout_clicked();
|
||||
|
||||
void on_btnCapUser1Face_clicked();
|
||||
|
||||
void on_btnCapUser1Fp1_clicked();
|
||||
|
||||
void on_btnCapUser1Fp2_clicked();
|
||||
|
||||
void on_btnCapUser2Face_clicked();
|
||||
|
||||
void on_btnCapUser2Fp1_clicked();
|
||||
|
||||
void on_btnCapUser2Fp2_clicked();
|
||||
|
||||
void on_btnSetToDev_clicked();
|
||||
|
||||
void on_btnClearLocal_clicked();
|
||||
|
||||
void on_btnEnableIdentification_clicked();
|
||||
|
||||
void on_btnDisableIdentification_clicked();
|
||||
|
||||
void on_btnStartListen_clicked();
|
||||
|
||||
void on_btnStopListen_clicked();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
std::string m_strUser1_Face;
|
||||
std::string m_strUser1_Fp1;
|
||||
std::string m_strUser1_Fp2;
|
||||
|
||||
std::string m_strUser2_Face;
|
||||
std::string m_strUser2_Fp1;
|
||||
std::string m_strUser2_Fp2;
|
||||
|
||||
};
|
||||
#endif // MAINWINDOW_H
|
||||
@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>294</width>
|
||||
<height>361</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="btnLogin">
|
||||
<property name="text">
|
||||
<string>登录设备</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="btnLogout">
|
||||
<property name="text">
|
||||
<string>登出设备</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="gbUser1">
|
||||
<property name="title">
|
||||
<string>人员1</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="btnCapUser1Fp1">
|
||||
<property name="text">
|
||||
<string>采集指纹1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="btnCapUser1Fp2">
|
||||
<property name="text">
|
||||
<string>采集指纹2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="btnCapUser1Face">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>采集人脸</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="gbUser2">
|
||||
<property name="title">
|
||||
<string>人员2</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="btnCapUser2Face">
|
||||
<property name="text">
|
||||
<string>采集人脸</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="btnCapUser2Fp1">
|
||||
<property name="text">
|
||||
<string>采集指纹1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="btnCapUser2Fp2">
|
||||
<property name="text">
|
||||
<string>采集指纹2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QPushButton" name="btnSetToDev">
|
||||
<property name="text">
|
||||
<string>下装到设备</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="btnClearLocal">
|
||||
<property name="text">
|
||||
<string>清空本地数据</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QPushButton" name="btnEnableIdentification">
|
||||
<property name="text">
|
||||
<string>启用识别</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QPushButton" name="btnDisableIdentification">
|
||||
<property name="text">
|
||||
<string>停用识别</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QPushButton" name="btnStartListen">
|
||||
<property name="text">
|
||||
<string>开始监听事件</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QPushButton" name="btnStopListen">
|
||||
<property name="text">
|
||||
<string>停止监听事件</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -0,0 +1,34 @@
|
||||
QT += widgets
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = test_hk_acs
|
||||
|
||||
LIBS += -llog4cplus \
|
||||
-lpub_logger_api -lacs_device_api
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
mainwindow.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
COMMON_PRI=$$PWD/../../../../common.pri
|
||||
exists($$COMMON_PRI) {
|
||||
include($$COMMON_PRI)
|
||||
}else {
|
||||
error("FATAL error: can not find common.pri")
|
||||
}
|
||||
|
||||
#必须在common.pri之后包含
|
||||
#-------------------------------------------------------------------
|
||||
HIKVISION_PRI=$$PWD/../../../../3rd/include/hikvision/hikvision.pri
|
||||
exists($$HIKVISION_PRI) {
|
||||
include($$HIKVISION_PRI)
|
||||
}else {
|
||||
error("FATAL error: can not find hikvision.pri")
|
||||
}
|
||||
9
platform/src/application/app_fbd/app_fbd.pro
Normal file
9
platform/src/application/app_fbd/app_fbd.pro
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
#各子工程按书写顺序编译,清注意各子工程的依赖关系,被依赖的库应写在前面。
|
||||
|
||||
TEMPLATE = subdirs
|
||||
CONFIG += ordered
|
||||
|
||||
SUBDIRS += fbd_common \
|
||||
fbd_module \
|
||||
app_fbd_server
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user