获取门禁记录方式-主动获取
Posted 摧残一生 涅槃重生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了获取门禁记录方式-主动获取相关的知识,希望对你有一定的参考价值。
主动获取
类似于获取门禁记录,通过代入的查询条件获取范围内的记录信息,使用该方式时需要注意时间范围不要重复或者获取数据后有查重操作,否则会出现重复的情况。
流程中的1,2,6,7的代码请参见《获取门禁记录方式-公用方法》
流程
-
NET_DVR_Init
(初始化) -
NET_DVR_Login_V40
(登录获得UserId) -
NET_DVR_StartRemoteConfig
(获取查记录的句柄)-
引用方法
int NET_DVR_StartRemoteConfig(int lUserID, int dwCommand, IntPtr lpInBuffer, Int32 dwInBufferLen, RemoteConfigCallback cbStateCallback, IntPtr pUserData)
-
参数说明
参数 说明 lUserID 登录句柄 dwCommand 命令,该例子中为NET_DVR_GET_ACS_EVENT(2514) lpInBuffer NET_DVR_ACS_EVENT_COND类的实例,转换为IntPtr dwInBufferLen NET_DVR_ACS_EVENT_COND类的实例长度 cbStateCallback null pUserData IntPtr.Zero 返回值 该次查询的句柄,下一步需要使用 -
代码举例
//获得查询条件 CHCNetSDK.NET_DVR_ACS_EVENT_COND cond = GetAcsEventCond(searchCond, isSearchAll); uint dwSize = cond.dwSize; // 声明cond实例大小的IntPtr IntPtr ptrCond = Marshal.AllocHGlobal((int)dwSize); // 将cond转换为IntPtr Marshal.StructureToPtr(cond, ptrCond, false); // 实例 int recordCfgHandle = CHCNetSDK.NET_DVR_StartRemoteConfig(lUserID, CHCNetSDK.NET_DVR_GET_ACS_EVENT, ptrCond, (int)dwSize, null, IntPtr.Zero); // 如果userCfgHandle为-1时,则不能查询,原因可能是没有释放之前的查询句柄,可通过GetLastError来判断
GetAcsEventCond
方法代码/// <summary> /// 根据条件获得NET_DVR_ACS_EVENT_COND实例 /// </summary> /// <param name="searchCond"> /// key 说明 /// beginTime 查询记录的起时间 /// endTime 查询记录的止时间 /// </param> /// <param name="isSearchAll">是否查询全部</param> /// <returns></returns> private CHCNetSDK.NET_DVR_ACS_EVENT_COND GetAcsEventCond(Dictionary<string, string> searchCond, bool isSearchAll) CHCNetSDK.NET_DVR_ACS_EVENT_COND cond = new CHCNetSDK.NET_DVR_ACS_EVENT_COND(); cond.Init(); cond.dwSize = (uint)Marshal.SizeOf(cond); //报警主类型 cond.dwMajor = 5; //报警次类型,0为全部 cond.dwMinor = 0; //是否带图片,0-不带图片,1-带图片 cond.byPicEnable = 0; //归纳事件类型,全部都要 cond.wInductiveEventType = 65535; // 如果是全部信息,则不需要设置起始时间 if (!isSearchAll) if (null != searchCond && searchCond.ContainsKey("beginTime")) // 如果有beginTime,则获取 cond.struStartTime = CHCNetSDK.GetDvrStruTIme(searchCond["beginTime"]); else // 如果没有,则默认为当前的凌晨开始 cond.struStartTime = CHCNetSDK.GetDvrStruTIme(String.Format("%s 00:00:00", DateTime.Now.ToString("yyyy-MM-dd"))); if (null != searchCond && searchCond.ContainsKey("endTime")) // 同上 cond.struEndTime = CHCNetSDK.GetDvrStruTIme(searchCond["endTime"]); else // 同上 cond.struEndTime = CHCNetSDK.GetDvrStruTIme(String.Format("%s", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))); return cond;
GetDvrStruTIme
方法/// <summary> /// 根据时间获得NET_DVR_TIME类型 /// </summary> /// <param name="time">yyyy-MM-dd HH:mm:ss形式的字符串</param> /// <returns>NET_DVR_TIME</returns> public static NET_DVR_TIME GetDvrStruTIme(String time) DateTime dateTime = System.DateTime.Now; if (!String.IsNullOrEmpty(time)) try dateTime = Convert.ToDateTime(time); catch (Exception ex) NET_DVR_TIME condTime = new NET_DVR_TIME(); condTime.dwYear = dateTime.Year; condTime.dwMonth = dateTime.Month; condTime.dwDay = dateTime.Day; condTime.dwHour = dateTime.Hour; condTime.dwMinute = dateTime.Minute; condTime.dwSecond = dateTime.Second; return condTime;
-
-
NET_DVR_GetNextRemoteConfig
(一条一条获取)注意:代码不变的情况下,有时会返回1000(成功),有时会返回1002,错误码为19(设备返回数据异常);原因可能是在调试的时候,时长过长导致的。
-
引用方法
int NET_DVR_GetNextRemoteConfig(int lHandle, ref CHCNetSDK.NET_DVR_ACS_EVENT_CFG lpOutBuff, int dwOutBuffSize);
-
参数说明
参数 说明 lHandle 查询句柄(NET_DVR_StartRemoteConfig返回值) lpOutBuff CUserInfoSearchCondCfg类的实例,检索条件 dwOutBuffSize CUserInfoSearchCondCfg类的实例长度 返回值 NET_SDK_GET_NEXT_STATUS_SUCCESS成功获取数据 -
代码举例
// 存储门禁记录的list List<AcessLogEntity> acessLogEntities = new List<AcessLogEntity>(); // 状态表示 int dwStatus = 0; // 循环使用 Boolean flag = true; // 门禁记录的类 CHCNetSDK.NET_DVR_ACS_EVENT_CFG struCFG = new CHCNetSDK.NET_DVR_ACS_EVENT_CFG(); struCFG.dwSize = (uint)Marshal.SizeOf(struCFG); int dwOutBuffSize = (int)struCFG.dwSize; // 门禁类里面的byte数组初始化 struCFG.init(); while (flag) // 调用下一条下一条的方法 dwStatus = CHCNetSDK.NET_DVR_GetNextRemoteConfig(recordCfgHandle, ref struCFG, dwOutBuffSize); switch (dwStatus) case CHCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS://成功读取到数据,处理完本次数据后需调用next // 获得门禁记录 // 注:personDic为获取到人员列表的编号对应姓名,因为门禁记录中貌似没有人员名称。personDic的获取不在本文中体现,可参考人员列表获取的相关文章。 AcessLogEntity acessLog = GetAccessLog(personDic, ref struCFG); // 如果有 if (null != acessLog) // 保存 acessLogEntities.Add(acessLog); break; case CHCNetSDK.NET_SDK_GET_NEXT_STATUS_NEED_WAIT: Thread.Sleep(200); break; case CHCNetSDK.NET_SDK_GET_NEXT_STATUS_FAILED: case CHCNetSDK.NET_SDK_GET_NEXT_STATUS_FINISH: default: CHCNetSDK.NET_DVR_StopRemoteConfig(recordCfgHandle); flag = false; break;
GetAccessLog
方法GetAccessLog的personDic参数为获取到人员列表的编号对应姓名,因为门禁记录中貌似没有人员名称。
personDic的获取不在本文中体现,可参考人员列表获取的相关文章。
/// <summary> /// 将NET_DVR_ACS_EVENT_CFG转换为AcessLogEntity /// </summary> /// <param name="personDic">人员的编号和姓名对应的字典</param> /// <param name="eventCfg">门禁记录</param> /// <returns></returns> private AcessLogEntity GetAccessLog(Dictionary<string, string> personDic, ref CHCNetSDK.NET_DVR_ACS_EVENT_CFG eventCfg) AcessLogEntity acessLog = new AcessLogEntity(); // 是什么记录,可通过对case的增减来选择性的获取记录 string minorType = AcessLogEntity.GetMinorType(eventCfg.dwMinor); // 如果没有则返回null if (minorType.Length < 1) return null; // 门禁的类型 acessLog.Verify = minorType; // 人员唯一编号,通过浏览器登录门禁,人员管理中现实的编号。 acessLog.Pin = Encoding.ASCII.GetString(eventCfg.struAcsEventInfo.byEmployeeNo).Replace("\\0", ""); // 没有则跳过 if (personDic.ContainsKey(acessLog.Pin)) acessLog.Name = personDic[acessLog.Pin]; // 卡号 acessLog.Cardno = Encoding.ASCII.GetString(eventCfg.struAcsEventInfo.byCardNo); // 门禁产生的时间 acessLog.AccessTime = String.Format("0-1:D2-2:D2 3:D2:4:D2:5:D2", eventCfg.struTime.dwYear, eventCfg.struTime.dwMonth, eventCfg.struTime.dwDay, eventCfg.struTime.dwHour, eventCfg.struTime.dwMinute, eventCfg.struTime.dwSecond); return acessLog;
AcessLogEntity.GetMinorType
方法可直接使用,如果想用“0x03 刷卡加密码认证通过”,只需要打开注释即可
public static string GetMinorType(uint seek) switch (seek) case 0x01: return "合法卡认证通过"; //case 0x02: return "刷卡加密码认证通过"; //case 0x03: return "刷卡加密码认证失败"; //case 0x04: return "数卡加密码认证超时"; //case 0x05: return "刷卡加密码超次"; //case 0x06: return "未分配权限"; //case 0x07: return "无效时段"; //case 0x08: return "卡号过期"; //case 0x09: return "无此卡号"; //case 0x0a: return "反潜回认证失败"; //case 0x0b: return "互锁门未关闭"; //case 0x0c: return "卡不属于多重认证群组"; //case 0x0d: return "卡不在多重认证时间段内"; //case 0x0e: return "多重认证模式超级权限认证失败"; //case 0x0f: return "多重认证模式远程认证失败"; case 0x10: return "多重认证成功"; //case 0x11: return "首卡开门开始"; //case 0x12: return "首卡开门结束"; //case 0x13: return "常开状态开始"; //case 0x14: return "常开状态结束"; //case 0x15: return "门锁打开"; //case 0x16: return "门锁关闭"; case 0x17: return "开门按钮打开"; //case 0x18: return "开门按钮放开"; //case 0x19: return "正常开门(门磁)"; //case 0x1a: return "正常关门(门磁)"; //case 0x1b: return "门异常打开(门磁)"; //case 0x1c: return "门打开超时(门磁)"; //case 0x1d: return "报警输出打开"; //case 0x1e: return "报警输出关闭"; //case 0x1f: return "常关状态开始"; //case 0x20: return "常关状态结束"; //case 0x21: return "多重多重认证需要远程开门"; //case 0x22: return "多重认证超级密码认证成功事件"; //case 0x23: return "多重认证重复认证事件"; //case 0x24: return "多重认证重复认证事件"; //case 0x25: return "门铃响"; case 0x26: return "指纹比对通过"; //case 0x27: return "指纹比对失败"; case 0x28: return "刷卡加指纹认证通过"; //case 0x29: return "刷卡加指纹认证失败"; //case 0x2a: return "刷卡加指纹认证超时"; case 0x2b: return "刷卡加指纹加密码认证通过"; //case 0x2c: return "刷卡加指纹加密码认证失败"; //case 0x2d: return "刷卡加指纹加密码认证超时"; case 0x2e: return "指纹加密码认证通过"; //case 0x2f: return "指纹加密码认证失败"; //case 0x30: return "指纹加密码认证超时"; //case 0x31: return "指纹不存在"; //case 0x32: return "刷卡平台认证"; //case 0x33: return "呼叫中心事件"; //case 0x34: return "消防继电器导通触发门常开"; //case 0x35: return "消防继电器恢复门恢复正常"; case 0x36: return "人脸加指纹认证通过"; //case 0x37: return "人脸加指纹认证失败"; //case 0x38: return "人脸加指纹认证超时"; case 0x39: return "人脸加密码认证通过"; //case 0x3a: return "人脸加密码认证失败"; //case 0x3b: return "人脸加密码认证超时"; case 0x3c: return "人脸加刷卡认证通过"; //case 0x3d: return "人脸加刷卡认证失败"; //case 0x3e: return "人脸加刷卡认证超时"; case 0x3f: return "人脸加密码加指纹认证通过"; //case 0x40: return "人脸加密码加指纹认证失败"; //case 0x41: return "人脸加密码加指纹认证超时"; case 0x42: return "人脸加刷卡加指纹认证通过"; //case 0x43: return "人脸加刷卡加指纹认证失败"; //case 0x44: return "人脸加刷卡加指纹认证超时"; case 0x45: return "工号加指纹认证通过"; //case 0x46: return "工号加指纹认证失败"; //case 0x47: return "工号加指纹认证超时"; case 0x48: return "工号加指纹加密码认证通过"; //case 0x49: return "工号加指纹加密码认证失败"; //case 0x4a: return "工号加指纹加密码认证超时"; case 0x4b: return "人脸认证通过"; //case 0x4c: return "人脸认证失败"; case 0x4d: return "工号加人脸认证通过"; //case 0x4e: return "工号加人脸认证失败"; //case 0x4f: return "工号加人脸认证超时"; //case 0x50: return "人脸识别失败"; //case 0x51: return "首卡授权开始"; //case 0x52: return "首卡授权结束"; //case 0x53: return "门锁输入短路报警"; //case 0x54: return "门锁输入断路报警"; //case 0x55: return "门锁输入异常报警"; //case 0x56: return "门磁输入短路报警"; //case 0x57: return "门磁输入断路报警"; //case 0x58: return "门磁输入异常报警"; //case 0x59: return "开门按钮输入短路报警"; //case 0x5a: return "开门按钮输入断路报警"; //case 0x5b: return "开门按钮输入异常报警"; //case 0x5c: return "门锁异常打开"; //case 0x5d: return "门锁打开超时"; //case 0x5e: return "首卡未授权开门失败"; //case 0x5f: return "呼梯继电器断开"; //case 0x60: return "呼梯继电器闭合"; //case 0x61: return "自动按键继电器断开"; //case 0x62: return "自动按键继电器闭合"; //case 0x63: return "按键梯控继电器断开"; //case 0x64: return "按键梯控继电器闭合"; case 0x65: return "工号加密码认证通过"; //case 0x66: return "工号加密码认证失败"; //case 0x67: return "工号加密码认证超时"; //case 0x68: return "真人检测失败"; case 0x69: return "人证比对通过"; //case 0x70: return "人证比对失败"; //case 0x71: return "黑名单事件"; //case 0x72: return "合法短信"; //case 0x73: return "非法短信"; //case 0x74: return "MAC侦测"; //case 0x75: return "门状态常闭或休眠状态认证失败"; //case 0x76: return "认证计划休眠模式认证失败"; //case 0x77: return "卡加密校验失败"; //case 0x78: return "反潜回服务器应答失败"; //case 0x85: return "尾随通行"; //case 0x86: return "反向闯入"; //case 0x87: return "外力冲撞"; //case 0x88: return "翻越"; //case 0x89: return "通行超时"; //case 0x8a: return "误闯报警"; //case 0x8b: return "闸机自由通行时未认证通过"; //case 0x8c: return "摆臂被阻挡"; //case 0x8d: return "摆臂阻挡消除"; //case 0x8e: return "设备升级本地人脸建模失败"; //case 0x8f: return "逗留事件"; //case 0x97: return "密码不匹配"; //case 0x98: return "工号不存在"; case 0x99: return "组合认证通过"; //case 0x9a: return "组合认证超时"; //case 0x9b: return "认证方式不匹配"; default: return "";
AcessLogEntity
类可根据自己的实际情况进行声明
-
-
NET_DVR_StopRemoteConfig
(释放该次查询句柄)-
引用方法
int NET_DVR_StartRemoteConfig(int lUserID, int dwCommand, IntPtr lpInBuffer, Int32 dwInBufferLen, RemoteConfigCallback cbStateCallback, IntPtr pUserData)
-
参数说明
参数 说明 lUserID 登录句柄 dwCommand 命令,该例子中为NET_DVR_JSON_CONFIG(2550) lpInBuffer url转换的IntPtr dwInBufferLen url的长度 cbStateCallback null pUserData IntPtr.Zero 返回值 该次查询的句柄,下一步需要使用 -
代码举例
-
-
NET_DVR_Logout
(注销) -
NET_DVR_Cleanup
(结束)
不用被动注入的方式, 主动从 Spring Boot 应用容器中的获取 Bean 的方法
package com.bytedance.kunlun.interpreter.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextUtil implements ApplicationContextAware {
// Spring应用上下文环境
private static ApplicationContext applicationContext;
/**
* 实现ApplicationContextAware接口的回调方法,设置上下文环境
*
* @param applicationContext
*/
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextUtil.applicationContext = applicationContext;
}
/**
* @return ApplicationContext
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 获取对象
*
* @param name
* @return Object
* @throws BeansException
*/
public static Object getBean(String name)throws BeansException {
return applicationContext.getBean(name);
}
}
PS: @Component 注解.
从容器中主动获取Bean的使用方式
package com.bytedance.kunlun.interpreter;
import com.bytedance.kunlun.interpreter.parser.SpecificationParser;
import com.bytedance.kunlun.interpreter.spec.IQuerySpecification;
import com.bytedance.kunlun.interpreter.util.JsonUtil;
import com.bytedance.kunlun.interpreter.util.SpringContextUtil;
import com.bytedance.kunlun.sdk.drivermanager.model.DriverType;
import com.bytedance.kunlun.sdk.drivermanager.model.EngineType;
import com.bytedance.kunlun.sdk.interpreter.api.KunlunInterpreter;
import com.bytedance.kunlun.sdk.interpreter.model.*;
import org.springframework.stereotype.Service;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
/**
* Kunlun 编译器实现类
*/
@Service
public class KunlunInterpreterImpl implements KunlunInterpreter {
SpecificationParser specificationParser;
@Override
public Statement interpret(KunlunRule rule)throws Exception {
// 选择引擎
selectEngine(rule);
KunlunExpression expression = rule.getExpression();
// BFS 解析嵌套子句
bfsParseExpression(expression);
// 解析构建 ASTQuery 抽象语法树
IQuerySpecification specification =specificationParser.parse(rule);
// 物理资源映射,生成真正执行的物理 SQL Statement
Statement statement =new Statement();
if (specification !=null) {
statement.setSelectSql(specification.genSelectSql());
statement.setCountSql(specification.genSelectCountSql());
statement.setGroupBySql(specification.genSelectGroupBySql());
statement.setKvSql(specification.genSelectSqlForKV());
}
return statement;
}
private void selectEngine(KunlunRule rule) {
// 引擎选择
if (EngineType.OLAP.equals(rule.getEngineSelector().getEngineType())
&&DriverType.CLICKHOUSE.equals(rule.getEngineSelector().getDriverType())) {
specificationParser = (SpecificationParser)SpringContextUtil.getBean("specificationParserClickHouse");
}else if (EngineType.OLAP.equals(rule.getEngineSelector().getEngineType())
&&DriverType.HIVE.equals(rule.getEngineSelector().getDriverType())) {
specificationParser = (SpecificationParser)SpringContextUtil.getBean("specificationParserHive");
}else {
throw new IllegalArgumentException("engine not supported yet!");
}
}
/**
* BFS 遍历表达式树
*
* @param kunlunExpression
* @throws Exception
*/
private void bfsParseExpression(KunlunExpression kunlunExpression)throws Exception {
Queuequeue =new ArrayDeque<>();
ListexpressionList =new ArrayList<>();
// 根节点入队列
queue.offer(kunlunExpression);
while (!queue.isEmpty()) {
// 出队列
KunlunExpression expr =queue.poll();
ListsubExpressionList =expr.getSubExpression();
if (subExpressionList !=null && !subExpressionList.isEmpty()) {
for (KunlunExpression e :subExpressionList) {
// 子节点入队列
queue.offer(e);
}
}
expressionList.add(expr);
}
for (KunlunExpression e :expressionList) {
System.out.println(e);
// 解析
parseExpression(e);
}
}
/**
* 解析表达式
*
* @param kunlunExpression
* @throws Exception
*/
private void parseExpression(KunlunExpression kunlunExpression)throws Exception {
ExpressionLogicOperatorEnum logic = kunlunExpression.getLogic();
if (logic ==null) {
throw new RuntimeException("can't get operator from kunlunExpression:" +JsonUtil.toString(kunlunExpression));
}
FieldCondition fieldCondition = kunlunExpression.getFilterField();
if (fieldCondition !=null) {
// 获取特征值运算符
this.processFieldFeature(specificationParser, kunlunExpression);
}else {
specificationParser.compose(kunlunExpression);
}
}
private void processFieldFeature(SpecificationParser specificationParser,KunlunExpression kunlunExpression)throws Exception {
FieldCondition fieldCondition = kunlunExpression.getFilterField();
FieldArithmeticOperatorEnum operator =fieldCondition.getOperator();
switch (operator) {
case GREATER_THAN:
specificationParser.greaterThan(kunlunExpression);
break;
case GREATER_EQUAL_THAN:
specificationParser.greaterEqualThan(kunlunExpression);
break;
case LESS_THAN:
specificationParser.lessThan(kunlunExpression);
break;
case LESS_EQUAL_THAN:
specificationParser.lessEqualThan(kunlunExpression);
break;
case EQUAL:
specificationParser.equals(kunlunExpression);
break;
case IN:
specificationParser.in(kunlunExpression);
break;
case BETWEEN:
specificationParser.between(kunlunExpression);
break;
case LIKE:
specificationParser.like(kunlunExpression);
break;
default:
throw new RuntimeException("unsupported operator.");
}
}
}
以上是关于获取门禁记录方式-主动获取的主要内容,如果未能解决你的问题,请参考以下文章
不用被动注入的方式, 主动从 Spring Boot 应用容器中的获取 Bean 的方法