初始化提交

This commit is contained in:
shi_jq 2025-03-12 11:08:50 +08:00
parent 1af8f545c7
commit dad3973bfc
2639 changed files with 584101 additions and 0 deletions

View 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目录。执行时间待定。

View 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时如果系统时间调整造成死锁的问题。

Binary file not shown.

View 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));
}
};

Binary file not shown.

View 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

View 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

View File

@ -0,0 +1,5 @@
#writen by yikenan,2018-08-28
纯头文件库,无需编译

View File

@ -0,0 +1,9 @@
writen by yikenan,2018-01-02
此目录为第三方组件源代码包存放目录,非部署路径。
本目录下的个子目录内有各组件的编译说明。
注意:
Unix、Linux下编译第三方库请务必设置rpath为“$ORIGIN”可用以下命令查看rpath字段
readelf -d 文件名

View 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_UNIXZeroMQ 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 APIs.
所以要编译具有AF_UNIX特性的libzmqVS 2015要安装对应于win 1709及以上版本的Win SDKVS 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 166872021年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连接BTCP连接后此时监视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);
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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文件拷贝至对应目录

Binary file not shown.

View 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

Binary file not shown.

View 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中定义。

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View File

@ -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);

View 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
{

View File

@ -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;
+}
+

View File

@ -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);

View 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版本

View 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

View File

@ -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

View File

@ -0,0 +1 @@
rpm包省略可去 https://pkgs.org/ 等网站下载

View File

@ -0,0 +1,4 @@
社区预编译版
https://kb.firedaemon.com/support/solutions/articles/4000121705
当前采用的版本是1.1.1h

Binary file not shown.

View 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

View 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)

View 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 。ubuntu18kernel 5.3 , gcc 7.5)未见此问题。
********************************************************************************
Windows编译
见windows目录
********************************************************************************

View File

@ -0,0 +1 @@

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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.

View File

@ -0,0 +1,35 @@
简介用于文件流读写xlsx文件内存占用极小处理100万个cell大概需要15-20秒
项目地址https://github.com/brechtsanders/xlsxio
项目licenseMIT
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即为目标文件

Binary file not shown.

Binary file not shown.

View 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工程编译

Binary file not shown.

View File

@ -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:
{
//< lpBuffer4字节状态 + 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:
{
//< lpBuffer4字节状态 + 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:
{
//< lpBuffer4字节状态 + 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
{
//< lpBuffer4字节状态 + 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

View File

@ -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

View File

@ -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:
{
//< lpBuffer4字节状态 + 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
{
//< lpBuffer4字节状态 + 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- 已存在该指纹ID7- 非法指纹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

View File

@ -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

View File

@ -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")
}

View File

@ -0,0 +1,9 @@
#各子工程按书写顺序编译,清注意各子工程的依赖关系,被依赖的库应写在前面
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += acs_device_api \
app_bio_identify_srv

View File

@ -0,0 +1,15 @@

/******************************************************************************//**
* @file BisCommon.cpp
* @brief
* @author yikenan
* @version 1.0
* @date
**********************************************************************************/
#include "BisCommon.h"
namespace kbd_application
{
} //< namespace kbd_application

View File

@ -0,0 +1,17 @@

/******************************************************************************//**
* @file BisCommon.h
* @brief
* @author yikenan
* @version 1.0
* @date
**********************************************************************************/
#pragma once
namespace kbd_application
{
} //< namespace kbd_application

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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")
}

View File

@ -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;
}

View File

@ -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")
}

View File

@ -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;
}

View File

@ -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, "", "设置失败");
}
}

View File

@ -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

View File

@ -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>

View File

@ -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")
}

View 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