Explorar o código

修改连接sdk bug

Anthony hai 1 semana
pai
achega
961ec62a40
Modificáronse 41 ficheiros con 2975 adicións e 547 borrados
  1. 0 5
      supervision-admin/resources/conf/acs/Face/AddFaceInfoParam.json
  2. 0 5
      supervision-admin/resources/conf/acs/Face/DeleteFaceInfoParam.json
  3. 28 0
      supervision-admin/resources/conf/acs/Face/FaceRecordTotalOutputParam.json
  4. 57 50
      supervision-admin/resources/conf/acs/Face/SearchFaceInfoInputParam.json
  5. 57 50
      supervision-admin/resources/conf/acs/Face/SearchFaceInfoOutputParam.json
  6. 0 53
      supervision-admin/resources/conf/acs/Face/SearchFaceInfoParam.json
  7. 0 151
      supervision-admin/resources/conf/acs/Face/SearchFaceInfoParamInput.xml
  8. 0 150
      supervision-admin/resources/conf/acs/Face/SearchFaceInfoParamOutput.xml
  9. 7 0
      supervision-admin/resources/conf/acs/Face/SetUpFaceInfoOutputParam.json
  10. 59 0
      supervision-admin/resources/conf/acs/User/AddUserInfoInputParam.json
  11. 39 0
      supervision-admin/resources/conf/acs/User/AddUserInfoOutputParam.json
  12. 34 0
      supervision-admin/resources/conf/acs/User/DeleteUserInfoInputParam.json
  13. 7 0
      supervision-admin/resources/conf/acs/User/DeleteUserInfoOutputParam.json
  14. 1 0
      supervision-admin/resources/conf/acs/User/GetUserCountInputParam.json
  15. 0 0
      supervision-admin/resources/conf/acs/User/GetUserCountOutputParam.json
  16. 32 0
      supervision-admin/resources/conf/acs/User/GetUserInfoInputParam.json
  17. 122 0
      supervision-admin/resources/conf/acs/User/GetUserInfoOutputParam.json
  18. 184 0
      supervision-admin/resources/conf/acs/User/ModifyUserInfoInputParam.json
  19. 7 0
      supervision-admin/resources/conf/acs/User/ModifyUserInfoOutputParam.json
  20. 63 0
      supervision-admin/resources/conf/acs/User/SetUserInfoInputParam.json
  21. 12 0
      supervision-admin/resources/conf/acs/User/SetUserInfoOutputParam.json
  22. 4 5
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/CarCameraDeviceManager.java
  23. 92 0
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/CommonMethod/CarDoorEventManage.java
  24. 2 5
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/alarm/Alarm.java
  25. 2 5
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/alarm/CarCameraAlarmDataParse.java
  26. 2 2
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/alarm/CarCameraFMSGCallBack_V31.java
  27. 1 1
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/alarm/FMSGCallBack.java
  28. 3 7
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/AcsMain.java
  29. 1 2
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/CardManage.java
  30. 107 0
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/EventSearch.java
  31. 127 28
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/FaceManage.java
  32. 1 2
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/FingerManage.java
  33. 193 6
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/UserManage.java
  34. 2 1
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/CommonMethod/CommonMethod.java
  35. 23 0
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/CommonMethod/CommonUtil.java
  36. 1 6
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/CommonMethod/ConfigFileUtil.java
  37. 1 1
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/CommonMethod/osSelect.java
  38. 3 2
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/NetSDKDemo/HCNetSDK.java
  39. 305 10
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/PeopleDoorDeviceManager.java
  40. 1373 0
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/alarm/PeopleDoorAlarmDataParse.java
  41. 23 0
      supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/alarm/PeopleDoorFMSGCallBack_V31.java

+ 0 - 5
supervision-admin/resources/conf/acs/Face/AddFaceInfoParam.json

@@ -1,5 +0,0 @@
-{
-  "faceLibType":"blackFD",
-  "FDID":"1",
-  "FPID":"${employeeNo}"
-}

+ 0 - 5
supervision-admin/resources/conf/acs/Face/DeleteFaceInfoParam.json

@@ -1,5 +0,0 @@
-{
-    "FPID": [{
-        "value": "${employeeNo}"
-    }]
-}

+ 28 - 0
supervision-admin/resources/conf/acs/Face/FaceRecordTotalOutputParam.json

@@ -0,0 +1,28 @@
+{
+  "requestURL": "http://10.7.52.31:8080/kms/services/rest/dataInfoService/downloadFile",
+  "statusCode": 1,
+  "statusString": "ok",
+  "subStatusCode": "ok",
+  "errorCode": 1,
+  "errorMsg": "ok",
+  "FDRecordDataInfo": [
+    {
+      "FDID": "test",
+      "faceLibType": "blackFD",
+      "name": "test",
+      "recordDataNumber": 123,
+      "libArmingType": "armingLib",
+      "libAttribute": "general",
+      "personnelFileEnabled": true
+    }
+  ],
+  "totalRecordDataNumber": 500000,
+  "FDCapacity": {
+    "total": 0,
+    "use": 0,
+    "remain": 0,
+    "maxRecordDataNumber": 0,
+    "useRecordDataNumber": 0,
+    "remainRecordDataNumber": 0
+  }
+}

+ 57 - 50
supervision-admin/resources/conf/acs/Face/SearchFaceInfoInputParam.json

@@ -1,53 +1,60 @@
 {
-  "searchID": "test",
-  "searchResultPosition": 0,
-  "maxResults": 30,
-  "FDID": "test",
-  "startTime": "1970-01-01+08:00",
-  "endTime": "1970-01-01+08:00",
-  "name": "test",
-  "sex": "male",
-  "province": "11",
-  "city": "11",
-  "certificateType": "ID",
-  "certificateNumber": "test",
-  "phoneNumber": "test",
-  "FaceModeList": [
-    {
-      "ModeInfo": {
-        "similarity": 0.0,
-        "modeData": "test"
-      }
-    }
-  ],
-  "modelStatus": "modeling",
-  "modelingStatus": ["success", "failed", "none"],
-  "customFaceLibID": "test",
-  "sortord": "time",
-  "order": "DESC",
-  "StrangerLibFaceAppendData": {
-    "PersonInfoExtendList": [
+  "FDSearchDescription": {
+    "version": "2.0",
+    "searchID": "test",
+    "searchResultPosition": 0,
+    "maxResults": 30,
+    "FDID": "test",
+    "startTime": "1970-01-01+08:00",
+    "endTime": "1970-01-01+08:00",
+    "name": "test",
+    "sex": "male",
+    "province": "11",
+    "city": "11",
+    "certificateType": "ID",
+    "certificateNumber": "test",
+    "phoneNumber": "test",
+    "FaceModeList": [
       {
-        "id": 1,
-        "enable": true,
-        "name": "test",
-        "value": "test"
+        "ModeInfo": {
+          "similarity": 0.0,
+          "modeData": "test"
+        }
       }
-    ]
-  },
-  "OccurrencesInfo": {
-    "enabled": true,
-    "occurrences": 1,
-    "occurrencesSearchType": "greaterThanOrEqual"
-  },
-  "faceScore": 1,
-  "FDIDList": [
-    "test"
-  ],
-  "faceScoreMax": 0,
-  "pictureStatus": "normal",
-  "importStartTime": "1970-01-01T00:00:00+08:00",
-  "importEndTime": "1970-01-01T00:00:00+08:00",
-  "faceContrastSuccessStartTime": "1970-01-01T00:00:00+08:00",
-  "faceContrastSuccessEndTime": "1970-01-01T00:00:00+08:00"
-}
+    ],
+    "modelStatus": "modeling",
+    "modelingStatus": [
+      "success",
+      "failed",
+      "none"
+    ],
+    "customFaceLibID": "test",
+    "sortord": "time",
+    "order": "DESC",
+    "StrangerLibFaceAppendData": {
+      "PersonInfoExtendList": [
+        {
+          "id": 1,
+          "enable": true,
+          "name": "test",
+          "value": "test"
+        }
+      ]
+    },
+    "OccurrencesInfo": {
+      "enabled": true,
+      "occurrences": 1,
+      "occurrencesSearchType": "greaterThanOrEqual"
+    },
+    "faceScore": 1,
+    "FDIDList": [
+      "test"
+    ],
+    "faceScoreMax": 0,
+    "pictureStatus": "normal",
+    "importStartTime": "1970-01-01T00:00:00+08:00",
+    "importEndTime": "1970-01-01T00:00:00+08:00",
+    "faceContrastSuccessStartTime": "1970-01-01T00:00:00+08:00",
+    "faceContrastSuccessEndTime": "1970-01-01T00:00:00+08:00"
+  }
+}

+ 57 - 50
supervision-admin/resources/conf/acs/Face/SearchFaceInfoOutputParam.json

@@ -1,53 +1,60 @@
 {
-  "searchID": "test",
-  "searchResultPosition": 0,
-  "maxResults": 30,
-  "FDID": "test",
-  "startTime": "1970-01-01+08:00",
-  "endTime": "1970-01-01+08:00",
-  "name": "test",
-  "sex": "male",
-  "province": "11",
-  "city": "11",
-  "certificateType": "ID",
-  "certificateNumber": "test",
-  "phoneNumber": "test",
-  "FaceModeList": [
-    {
-      "ModeInfo": {
-        "similarity": 0.0,
-        "modeData": "test"
-      }
-    }
-  ],
-  "modelStatus": "modeling",
-  "modelingStatus": ["success", "failed", "none"],
-  "customFaceLibID": "test",
-  "sortord": "time",
-  "order": "DESC",
-  "StrangerLibFaceAppendData": {
-    "PersonInfoExtendList": [
+  "FDSearchResult": {
+    "version": "2.0",
+    "searchID": "test",
+    "searchResultPosition": 0,
+    "maxResults": 30,
+    "FDID": "test",
+    "startTime": "1970-01-01+08:00",
+    "endTime": "1970-01-01+08:00",
+    "name": "test",
+    "sex": "male",
+    "province": "11",
+    "city": "11",
+    "certificateType": "ID",
+    "certificateNumber": "test",
+    "phoneNumber": "test",
+    "FaceModeList": [
       {
-        "id": 1,
-        "enable": true,
-        "name": "test",
-        "value": "test"
+        "ModeInfo": {
+          "similarity": 0.0,
+          "modeData": "test"
+        }
       }
-    ]
-  },
-  "OccurrencesInfo": {
-    "enabled": true,
-    "occurrences": 1,
-    "occurrencesSearchType": "greaterThanOrEqual"
-  },
-  "faceScore": 1,
-  "FDIDList": [
-    "test"
-  ],
-  "faceScoreMax": 0,
-  "pictureStatus": "normal",
-  "importStartTime": "1970-01-01T00:00:00+08:00",
-  "importEndTime": "1970-01-01T00:00:00+08:00",
-  "faceContrastSuccessStartTime": "1970-01-01T00:00:00+08:00",
-  "faceContrastSuccessEndTime": "1970-01-01T00:00:00+08:00"
-}
+    ],
+    "modelStatus": "modeling",
+    "modelingStatus": [
+      "success",
+      "failed",
+      "none"
+    ],
+    "customFaceLibID": "test",
+    "sortord": "time",
+    "order": "DESC",
+    "StrangerLibFaceAppendData": {
+      "PersonInfoExtendList": [
+        {
+          "id": 1,
+          "enable": true,
+          "name": "test",
+          "value": "test"
+        }
+      ]
+    },
+    "OccurrencesInfo": {
+      "enabled": true,
+      "occurrences": 1,
+      "occurrencesSearchType": "greaterThanOrEqual"
+    },
+    "faceScore": 1,
+    "FDIDList": [
+      "test"
+    ],
+    "faceScoreMax": 0,
+    "pictureStatus": "normal",
+    "importStartTime": "1970-01-01T00:00:00+08:00",
+    "importEndTime": "1970-01-01T00:00:00+08:00",
+    "faceContrastSuccessStartTime": "1970-01-01T00:00:00+08:00",
+    "faceContrastSuccessEndTime": "1970-01-01T00:00:00+08:00"
+  }
+}

+ 0 - 53
supervision-admin/resources/conf/acs/Face/SearchFaceInfoParam.json

@@ -1,53 +0,0 @@
-{
-  "searchID": "test",
-  "searchResultPosition": 0,
-  "maxResults": 30,
-  "FDID": "test",
-  "startTime": "1970-01-01+08:00",
-  "endTime": "1970-01-01+08:00",
-  "name": "test",
-  "sex": "male",
-  "province": "11",
-  "city": "11",
-  "certificateType": "ID",
-  "certificateNumber": "test",
-  "phoneNumber": "test",
-  "FaceModeList": [
-    {
-      "ModeInfo": {
-        "similarity": 0.0,
-        "modeData": "test"
-      }
-    }
-  ],
-  "modelStatus": "modeling",
-  "modelingStatus": ["success", "failed", "none"],
-  "customFaceLibID": "test",
-  "sortord": "time",
-  "order": "DESC",
-  "StrangerLibFaceAppendData": {
-    "PersonInfoExtendList": [
-      {
-        "id": 1,
-        "enable": true,
-        "name": "test",
-        "value": "test"
-      }
-    ]
-  },
-  "OccurrencesInfo": {
-    "enabled": true,
-    "occurrences": 1,
-    "occurrencesSearchType": "greaterThanOrEqual"
-  },
-  "faceScore": 1,
-  "FDIDList": [
-    "test"
-  ],
-  "faceScoreMax": 0,
-  "pictureStatus": "normal",
-  "importStartTime": "1970-01-01T00:00:00+08:00",
-  "importEndTime": "1970-01-01T00:00:00+08:00",
-  "faceContrastSuccessStartTime": "1970-01-01T00:00:00+08:00",
-  "faceContrastSuccessEndTime": "1970-01-01T00:00:00+08:00"
-}

+ 0 - 151
supervision-admin/resources/conf/acs/Face/SearchFaceInfoParamInput.xml

@@ -1,151 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<FDSearchDescription xmlns="http://www.isapi.org/ver20/XMLSchema" version="2.0">
-    <!--opt, object, 查询描述, attr:version{req, string, 协议版本, range:[,]}-->
-    <searchID>
-        <!--req, string, 搜索记录唯一标识, range:[,], desc:用来确认上层客户端是否为同一个(倘若是同一个,则设备记录内存,下次搜索加快速度)-->
-        test
-    </searchID>
-    <searchResultPosition>
-        <!--req, int, 查询结果在结果列表中的起始位置, range:[,], step:, unit:, unitType:, desc:当记录条数很多时, 一次查询不能获取所有的记录, 下一次查询时指定位置可以查询后面的记录-->
-        1
-    </searchResultPosition>
-    <maxResults>
-        <!--req, int, 本次查询(每页显示)最大记录数, range:[,], step:, unit:, unitType:-->1
-    </maxResults>
-    <FDID>
-        <!--opt, string, 人脸比对库唯一标示ID, range:[,]-->test
-    </FDID>
-    <startTime>
-        <!--opt, date, 人脸库人员出生开始时间-->1970-01-01+08:00
-    </startTime>
-    <endTime>
-        <!--opt, date, 人脸库人员出生结束时间-->1970-01-01+08:00
-    </endTime>
-    <name>
-        <!--req, string, 姓名, range:[1,32]-->test
-    </name>
-    <sex>
-        <!--opt, enum, 性别, subType:string, [male#男,female#女]-->male
-    </sex>
-    <province>
-        <!--opt, string, 省份, range:[,], desc:参考《全国各省份城市列表.txt》-->11
-    </province>
-    <city>
-        <!--opt, string, 城市, range:[,], desc:参考《全国各省份城市列表.txt》-->11
-    </city>
-    <certificateType>
-        <!--opt, enum, 证件类型, subType:string, [ID#身份证,passportID#护照,other#其他]-->ID
-    </certificateType>
-    <certificateNumber>
-        <!--opt, string, 证件号, range:[8,32], desc:当certificateType为ID时,certificateNumber长度范围[8,18];当certificateType为passportID时,certificateNumber长度范围[8,32];当certificateType为other时,certificateNumber长度范围[8,18];-->
-        test
-    </certificateNumber>
-    <phoneNumber>
-        <!--opt, string, 电话号码, range:[1,64]-->test
-    </phoneNumber>
-    <FaceModeList>
-        <!--opt, array, 人脸模型信息列表, subType:object, range:[,]-->
-        <FaceMode>
-            <!--opt, object, 人脸模型-->
-            <ModeInfo>
-                <!--opt, object, 模型数据, desc:以图搜图时<ModeInfo>字段必填-->
-                <similarity>
-                    <!--opt, float, 相似度, range:[0.0,100.0], step:, unit:, unitType:-->0.0
-                </similarity>
-                <modeData>
-                    <!--opt, string, 目标模型数据, range:[,], desc:传输过程中针对二进制非建模数据进行base64的加密处理-->
-                    test
-                </modeData>
-            </ModeInfo>
-        </FaceMode>
-    </FaceModeList>
-    <modelStatus>
-        <!--opt, enum, 建模状态(旧), subType:string, [modeling#已建模,unmodeled#未建模,modelingFailed#建模失败]-->
-        modeling
-    </modelStatus>
-    <modelingStatus>
-        <!--opt, string, 建模状态, range:[,], desc:success-建模成功,failed-建模失败,none-尚未建模;支持复选;后续使用这个字段,modelStatus将会去除-->
-        success,failed,none
-    </modelingStatus>
-    <customFaceLibID>
-        <!--opt, string, 自定义人脸库ID, range:[,], desc:当FDID和customFaceLibID同时存在时,以customFaceLibID为准-->test
-    </customFaceLibID>
-    <sortord>
-        <!--opt, enum, 搜索结果排序类型, subType:string, [time#入库时间,contrastSuccessTime#比对成功时间,count#比对成功次数]-->
-        time
-    </sortord>
-    <order>
-        <!--opt, enum, 搜索结果排序方式, subType:string, [DESC#最晚入库最先展示,ASC#最早入库最先展示], desc:默认:DESC-->
-        DESC
-    </order>
-    <StrangerLibFaceAppendData>
-        <!--opt, object, 陌生人库支持人脸属性信息-->
-        <PersonInfoExtendList size="4">
-            <!--opt, array, 人员扩展信息列表, subType:object, range:[,], attr:size{req, int, 数组元素总数, range:[,], step:, unit:, unitType:}-->
-            <PersonInfoExtend>
-                <!--opt, object, 人员扩展信息-->
-                <id>
-                    <!--req, int, 人员扩展信息序号, range:[,], step:, unit:, unitType:, desc:从1开始赋值,依次增加-->1
-                </id>
-                <enable>
-                    <!--req, bool, 人员扩展信息使能-->true
-                </enable>
-                <name>
-                    <!--opt, string, 人员标签信息扩展名称, range:[,]-->test
-                </name>
-                <value>
-                    <!--opt, string, 人员标签信息扩展内容, range:[,]-->test
-                </value>
-            </PersonInfoExtend>
-        </PersonInfoExtendList>
-    </StrangerLibFaceAppendData>
-    <OccurrencesInfo>
-        <!--opt, object, 频次信息-->
-        <enabled>
-            <!--req, bool, 频次是否返回-->true
-        </enabled>
-        <occurrences>
-            <!--opt, int, 频次, range:[,], step:, unit:, unitType:, desc:达到最低频次的人脸库图片才返回,当enabled为true时必须存在-->
-            1
-        </occurrences>
-        <occurrencesSearchType>
-            <!--opt, enum, 频次检索方式, subType:string, [greaterThanOrEqual#大于等于,lessThan#小于,equal#等于], desc:当enabled为true时必须存在-->
-            greaterThanOrEqual
-        </occurrencesSearchType>
-    </OccurrencesInfo>
-    <faceScore>
-        <!--opt, int, 人脸评分, range:[-1,100], step:, unit:, unitType:, desc:-1表示评分未知(未对该人脸评分)-->1
-    </faceScore>
-    <FDIDList>
-        <!--opt, object, 人脸库列表, desc:支持查询多个人脸库搜索,理论上FDID和FDIDList是互斥的,若用户同时下发,则以FDIDList为准-->
-        <FDID>
-            <!--req, string, 人脸库ID, range:[1,64]-->test
-        </FDID>
-    </FDIDList>
-    <faceScoreMax>
-        <!--opt, int, 人脸评分范围最大值, range:[-1,100], step:, unit:, unitType:, desc:有效值[0-100],-1表示评分未知(未对该人脸评分),该节点可以和faceScore组合,此时faceScore表示该范围最小值,faceScore表示该范围最大值,如果单独使用,则最小值为0-->
-        0
-    </faceScoreMax>
-    <pictureStatus>
-        <!--opt, enum, 人脸图片状态, subType:string, [normal#正常人脸,abnormal#异常人脸],
-    desc:异常人脸(建模失败+人脸评分为低+图片url下载失败的),
-        Note:此搜索结果是设备根据当前算法识别效果提供的评判标准,异常图片可能影响人脸抓拍和比对的效果,如果为异常图片的,建议更换图片,后期随着算法准确率的提提升,此判断标准可能发生变化,因此此判断标准结果仅供参考,-->
-        normal
-    </pictureStatus>
-    <importStartTime>
-        <!--ro, opt, datetime, 入库开始时间-->1970-01-01T00:00:00+08:00
-    </importStartTime>
-    <importEndTime>
-        <!--ro, opt, datetime, 入库结束时间-->1970-01-01T00:00:00+08:00
-    </importEndTime>
-    <faceContrastSuccessStartTime>
-        <!--ro, opt, datetime, 人脸比对成功开始时间, desc:支持确认某段时间内监控场景有哪些人出现过。配合使用的查询条件:人脸库ID(FDID,包括:动态库、允许库、静态库)、排序类型(sortord)、排序顺序(order)-->
-        1970-01-01T00:00:00+08:00
-    </faceContrastSuccessStartTime>
-    <faceContrastSuccessEndTime>
-        <!--ro, opt, datetime, 人脸比对成功结束时间, desc:支持确认某段时间内监控场景有哪些人出现过。配合使用的查询条件:人脸库ID(FDID,包括:动态库,允许库、静态库)、排序类型(sortord)、排序顺序(order)-->
-        1970-01-01T00:00:00+08:00
-    </faceContrastSuccessEndTime>
-</FDSearchDescription>
-

+ 0 - 150
supervision-admin/resources/conf/acs/Face/SearchFaceInfoParamOutput.xml

@@ -1,150 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<FDSearchResult xmlns="http://www.isapi.org/ver20/XMLSchema" version="2.0">
-    <!--ro, opt, object, 查询结果, attr:version{req, string, 协议版本, range:[,]}-->
-    <searchID>
-        <!--ro, req, string, 搜索记录唯一标识, range:[,], desc:用来确认上层客户端是否为同一个(倘若是同一个,则设备记录内存,下次搜索加快速度)-->test
-    </searchID>
-    <responseStatus>
-        <!--ro, req, bool, 查询结果-->true
-    </responseStatus>
-    <responseStatusStrg>
-        <!--ro, req, enum, 查询状态字符串描述, subType:string, [OK#查询结束,MORE#还有数据等待查询,NO MATCH#没有匹配数据]-->OK
-    </responseStatusStrg>
-    <numOfMatches>
-        <!--ro, req, int, 本次返回的记录条数, range:[,], step:, unit:, unitType:-->1
-    </numOfMatches>
-    <totalMatches>
-        <!--ro, req, int, 符合条件的记录总条数, range:[,], step:, unit:, unitType:-->1
-    </totalMatches>
-    <progress>
-        <!--ro, opt, int, 查询进度, range:[0,100], step:, unit:, unitType:, desc:设备库的容量可能非常大,检索时间较长,对于远程检索时更加明显,为了提高检索性能,在交互链接中增加进度返回(只有在进度达到100的时候,就可以搜索出具体的数据<MatchList></MatchList>-->1
-    </progress>
-    <MatchList>
-        <!--ro, opt, array, 匹配结果列表, subType:object, range:[,]-->
-        <MatchElement>
-            <!--ro, opt, object, 匹配结果-->
-            <FDID>
-                <!--ro, opt, string, 人脸比对库唯一标示ID, range:[,]-->test
-            </FDID>
-            <thresholdValue>
-                <!--ro, opt, int, 检测阈值, range:[0,100], step:, unit:, unitType:, desc:阈值越大检测准确率越高-->1
-            </thresholdValue>
-            <bornTime>
-                <!--ro, opt, date, 人员出生日期-->1970-01-01+08:00
-            </bornTime>
-            <name>
-                <!--ro, req, string, 姓名, range:[1,32]-->test
-            </name>
-            <sex>
-                <!--ro, opt, enum, 性别, subType:string, [male#男,female#女]-->male
-            </sex>
-            <province>
-                <!--ro, opt, string, 省份, range:[,], desc:参考《全国各省份城市列表.txt》-->11
-            </province>
-            <city>
-                <!--ro, opt, string, 城市, range:[,], desc:参考《全国各省份城市列表.txt》-->11
-            </city>
-            <certificateType>
-                <!--ro, opt, enum, 证件类型, subType:string, [ID#身份证,passportID#护照,other#其他]-->ID
-            </certificateType>
-            <certificateNumber>
-                <!--ro, opt, string, 证件号, range:[8,32], desc:当certificateType为ID时,certificateNumber长度范围[8,18];当certificateType为passportID时,certificateNumber长度范围[8,32];当certificateType为other时,certificateNumber长度范围[8,18];-->test
-            </certificateNumber>
-            <picURL>
-                <!--ro, req, picurl, 人脸信息的对应图片的URL, desc:上层根据这个返回的URL在获取图片数据-->http://127.0.0.1
-            </picURL>
-            <PID>
-                <!--ro, req, string, 图片ID, range:[,]-->test
-            </PID>
-            <PersonInfoExtendList>
-                <!--ro, opt, array, 人员扩展信息列表, subType:object, range:[,]-->
-                <PersonInfoExtend>
-                    <!--ro, opt, object, 人员扩展信息-->
-                    <id>
-                        <!--ro, req, int, 人员扩展信息序号, range:[,], step:, unit:, unitType:-->1
-                    </id>
-                    <enable>
-                        <!--ro, req, bool, 人员扩展信息使能-->true
-                    </enable>
-                    <name>
-                        <!--ro, opt, string, 人员标签信息扩展名称, range:[,]-->test
-                    </name>
-                    <value>
-                        <!--ro, opt, string, 人员标签信息扩展内容, range:[,]-->test
-                    </value>
-                </PersonInfoExtend>
-            </PersonInfoExtendList>
-            <similarity>
-                <!--ro, opt, float, 相似度, range:[0.0,100.0], step:, unit:, unitType:-->0.0
-            </similarity>
-            <ModelingStatus>
-                <!--ro, opt, object, 建模状态, desc:后续使用这个字段,modelStatus将会去除-->
-                <FDID>
-                    <!--ro, opt, string, 人脸库ID, range:[,]-->test
-                </FDID>
-                <PID>
-                    <!--ro, opt, string, 图片ID, range:[,]-->test
-                </PID>
-                <name>
-                    <!--ro, req, string, 图片名称, range:[,]-->test
-                </name>
-                <status>
-                    <!--ro, req, enum, 建模状态, subType:string, [success#建模成功,failed#建模失败,none#尚未建模]-->success
-                </status>
-                <reason>
-                    <!--ro, opt, enum, 建模失败原因, subType:string, [noface#没有人脸,faceSizeSmall#图片尺寸太小,shadeFace#人脸被遮挡,unknow#未知错误,imageURLDownloadFailed#图片下载失败,noJpgPicture#图片不是jpg格式,errorPictureResolution#错误的图片分辨率,faceSizeBig#图片尺寸太大,diskError#磁盘错误,diskFull#磁盘满,analysisFailed#分析失败,multipleFaces#存在多个人脸], desc:当<status>==failed时存在-->noface
-                </reason>
-                <customHumanID>
-                    <!--ro, opt, string, 集成客户自定义人员ID, range:[,], desc:最小长度32-->12345678901234567890123456789012
-                </customHumanID>
-                <customFaceLibID>
-                    <!--ro, opt, string, 集成客户自定义人脸库ID, range:[,], desc:最小长度32-->12345678901234567890123456789012
-                </customFaceLibID>
-                <modeData>
-                    <!--ro, opt, string, 目标模型数据, range:[,], desc:传输过程中针对二进制非建模数据进行base64的加密处理-->test
-                </modeData>
-            </ModelingStatus>
-            <isNoSaveFDPicture>
-                <!--ro, opt, bool, 不保存人脸库图片, desc:若开启了导入图片或者建模时不保存原图功能,则需返回该节点为true,未开启则无需返回该节点-->true
-            </isNoSaveFDPicture>
-            <humanId>
-                <!--ro, opt, string, 人员ID, range:[,]-->test
-            </humanId>
-            <modelStatus>
-                <!--ro, opt, enum, 建模状态(旧), subType:string, [modeling#已建模,unmodeled#未建模,modelingFailed#建模失败]-->modeling
-            </modelStatus>
-            <FMCount>
-                <!--ro, opt, int, 人脸比对成功总次数, range:[,], step:, unit:, unitType:-->1
-            </FMCount>
-            <importTime>
-                <!--ro, opt, datetime, 入库时间-->1970-01-01T00:00:00+08:00
-            </importTime>
-            <UUPID>
-                <!--ro, opt, string, 人脸库底库图片唯一标识ID, range:[,]-->test
-            </UUPID>
-            <occurrences>
-                <!--ro, opt, int, 出现频次, range:[,], step:, unit:, unitType:, desc:仅搜索条件中启用频次返回,本字段才返回-->1
-            </occurrences>
-            <IMSIList>
-                <!--ro, opt, array, IMSI列表, subType:object, range:[,], desc:若人脸库类型为允许库,必须绑定至少一个IMSI号码,最多5个-->
-                <IMSIItem>
-                    <!--ro, opt, object, IMSI采集信息-->
-                    <IMSI>
-                        <!--ro, opt, string, IMSI号码, range:[,]-->123456789012345
-                    </IMSI>
-                    <count>
-                        <!--ro, opt, int, 比中次数, range:[,], step:, unit:, unitType:-->10
-                    </count>
-                    <lastFMTime>
-                        <!--ro, opt, datetime, 最近比对成功时间-->1970-01-01T00:00:00+08:00
-                    </lastFMTime>
-                </IMSIItem>
-            </IMSIList>
-            <lastFMTime>
-                <!--ro, opt, datetime, 最近比对成功时间-->1970-01-01T00:00:00+08:00
-            </lastFMTime>
-        </MatchElement>
-    </MatchList>
-</FDSearchResult>
-

+ 7 - 0
supervision-admin/resources/conf/acs/Face/SetUpFaceInfoOutputParam.json

@@ -0,0 +1,7 @@
+{
+  "statusCode": 1,
+  "statusString": "ok",
+  "subStatusCode": "ok",
+  "errorCode": 1,
+  "errorMsg": "ok"
+}

+ 59 - 0
supervision-admin/resources/conf/acs/User/AddUserInfoInputParam.json

@@ -0,0 +1,59 @@
+{
+  "UserInfo": {                          // 人员信息对象
+    "employeeNo": "test",                // 【必填】工号(人员ID)
+    "name": "test",                      // 【可选】姓名
+    "userType": "normal",                // 【必填】人员类型 [normal 普通人, visitor 来宾, blackList 黑名单人员]
+    "closeDelayEnabled": true,           // 【可选】是否启用关门延迟
+
+    "Valid": {                           // 【可选】有效期设置
+      "enable": true,                    // 【必填】是否启用有效期
+      "beginTime": "2017-08-01T17:30:08+08:00",  // 【必填】有效期开始时间(本地或UTC)
+      "endTime": "2017-08-01T17:30:08+08:00",    // 【必填】有效期结束时间(本地或UTC)
+      "timeType": "local"                // 【可选】时间类型 [local 设备本地时间, UTC 标准时间]
+    },
+
+    "belongGroup": "1,3,5",              // 【可选】所属群组
+    "password": "123456",                // 【可选】开门密码
+    "doorRight": "1,3",                  // 【可选】门权限(多个门用逗号分隔)
+
+    "RightPlan": [                       // 【可选】门权限计划(锁权限计划)
+      {
+        "doorNo": 1,                     // 门编号(锁ID)
+        "planTemplateNo": "1,3,5"        // 计划模板编号(多个模板编号取“或”关系)
+      }
+    ],
+
+    "maxOpenDoorTime": 0,                // 【可选】最大认证次数(0 表示无限制)
+    "openDoorTime": 1,                   // 【可选】已认证次数
+    "roomNumber": 123,                   // 【可选】房间号
+    "floorNumber": 1,                    // 【可选】楼层号
+    "doubleLockRight": true,             // 【可选】是否具备反锁开门权限
+    "localUIRight": true,                // 【可选】是否可使用设备本地UI操作
+
+    "userVerifyMode": "card",            // 【可选】验证方式(如 card 刷卡,fp 指纹,face 人脸等)
+    // 示例枚举:
+    // [cardAndPw, card, cardOrPw, fp, fpAndPw, fpOrCard, fpAndCard, fpAndCardAndPw,
+    //  faceOrFpOrCardOrPw, faceAndFp, faceAndPw, faceAndCard, face, employeeNoAndPw,
+    //  fpOrPw, employeeNoAndFp, employeeNoAndFpAndPw, faceAndFpAndCard,
+    //  faceAndPwAndFp, employeeNoAndFace, faceOrfaceAndCard, fpOrface, cardOrfaceOrPw]
+
+    "checkUser": true,                   // 【可选】是否校验重复添加人员(true 开启重复校验)
+    "numOfFace": 0,                      // 【可选】关联人脸数量(不支持可不返回)
+    "numOfFP": 0,                        // 【可选】关联指纹数量
+    "numOfCard": 0,                      // 【可选】关联卡数量
+    "gender": "male",                    // 【可选】性别 [male 男, female 女, unknown 未知]
+
+    "PersonInfoExtends": [               // 【可选】人员信息扩展
+      {
+        "value": "test"                  // 扩展内容(可自定义)
+      }
+    ],
+
+    "operateType": "byTerminal",         // 【可选】操作类型,如 byTerminal 表示按终端操作
+    "terminalNoList": [1],               // 【可选】终端ID列表(type 为 byTerminal 时必填)
+    "dynamicCode": "123456",             // 【可选】动态权限码
+    "callNumbers": ["1-1-1-401"],        // 【可选】呼叫号码列表(如 1-1-1-401)
+    "floorNumbers": [1, 2],              // 【可选】楼层列表(可配置多层)
+    "groupName": "test"                  // 【可选】组织架构名称
+  }
+}

+ 39 - 0
supervision-admin/resources/conf/acs/User/AddUserInfoOutputParam.json

@@ -0,0 +1,39 @@
+{
+  "statusCode": 1,
+  /* 只读 (ro),可选 (opt)
+     类型:int
+     含义:状态码。
+     当返回值为 1 时,表示操作成功且无特殊状态;
+     当无法用 1 表示时(如存在部分成功或异常情况),必须返回其他具体状态码。 */
+
+  "statusString": "ok",
+  /* 只读 (ro),可选 (opt)
+     类型:string
+     含义:状态描述。
+     当无法使用 "ok" 表示成功时("ok" 表示成功且无特殊状态),
+     必须返回其他描述信息。
+     范围:[1, 64] 个字符。 */
+
+  "subStatusCode": "ok",
+  /* 只读 (ro),可选 (opt)
+     类型:string
+     含义:子状态码。
+     当无法使用 "ok" 表示成功时("ok" 表示成功且无特殊状态),
+     必须返回具体的子状态码,用于进一步区分结果状态。
+     范围:[1, 64] 个字符。 */
+
+  "errorCode": 1,
+  /* 只读 (ro),可选 (opt)
+     类型:int
+     含义:错误码。
+     当 statusCode ≠ 1 时,表示操作失败,
+     此字段必须返回并与 subStatusCode 对应,用于辅助定位错误原因。 */
+
+  "errorMsg": "ok"
+  /* 只读 (ro),可选 (opt)
+     类型:string
+     含义:错误信息。
+     当 statusCode ≠ 1 时必须返回,说明具体的失败原因。
+     描述信息可在后续版本中优化或扩展,不固定。
+     示例:当失败时,可能返回 “参数错误”、“网络异常”、“用户已存在”等信息。 */
+}

+ 34 - 0
supervision-admin/resources/conf/acs/User/DeleteUserInfoInputParam.json

@@ -0,0 +1,34 @@
+{
+  "UserInfoDetail": {
+    /*opt, object, 用户信息*/
+    "mode": "all",
+    /*req, enum, 删除模式, subType:string,
+      [all#删除所有, byEmployeeNo#按工号],
+      desc: all 表示删除设备上所有人员,byEmployeeNo 表示按人员ID列表删除指定人员 */
+
+    "EmployeeNoList": [
+      /*opt, array, 人员ID列表, subType:object, range:[,],
+        desc: 当 mode=byEmployeeNo 时需配置此字段 */
+      {
+        "employeeNo": "test"
+        /*opt, string, 工号(人员ID), range:[,]*/
+      }
+    ],
+
+    "operateType": "byTerminal",
+    /*opt, enum, 操作类型, subType:string,
+      [byTerminal#按终端操作, byOrg#按组织操作, byTerminalOrg#按终端组织操作],
+      desc: 指定删除操作的执行范围 */
+
+    "terminalNoList": [1, 2, 3, 4],
+    /*opt, array, 终端列表, subType:int, range:[,],
+      dep:and,{$.UserInfoDetail.operateType,eq,byTerminal},
+      desc: operateType=byTerminal 时需填写终端号 */
+
+    "orgNoList": [1, 2, 3, 4]
+    /*opt, array, 组织列表, subType:int, range:[,],
+      dep:or,{$.UserInfoDetail.operateType,eq,byOrg},{$.UserInfoDetail.operateType,eq,byTerminalOrg},
+      desc: operateType 为组织相关操作时需填写组织编号 */
+  }
+}
+

+ 7 - 0
supervision-admin/resources/conf/acs/User/DeleteUserInfoOutputParam.json

@@ -0,0 +1,7 @@
+{
+  "statusCode": 1,          // 状态码:1 表示成功且无特殊状态;非 1 表示失败或异常状态
+  "statusString": "ok",     // 状态描述:ok 表示成功;无法用 "ok" 表示时需返回具体描述
+  "subStatusCode": "ok",    // 子状态码:ok 表示无特殊状态,否则需返回具体说明
+  "errorCode": 1,           // 错误码:当 statusCode ≠ 1 时使用,对应 subStatusCode 的具体错误类型
+  "errorMsg": "ok"          // 错误信息:当 statusCode ≠ 1 时必须返回,用于解释错误原因
+}

+ 1 - 0
supervision-admin/resources/conf/acs/User/GetUserCountInputParam.json

@@ -0,0 +1 @@
+{}

+ 0 - 0
supervision-admin/resources/conf/acs/User/GetUserCountOutputParam.json


+ 32 - 0
supervision-admin/resources/conf/acs/User/GetUserInfoInputParam.json

@@ -0,0 +1,32 @@
+{
+  "UserInfoSearchCond": {
+    /* 可选,对象类型,查询条件 */
+
+    "searchID": "123",
+    /* 必填,字符串类型,搜索记录唯一标识。
+       说明:用于确认上层客户端是否为同一次查询任务。
+       若为同一 searchID,设备会缓存上次查询结果,加快查询速度。*/
+
+    "searchResultPosition": 0,
+    /* 可选,整数类型,查询起始位置。
+       说明:当记录较多、一次查询无法返回全部结果时,可通过该字段指定从第几条开始继续查询。
+       例如上次查询了0~29条记录,下次可设为30继续查询后续结果。
+       合法范围:0 ~ (设备已存储总记录数 - 1)。*/
+
+    "maxResults": 30,
+    /* 可选,整数类型,本次调用最多返回的记录数。
+       说明:若超过设备支持的最大返回数量,设备会自动按上限返回,不报错。*/
+
+    "EmployeeNoList": [
+      /* 可选,数组类型,指定按人员ID(工号)精确查询 */
+      {
+        "employeeNo": "test"
+        /* 可选,字符串类型,工号(人员ID) */
+      }
+    ],
+
+    "fuzzySearch": "test"
+    /* 可选,字符串类型,模糊搜索关键字。
+       说明:可按姓名、工号等字段模糊匹配查询。*/
+  }
+}

+ 122 - 0
supervision-admin/resources/conf/acs/User/GetUserInfoOutputParam.json

@@ -0,0 +1,122 @@
+{
+  "UserInfoSearch": {
+    /* 只读(ro),可选(opt),object类型 —— 查询结果对象 */
+
+    "searchID": "test",
+    /* 只读(ro),必填(req),string类型 —— 搜索记录唯一标识ID */
+
+    "responseStatusStrg": "OK",
+    /* 只读(ro),必填(req),枚举类型(enum),查询状态:
+       - OK:查询结束
+       - MORE:还有数据待查询
+       - NO MATCH:没有匹配数据 */
+
+    "numOfMatches": 1,
+    /* 只读(ro),必填(req),int类型 —— 当前返回的记录条数 */
+
+    "totalMatches": 1,
+    /* 只读(ro),必填(req),int类型 —— 符合条件的记录总条数 */
+
+    "UserInfo": [
+      /* 只读(ro),可选(opt),array类型 —— 人员信息数组 */
+      {
+        "employeeNo": "test",
+        /* 只读(ro),必填(req),string类型 —— 工号(人员ID) */
+
+        "name": "test",
+        /* 只读(ro),可选(opt),string类型 —— 姓名 */
+
+        "userType": "normal",
+        /* 只读(ro),必填(req),string类型 —— 人员类型 */
+
+        "closeDelayEnabled": true,
+        /* 只读(ro),可选(opt),bool类型 —— 是否启用关门延迟 */
+
+        "Valid": {
+          /* 只读(ro),可选(opt),object类型 —— 有效期参数 */
+          "enable": true,
+          /* 是否启用有效期 */
+          "beginTime": "2025-01-01T00:00:00",
+          /* 有效期起始时间 */
+          "endTime": "2025-12-31T23:59:59",
+          /* 有效期结束时间 */
+          "timeType": "local"
+          /* 时间类型(local/UTC) */
+        },
+
+        "belongGroup": "1,3,5",
+        /* 所属群组,多个以逗号分隔 */
+
+        "password": "123456",
+        /* 登录/开门密码 */
+
+        "doorRight": "1,3",
+        /* 门权限(如“1,3”代表对门1、门3有开门权限) */
+
+        "RightPlan": [
+          /* 门权限计划 */
+          {
+            "doorNo": 1,
+            /* 门编号 */
+            "planTemplateNo": "1,3,5"
+            /* 权限计划模板编号 */
+          }
+        ],
+
+        "maxOpenDoorTime": 0,
+        /* 最大可认证开门次数 */
+
+        "openDoorTime": 0,
+        /* 已认证次数 */
+
+        "roomNumber": 123,
+        /* 房间号 */
+
+        "floorNumber": 1,
+        /* 层号 */
+
+        "doubleLockRight": true,
+        /* 是否具有反锁开门权限(true=有权限) */
+
+        "localUIRight": true,
+        /* 是否具有设备本地UI访问权限 */
+
+        "userVerifyMode": "card",
+        /* 人员验证方式(枚举):
+           可选值如:card, face, fp, faceAndPw 等 */
+
+        "dynamicCode": "123456",
+        /* 动态权限码 */
+
+        "callNumbers": ["1-1-1-401", "1-1-1-402", "1-1-1-403"],
+        /* 呼叫号码列表(可与房间号关联) */
+
+        "floorNumbers": [1, 2],
+        /* 层号列表(支持多层) */
+
+        "numOfFace": 0,
+        /* 关联人脸数量 */
+
+        "numOfFP": 0,
+        /* 关联指纹数量 */
+
+        "numOfCard": 0,
+        /* 关联卡数量 */
+
+        "gender": "male",
+        /* 性别(male=男, female=女, unknown=未知) */
+
+        "PersonInfoExtends": [
+          /* 人员信息扩展字段 */
+          {
+            "value": "test"
+            /* 扩展内容 */
+          }
+        ],
+
+        "groupName": "test"
+        /* 组织架构名称(如部门名) */
+      }
+    ]
+  }
+}

+ 184 - 0
supervision-admin/resources/conf/acs/User/ModifyUserInfoInputParam.json

@@ -0,0 +1,184 @@
+{
+  "UserInfo": {
+    /* 可选 (opt),对象类型
+       含义:人员信息,用于修改设备中已存在的人员信息。*/
+
+    "employeeNo": "test",
+    /* 必填 (req),字符串类型
+       含义:工号(人员ID),作为人员的唯一标识,用于匹配要修改的人员。*/
+
+    "name": "test",
+    /* 可选 (opt),字符串类型
+       含义:姓名,用于更新人员名称。*/
+
+    "userType": "normal",
+    /* 必填 (req),枚举类型
+       含义:人员类型。
+       可选值:
+       - normal:普通人(主人)
+       - visitor:来宾(访客)
+       - blackList:非授权名单人
+       注意:字段名中不能有空格(原文 userType 后面多了一个空格,应改为 userType)。*/
+
+    "closeDelayEnabled": true,
+    /* 可选 (opt),布尔类型
+       含义:是否启用关门延迟。true 表示启用,false 表示不启用。*/
+
+    "Valid": {
+      /* 可选 (opt),对象类型
+         含义:有效期设置。*/
+
+      "enable": true,
+      /* 必填 (req),布尔类型
+         含义:是否使能有效期。false 表示长期有效,true 表示启用时间限制。*/
+
+      "beginTime": "2017-08-01T17:30:08+08:00",
+      /* 必填 (req),字符串类型(日期时间)
+         含义:有效期起始时间。
+         若 timeType 为 local 或不存在,则为设备本地时间;
+         若 timeType 为 UTC,则需带时区信息,如 +08:00。*/
+
+      "endTime": "2017-08-01T17:30:08+08:00",
+      /* 必填 (req),字符串类型(日期时间)
+         含义:有效期结束时间。
+         格式说明同上。*/
+
+      "timeType": "local"
+      /* 可选 (opt),枚举类型
+         含义:时间类型。
+         可选值:
+         - local:设备本地时间
+         - UTC:协调世界时 */
+    },
+
+    "belongGroup": "1,3,5",
+    /* 可选 (opt),字符串类型
+       含义:所属群组,可配置多个群组 ID,用逗号分隔。*/
+
+    "password": "123456",
+    /* 可选 (opt),字符串类型
+       含义:密码,可为空。*/
+
+    "doorRight": "1,3",
+    /* 可选 (opt),字符串类型
+       含义:门权限,多个门号之间用逗号分隔。*/
+
+    "RightPlan": [
+      /* 可选 (opt),数组类型
+         含义:门权限计划(锁权限计划)。 */
+      {
+        "doorNo": 1,
+        /* 可选 (opt),整数类型
+           含义:门编号(锁 ID)。*/
+
+        "planTemplateNo": "1,3,5"
+        /* 可选 (opt),字符串类型
+           含义:计划模板编号,可配置多个模板编号,用逗号分隔;
+           同一门号的多个模板以“权限或”的方式叠加。*/
+      }
+    ],
+
+    "maxOpenDoorTime": 0,
+    /* 可选 (opt),整数类型
+       含义:最大认证次数。0 表示无次数限制。*/
+
+    "openDoorTime": 1,
+    /* 可选 (opt),整数类型
+       含义:已认证次数。*/
+
+    "roomNumber": 123,
+    /* 可选 (opt),整数类型
+       含义:房间号。*/
+
+    "floorNumber": 1,
+    /* 可选 (opt),整数类型
+       含义:层号。*/
+
+    "doubleLockRight": true,
+    /* 可选 (opt),布尔类型
+       含义:是否具备反锁开门权限。true 表示有权限。*/
+
+    "localUIRight": true,
+    /* 可选 (opt),布尔类型
+       含义:是否具有设备本地 UI 界面访问权限。*/
+
+    "userVerifyMode": "card",
+    /* 可选 (opt),枚举类型
+       含义:人员验证方式。
+       可选值:
+       cardAndPw#刷卡+密码,
+       card#刷卡,
+       cardOrPw#刷卡或密码,
+       fp#指纹,
+       fpAndPw#指纹+密码,
+       fpOrCard#指纹或刷卡,
+       fpAndCard#指纹+刷卡,
+       fpAndCardAndPw#指纹+刷卡+密码,
+       faceOrFpOrCardOrPw#人脸或指纹或刷卡或密码,
+       faceAndFp#人脸+指纹,
+       faceAndPw#人脸+密码,
+       faceAndCard#人脸+刷卡,
+       face#人脸,
+       employeeNoAndPw#工号+密码,
+       fpOrPw#指纹或密码,
+       employeeNoAndFp#工号+指纹,
+       employeeNoAndFpAndPw#工号+指纹+密码,
+       faceAndFpAndCard#人脸+指纹+刷卡,
+       faceAndPwAndFp#人脸+密码+指纹,
+       employeeNoAndFace#工号+人脸,
+       faceOrfaceAndCard#人脸或人脸+刷卡,
+       fpOrface#指纹或人脸,
+       cardOrfaceOrPw#刷卡或人脸或密码。
+       说明:为空时表示清空该人员的验证方式。*/
+
+    "checkUser": true,
+    /* 可选 (opt),布尔类型
+       含义:是否进行人员重复添加校验。
+       true:开启重复校验;
+       false:关闭(当确认设备内无人员时可关闭以提升下发速度)。*/
+
+    "gender": "male",
+    /* 可选 (opt),枚举类型
+       含义:性别。
+       可选值:male(男)、female(女)、unknown(未知)。*/
+
+    "PersonInfoExtends": [
+      /* 可选 (opt),数组类型
+         含义:扩展的人员信息,可根据业务自定义附加信息。 */
+      {
+        "value": "test"
+        /* 可选 (opt),字符串类型
+           含义:扩展信息内容。*/
+      }
+    ],
+
+    "dynamicCode": "123456",
+    /* 可选 (opt),字符串类型
+       含义:动态权限码,用于动态授权场景。*/
+
+    "callNumbers": ["1-1-1-401"],
+    /* 可选 (opt),字符串数组
+       含义:呼叫号码列表。
+       默认格式为 X-X-X-X,如 “1-1-1-401”。*/
+
+    "floorNumbers": [1, 2],
+    /* 可选 (opt),整数数组
+       含义:层号列表,为 floorNumber 字段的扩展,支持配置多个层号。*/
+
+    "operateType": "byTerminal",
+    /* 可选 (opt),字符串类型
+       含义:操作类型。
+       可选值:
+       - byTerminal:按终端操作。*/
+
+    "terminalNoList": [1],
+    /* 可选 (opt),整数数组
+       含义:终端编号列表。
+       当 operateType 为 byTerminal 或 byTerminalOrg 时必填;
+       当前仅支持单个终端。*/
+
+    "groupName": "test"
+    /* 可选 (opt),字符串类型
+       含义:组织架构名称,长度范围:[1,64] 字符。*/
+  }
+}

+ 7 - 0
supervision-admin/resources/conf/acs/User/ModifyUserInfoOutputParam.json

@@ -0,0 +1,7 @@
+{
+  "statusCode": 1,          // 状态码:1 表示成功且无特殊状态;非 1 表示失败或异常状态
+  "statusString": "ok",     // 状态描述:ok 表示成功;当无法用 "ok" 表示时需返回具体状态描述
+  "subStatusCode": "ok",    // 子状态码:ok 表示无特殊状态,否则需返回具体子状态说明
+  "errorCode": 1,           // 错误码:当 statusCode ≠ 1 时使用,对应 subStatusCode 的具体错误
+  "errorMsg": "ok"          // 错误信息:当 statusCode ≠ 1 时必须返回,用于解释错误原因
+}

+ 63 - 0
supervision-admin/resources/conf/acs/User/SetUserInfoInputParam.json

@@ -0,0 +1,63 @@
+{
+  "UserInfo": {
+    "employeeNo": "test",                // 必填,工号(人员ID),作为人员唯一标识
+    "deleteUser": true,                  // 可选,是否删除该人员(true-删除,false-不删除)
+    "name": "test",                      // 可选,人员姓名
+    "userType": "normal",                // 必填,人员类型:normal=普通人,visitor=访客,blackList=黑名单
+    "closeDelayEnabled": true,           // 可选,是否启用关门延迟(true-是,false-否)
+
+    "Valid": {                           // 可选,有效期信息
+      "enable": true,                    // 是否启用有效期(true-启用,false-不启用表示长期有效)
+      "beginTime": "2025-01-01T08:00:00",// 有效期开始时间,本地时间格式:YYYY-MM-DDTHH:mm:ss
+      "endTime": "2030-12-31T23:59:59",  // 有效期结束时间
+      "timeType": "local"                // 时间类型:local=设备本地时间,UTC=协调世界时
+    },
+
+    "belongGroup": "1,3,5",              // 可选,所属群组编号(多个群组用逗号分隔)
+    "password": "123456",                // 可选,开门密码
+    "doorRight": "1,3",                  // 可选,门权限(代表对门1、门3有权限)
+
+    "RightPlan": [                       // 可选,门权限计划(数组)
+      {
+        "doorNo": 1,                     // 门编号
+        "planTemplateNo": "1,3,5"        // 权限计划模板编号(多个模板用逗号分隔)
+      }
+    ],
+
+    "maxOpenDoorTime": 0,                // 可选,最大认证次数(0表示不限)
+    "openDoorTime": 0,                   // 可选,已认证次数
+    "roomNumber": 123,                   // 可选,房间号
+    "floorNumber": 1,                    // 可选,所在楼层号
+    "doubleLockRight": true,             // 可选,反锁开门权限(true-有权限)
+    "localUIRight": true,                // 可选,是否具有设备本地UI访问权限(true-有权限)
+
+    "userVerifyMode": "card",            // 可选,人员验证方式:
+    // cardAndPw#刷卡+密码
+    // card#刷卡
+    // cardOrPw#刷卡或密码
+    // fp#指纹
+    // face#人脸
+    // faceAndCard#人脸+刷卡
+    // faceAndPw#人脸+密码
+    // 等多种组合方式
+
+    "checkUser": true,                   // 可选,是否进行人员重复添加校验(true-校验,false-不校验)
+    "gender": "male",                    // 可选,性别(male#男,female#女,unknown#未知)
+
+    "PersonInfoExtends": [               // 可选,人员扩展信息(自定义字段)
+      {
+        "value": "test"                  // 扩展信息内容
+      }
+    ],
+
+    "dynamicCode": "123456",             // 可选,动态权限码(用于临时权限或访客权限)
+    "callNumbers": [                     // 可选,呼叫号码列表
+      "1-1-1-401",
+      "1-1-1-402",
+      "1-1-1-403"
+    ],
+
+    "floorNumbers": [1, 2],              // 可选,层号列表(多个楼层)
+    "groupName": "test"                  // 可选,组织架构名称
+  }
+}

+ 12 - 0
supervision-admin/resources/conf/acs/User/SetUserInfoOutputParam.json

@@ -0,0 +1,12 @@
+{
+  "statusCode":  1,
+  /*ro, opt, int, 状态码, range:[,], step:, unit:, unitType:, desc:无法用1表示时(1表示成功且无特殊状态)必须返回*/
+  "statusString":  "ok",
+  /*ro, opt, string, 状态描述, range:[1,64], desc:无法用ok表示时(ok表示成功且无特殊状态)必须返回*/
+  "subStatusCode":  "ok",
+  /*ro, opt, string, 子状态码, range:[1,64], desc:无法用ok表示(ok表示成功且无特殊状态)必须返回*/
+  "errorCode":  1,
+  /*ro, opt, int, 错误码, range:[,], step:, unit:, unitType:, desc:当statusCode不为1时,与subStatusCode对应*/
+  "errorMsg":  "ok"
+  /*ro, opt, string, 错误信息, range:[,], desc:当statusCode不为1时,必须返回,解释信息在协议约束中,允许设备在后续的版本迭代中,进行优化丰富提升(不限制死)*/
+}

+ 4 - 5
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/CarCameraDeviceManager.java

@@ -4,7 +4,7 @@ package com.supervision.web.ConnectSDK.carCamera;
 import com.supervision.web.ConnectSDK.carCamera.NetSDKDemo.HCNetSDK;
 import com.supervision.web.ConnectSDK.carCamera.alarm.Alarm;
 import com.supervision.web.ConnectSDK.carCamera.alarm.FMSGCallBack;
-import com.supervision.web.ConnectSDK.carCamera.alarm.FMSGCallBack_V31;
+import com.supervision.web.ConnectSDK.carCamera.alarm.CarCameraFMSGCallBack_V31;
 import com.supervision.web.ConnectSDK.util.DeviceSession;
 import com.supervision.web.ConnectSDK.util.HikSDKManager;
 import com.supervision.web.ConnectSDK.util.SdkType;
@@ -15,7 +15,6 @@ import org.springframework.stereotype.Component;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
-import java.nio.charset.Charset;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.concurrent.ConcurrentHashMap;
@@ -48,7 +47,7 @@ public class CarCameraDeviceManager {
     private int lListenHandle = -1;
 
     /** 报警布防回调 */
-    private FMSGCallBack_V31 fMSFCallBack_V31;
+    private CarCameraFMSGCallBack_V31 fMSFCallBack_V31;
 
     /** 报警监听回调(不常用) */
     private FMSGCallBack fMSFCallBack;
@@ -114,7 +113,7 @@ public class CarCameraDeviceManager {
         // 在SDK初始化之后即可以调用,多台设备对接时也只需要调用一次设置一个回调函数,回调函数里面接收数据之后可以通过报警设备信息(NET_DVR_ALARMER)中lUserID等参数判断区分设备。
         if (fMSFCallBack_V31 != null) return; // 防止重复注册
 
-        fMSFCallBack_V31 = new FMSGCallBack_V31();
+        fMSFCallBack_V31 = new CarCameraFMSGCallBack_V31();
         boolean ok = hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(
                 fMSFCallBack_V31,
                 null
@@ -405,4 +404,4 @@ public class CarCameraDeviceManager {
             }
         }
     }
-}
+}

+ 92 - 0
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/CommonMethod/CarDoorEventManage.java

@@ -0,0 +1,92 @@
+package com.supervision.web.ConnectSDK.carCamera.CommonMethod;
+
+import com.supervision.web.ConnectSDK.peopleDoor.NetSDKDemo.HCNetSDK;
+import com.supervision.web.ConnectSDK.peopleDoor.alarm.PeopleDoorFMSGCallBack_V31;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CarDoorEventManage {
+
+    private static final Logger logger = LoggerFactory.getLogger(com.supervision.web.ConnectSDK.carCamera.CommonMethod.CarDoorEventManage.class);
+
+    // SDK 实例
+    private static final HCNetSDK sdk = HCNetSDK.INSTANCE;
+
+    // 登录返回的用户句柄
+    private int lUserID = -1;
+
+    // 布防通道句柄
+    private int lAlarmHandle = -1;
+
+    /**
+     * 初始化并布防门禁设备,接收实时事件
+     */
+    public void initPeopleDoorAlarm(String ip, short port, String username, String password) {
+        // 初始化 SDK
+        if (!sdk.NET_DVR_Init()) {
+            logger.error("SDK 初始化失败!");
+            return;
+        }
+        logger.info(" SDK 初始化成功");
+
+        // 设置报警回调函数 (V31)
+        boolean setCb = sdk.NET_DVR_SetDVRMessageCallBack_V31( new PeopleDoorFMSGCallBack_V31(), null);
+        if (!setCb) {
+            logger.error("设置报警回调函数失败,错误码:" + sdk.NET_DVR_GetLastError());
+            return;
+        }
+        logger.info(" 报警回调函数(V31)设置成功");
+
+        // 登录设备(PeopleDoorDeviceManager里已登录)
+//        HCNetSDK.NET_DVR_USER_LOGIN_INFO loginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
+//        HCNetSDK.NET_DVR_DEVICEINFO_V40 deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
+
+        // 登录信息设置
+//        System.arraycopy(ip.getBytes(), 0, loginInfo.sDeviceAddress, 0, ip.length());
+//        System.arraycopy(username.getBytes(), 0, loginInfo.sUserName, 0, username.length());
+//        System.arraycopy(password.getBytes(), 0, loginInfo.sPassword, 0, password.length());
+//        loginInfo.wPort = port;
+//        loginInfo.bUseAsynLogin = false; // 同步登录
+//
+//        lUserID = sdk.NET_DVR_Login_V40(loginInfo, deviceInfo);
+//        if (lUserID < 0) {
+//            logger.error("设备登录失败,错误码:" + sdk.NET_DVR_GetLastError());
+//            return;
+//        }
+//        logger.info(" 登录成功,设备IP:" + ip + ",用户句柄:" + lUserID);
+
+        // 布防设置
+//        HCNetSDK.NET_DVR_SETUPALARM_PARAM alarmParam = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
+//        alarmParam.dwSize = alarmParam.size();
+//        alarmParam.byLevel = 1;      // 0-一级布防, 1-二级布防
+//        alarmParam.byAlarmInfoType = 1; // 1: 新报警信息(JSON结构)
+//        alarmParam.byRetAlarmTypeV40 = 1; // 返回V40结构体信息
+//
+//        lAlarmHandle = sdk.NET_DVR_SetupAlarmChan_V41(lUserID, alarmParam);
+//        if (lAlarmHandle < 0) {
+//            logger.error("布防失败,错误码:" + sdk.NET_DVR_GetLastError());
+//            return;
+//        }
+//        logger.info(" 布防成功,开始接收实时事件");
+    }
+
+    /**
+     * 撤防并释放资源
+     */
+//    public void closePeopleDoorAlarm() {
+//        if (lAlarmHandle >= 0) {
+//            sdk.NET_DVR_CloseAlarmChan_V30(lAlarmHandle);
+//            logger.info("撤防成功");
+//        }
+//        if (lUserID >= 0) {
+//            sdk.NET_DVR_Logout(lUserID);
+//            logger.info("设备登出成功");
+//        }
+//        sdk.NET_DVR_Cleanup();
+//        logger.info("SDK 清理完成");
+//    }
+
+
+}

+ 2 - 5
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/alarm/Alarm.java

@@ -5,10 +5,7 @@ import com.supervision.web.ConnectSDK.carCamera.CommonMethod.osSelect;
 import com.supervision.web.ConnectSDK.carCamera.NetSDKDemo.HCNetSDK;
 import com.sun.jna.Native;
 import com.sun.jna.Pointer;
-import com.supervision.web.ConnectSDK.carDoor.hik.ITCMain;
 import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
 import java.util.Scanner;
@@ -26,7 +23,7 @@ public class Alarm {
 
     private int lListenHandle = -1; // 报警监听句柄
 
-    private FMSGCallBack_V31 fMSFCallBack_V31 = null; // 报警布防回调函数
+    private CarCameraFMSGCallBack_V31 fMSFCallBack_V31 = null; // 报警布防回调函数
 
     private FMSGCallBack fMSFCallBack = null; // 报警监听回调函数
 
@@ -97,7 +94,7 @@ public class Alarm {
 
         // 设置报警回调函数
         if (fMSFCallBack_V31 == null) {
-            fMSFCallBack_V31 = new FMSGCallBack_V31();
+            fMSFCallBack_V31 = new CarCameraFMSGCallBack_V31();
             Pointer pUser = null;
             boolean setCallback = hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(
                     fMSFCallBack_V31, // fMessageCallBack [in] 回调函数

+ 2 - 5
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/alarm/AlarmDataParse.java → supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/alarm/CarCameraAlarmDataParse.java

@@ -7,8 +7,6 @@ import com.sun.jna.Pointer;
 import com.supervision.web.ConnectSDK.util.GetCarInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
 import java.io.*;
@@ -17,9 +15,9 @@ import java.text.SimpleDateFormat;
 import java.util.Date;
 
 @Component
-public class AlarmDataParse {
+public class CarCameraAlarmDataParse {
 
-    private static final Logger logger = LoggerFactory.getLogger(AlarmDataParse.class);
+    private static final Logger logger = LoggerFactory.getLogger(CarCameraAlarmDataParse.class);
 
     private HCNetSDK hCNetSDK;
 
@@ -711,7 +709,6 @@ public class AlarmDataParse {
                     strVideoIntercomAlarm.uAlarmInfo.read();
                     logger.info("byZoneType :" + strVideoIntercomAlarm.uAlarmInfo.struZoneAlarm.byZoneType);
                 }
-
                 break;
             case HCNetSDK.COMM_UPLOAD_VIDEO_INTERCOM_EVENT: //可视对讲事件记录信息
                 logger.info("可视对讲事件记录报警触发");

+ 2 - 2
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/alarm/FMSGCallBack_V31.java → supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/alarm/CarCameraFMSGCallBack_V31.java

@@ -6,7 +6,7 @@ import com.sun.jna.Pointer;
 import org.springframework.stereotype.Component;
 
 @Component
-public class FMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {
+public class CarCameraFMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {
 
     // 报警信息回调函数
     @Override
@@ -17,7 +17,7 @@ public class FMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {
             int dwBufLen, // dwBufLen [out] 报警信息缓存大小
             Pointer pUser // pUser[out] 用户数据
     ) {
-        AlarmDataParse.alarmDataHandle(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser);
+        CarCameraAlarmDataParse.alarmDataHandle(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser);
         return true;
     }
 

+ 1 - 1
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/carCamera/alarm/FMSGCallBack.java

@@ -15,7 +15,7 @@ public class FMSGCallBack implements HCNetSDK.FMSGCallBack {
     // 报警信息回调函数
     @Override
     public void invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
-        AlarmDataParse.alarmDataHandle(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser);
+        CarCameraAlarmDataParse.alarmDataHandle(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser);
         return;
     }
 

+ 3 - 7
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/AcsMain.java

@@ -2,18 +2,13 @@
 package com.supervision.web.ConnectSDK.peopleDoor.Acs;
 
 
-import com.supervision.web.ConnectSDK.carCamera.alarm.Alarm;
-import com.supervision.web.ConnectSDK.peopleDoor.Commom.osSelect;
+import com.supervision.web.ConnectSDK.peopleDoor.CommonMethod.osSelect;
 import com.supervision.web.ConnectSDK.peopleDoor.NetSDKDemo.HCNetSDK;
 import com.sun.jna.Native;
 import org.json.JSONException;
 import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
-import java.io.UnsupportedEncodingException;
-
 @Component
 public class AcsMain {
 
@@ -279,4 +274,5 @@ public class AcsMain {
         }
 
     }
-}//AcsMain  Class结束
+
+}

+ 1 - 2
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/CardManage.java

@@ -1,13 +1,12 @@
 package com.supervision.web.ConnectSDK.peopleDoor.Acs;
 
 
-import com.supervision.web.ConnectSDK.peopleDoor.Commom.ConfigFileUtil;
+import com.supervision.web.ConnectSDK.peopleDoor.CommonMethod.ConfigFileUtil;
 import com.supervision.web.ConnectSDK.peopleDoor.NetSDKDemo.HCNetSDK;
 import com.sun.jna.ptr.IntByReference;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
 import java.util.HashMap;

+ 107 - 0
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/EventSearch.java

@@ -1,5 +1,9 @@
 package com.supervision.web.ConnectSDK.peopleDoor.Acs;
 
+import cn.hutool.json.JSONException;
+import cn.hutool.json.JSONObject;
+import com.sun.jna.NativeLong;
+import com.sun.jna.ptr.IntByReference;
 import com.supervision.web.ConnectSDK.peopleDoor.NetSDKDemo.HCNetSDK;
 import com.sun.jna.Pointer;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -11,6 +15,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 
 /**
  * 事件查询模块
@@ -146,4 +151,106 @@ public final class EventSearch {
         return;
     }
 
+    /**
+     * 门禁事件查询(支持按时间段、事件类型、工号、卡号查询)
+     * 功能说明:
+     * 通过调用海康 SDK 的 NET_DVR_StartRemoteConfig / NET_DVR_GetNextRemoteConfig 接口,
+     * 查询设备的门禁事件记录,并可选地保存抓拍图片。
+     *
+     * @param lUserID     登录返回的用户句柄(设备登录成功后获得)
+     * @param employeeNo  工号(可选,传 null 或空字符串表示不按工号过滤)
+     * @param cardNo      卡号(可选,传 null 或空字符串表示不按卡号过滤)
+     * @param majorType   主事件类型(可选,传 0 表示查询所有主类型)
+     * @param minorType   次事件类型(可选,传 0 表示查询所有次类型)
+     * @param startTime   查询起始时间(可选,null 时默认前 24 小时)
+     * @param endTime     查询结束时间(可选,null 时默认当前时间)
+     * @throws InterruptedException         查询等待时线程中断
+     */
+    public void searchEventByCondition(int lUserID, String employeeNo, String cardNo, int majorType, int minorType,
+                                       HCNetSDK.NET_DVR_TIME startTime, HCNetSDK.NET_DVR_TIME endTime)
+            throws InterruptedException {
+
+
+
+        HCNetSDK.NET_DVR_ACS_EVENT_COND struCond = new HCNetSDK.NET_DVR_ACS_EVENT_COND();
+        struCond.dwSize = struCond.size();
+
+        // 事件类型过滤(0表示全部)
+        struCond.dwMajor = majorType;  // 主事件类型,例如:1-报警,2-门禁事件等
+        struCond.dwMinor = minorType;  // 次事件类型,例如刷卡、刷脸、报警子类型
+
+        // 设置时间范围
+        struCond.struStartTime = startTime;
+        struCond.struEndTime = endTime;
+
+        // 按工号或卡号查询
+        if (employeeNo != null && !employeeNo.isEmpty()) {
+            byte[] empBytes = employeeNo.getBytes(StandardCharsets.UTF_8);
+            System.arraycopy(empBytes, 0, struCond.byEmployeeNo, 0, Math.min(empBytes.length, struCond.byEmployeeNo.length));
+        }
+        if (cardNo != null && !cardNo.isEmpty()) {
+            byte[] cardBytes = cardNo.getBytes(StandardCharsets.UTF_8);
+            System.arraycopy(cardBytes, 0,
+                    struCond.byCardNo, 0,
+                    Math.min(cardBytes.length, struCond.byCardNo.length));
+        }
+
+        struCond.byPicEnable = 1;  // 是否需要返回图片
+        struCond.write();
+
+        int handle = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_GET_ACS_EVENT,
+                struCond.getPointer(), struCond.size(), null, null);
+        if (handle < 0) {
+            System.out.println("NET_DVR_StartRemoteConfig 调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());
+            return;
+        }
+
+        HCNetSDK.NET_DVR_ACS_EVENT_CFG struEvent = new HCNetSDK.NET_DVR_ACS_EVENT_CFG();
+        struEvent.dwSize = struEvent.size();
+
+        int count = 0;
+        while (true) {
+            int status = hCNetSDK.NET_DVR_GetNextRemoteConfig(handle, struEvent.getPointer(), struEvent.size());
+            if (status == HCNetSDK.NET_SDK_GET_NEXT_STATUS_NEED_WAIT) {
+                Thread.sleep(10);
+                continue;
+            } else if (status == HCNetSDK.NET_SDK_NEXT_STATUS__FINISH) {
+                System.out.println("查询完成,共 " + count + " 条记录。");
+                break;
+            } else if (status == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FAILED) {
+                System.out.println("获取事件失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());
+                break;
+            } else if (status == HCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS) {
+                struEvent.read();
+
+                String eventCard = new String(struEvent.struAcsEventInfo.byCardNo).trim();
+                String eventEmpNo = new String(struEvent.struAcsEventInfo.byEmployeeNo).trim();
+
+                System.out.printf("事件%d: 工号=%s, 卡号=%s, 主类型=%d, 次类型=%d, 时间=%04d-%02d-%02d %02d:%02d:%02d%n",
+                        count + 1,
+                        eventEmpNo, eventCard,
+                        struEvent.dwMajor, struEvent.dwMinor,
+                        struEvent.struTime.dwYear, struEvent.struTime.dwMonth, struEvent.struTime.dwDay,
+                        struEvent.struTime.dwHour, struEvent.struTime.dwMinute, struEvent.struTime.dwSecond);
+
+                count++;
+            }
+        }
+
+        // 关闭查询
+        if (!hCNetSDK.NET_DVR_StopRemoteConfig(handle)) {
+            System.out.println("关闭连接失败:" + hCNetSDK.NET_DVR_GetLastError());
+        } else {
+            System.out.println("NET_DVR_StopRemoteConfig 成功关闭连接。");
+        }
+    }
+
+
+
+
+
+
+
+
+
 }

+ 127 - 28
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/FaceManage.java

@@ -1,17 +1,18 @@
 package com.supervision.web.ConnectSDK.peopleDoor.Acs;
 
 
-import com.supervision.web.ConnectSDK.peopleDoor.Commom.ConfigFileUtil;
+import com.sun.jna.Memory;
+import com.supervision.web.ConnectSDK.peopleDoor.CommonMethod.ConfigFileUtil;
 import com.supervision.web.ConnectSDK.peopleDoor.NetSDKDemo.HCNetSDK;
 import com.sun.jna.Pointer;
 import com.sun.jna.ptr.IntByReference;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.json.XML;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
 import java.io.*;
@@ -280,10 +281,9 @@ public class FaceManage {
             struAddFaceDataCfg.read();
 
             JSONObject jsonObject = new JSONObject();
-            jsonObject.put("faceURL",
-                    "http://10.17.34.106:6011/pic?7DD9D70207A9D7F576F99AC197B2D6CAface.jpg"); //人脸图片URL,平台自己实现,需要保证设备可以正常访问
-            jsonObject.put("faceLibType", "blackFD");
-            jsonObject.put("FDID", "1");
+            jsonObject.put("faceURL", "http://10.17.34.106:6011/pic?7DD9D70207A9D7F576F99AC197B2D6CAface.jpg"); //人脸图片URL,平台自己实现,需要保证设备可以正常访问
+            jsonObject.put("faceLibType", "blackFD"); /* req, enum, 人脸库类型, subType:string, [blackFD#名单库,staticFD#静态库], desc:人脸库类型: blackFD-名单库, staticFD-静态库, string类型, 最大长度为32*/
+            jsonObject.put("FDID", "1"); /* req, string, 人脸库ID, range:[,], desc:人脸库ID, string类型, 最大长度为63字节,多个人脸库用逗号隔开;*/
             jsonObject.put("FPID", employeeNo); //人脸下发关联的工号
 
             String strJsonData = jsonObject.toString();
@@ -378,14 +378,15 @@ public class FaceManage {
                 null, // cbStateCallback[in] 状态回调函数
                 null // pUserData[in] 用户数据
         );
+        // -1表示失败,其他值作为NET_DVR_SendWithRecvRemoteConfig等接口的句柄。接口返回失败请调用NET_DVR_GetLastError获取错误码,通过错误码判断出错原因。
         if (lHandler < 0) {
             int errorCode = hCNetSDK.NET_DVR_GetLastError();
             logger.info("调用NET_DVR_StartRemoteConfig建立长连接,获取句柄失败,错误码:" + errorCode);
             return;
-        } else {
-            logger.info("调用NET_DVR_StartRemoteConfig建立长连接,获取句柄成功!");
         }
 
+        logger.info("调用NET_DVR_StartRemoteConfig建立长连接,获取句柄成功!");
+
         // ================== 人脸信息查询参数构建 ==================
         // 校验必传字段
         validateRequiredFields(searchCondition, SEARCH_FACE_INFO_REQUIRED_FIELDS);
@@ -749,7 +750,7 @@ public class FaceManage {
         // 添加人脸信息
         HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(1024); // 数组
         String strInBuffer = "POST /ISAPI/Intelligent/FDLib/FaceDataRecord?format=json"; // 查询人脸信息
-        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
+        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length()); // 字符串拷贝到数组中
         ptrByteArray.write();
 
         int lHandler = hCNetSDK.NET_DVR_StartRemoteConfig(
@@ -948,15 +949,129 @@ public class FaceManage {
         stopRemoteConfig(lHandler);
     }
 
+    /**
+     * 修改单条人脸信息(新加的)
+     * @param userID 登录设备的句柄
+     * @param condition 参数:包括 faceLibType, FDID, FPID, imagePath
+     */
+    public void modifyFaceInfo(int userID, Map<String, Object> condition) {
+        // 构造URL命令(PUT)
+        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(1024);
+        String strInBuffer = "PUT /ISAPI/Intelligent/FDLib/FDSearch?format=json&FDID=1&FPID=&faceLibType=blackFD";
+        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());
+        ptrByteArray.write();
+
+        // 构造输入 JSON(人脸信息)
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("faceLibType", condition.get("faceLibType")); // 一般是 "blackFD" 或 "whiteFD"
+        jsonObject.put("FDID", condition.get("FDID")); // 人脸库ID
+        jsonObject.put("FPID", condition.get("FPID")); // 人脸记录ID
+
+        String strJson = jsonObject.toString();
+        HCNetSDK.BYTE_ARRAY ptrInputJson = new HCNetSDK.BYTE_ARRAY(strJson.length());
+        System.arraycopy(strJson.getBytes(), 0, ptrInputJson.byValue, 0, strJson.length());
+        ptrInputJson.write();
+
+        // 读取人脸图片文件
+        String imagePath = (String) condition.get("imagePath");
+        File imageFile = new File(imagePath);
+        int fileLength = (int) imageFile.length();
+        HCNetSDK.BYTE_ARRAY ptrInputData = new HCNetSDK.BYTE_ARRAY(fileLength);
+        try (FileInputStream fis = new FileInputStream(imageFile)) {
+            fis.read(ptrInputData.byValue);
+        } catch (IOException e) {
+            e.printStackTrace();
+            return;
+        }
+        ptrInputData.write();
+
+        // 调用 SDK 接口发送请求
+        HCNetSDK.NET_DVR_XML_CONFIG_INPUT input = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
+        input.lpRequestUrl = ptrByteArray.getPointer();
+        input.dwRequestUrlLen = strInBuffer.length();
+        input.lpInBuffer = ptrInputJson.getPointer();
+        input.dwInBufferSize = strJson.length();
+        input.lpInBuffer = ptrInputData.getPointer();
+        input.dwInBufferSize = fileLength;
+        input.write();
+
+        HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT output = new HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT();
+        output.dwOutBufferSize = 1024 * 10;
+        output.lpOutBuffer = new Memory(output.dwOutBufferSize);
+        output.write();
+
+        boolean result = hCNetSDK.NET_DVR_STDXMLConfig(userID, input, output);
+        if (!result) {
+            System.err.println("修改人脸失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());
+        } else {
+            output.read();
+            String jsonResponse = output.lpOutBuffer.getString(0);
+            System.out.println("修改人脸成功,返回数据:" + jsonResponse);
+        }
+    }
+
+    /**
+     * 获取设备上所有人脸的数量(新加的)
+     *
+     * @param userID 用户登录句柄
+     * @return 人脸数量
+     */
+    public int getFaceCount(int userID) {
+        // 设置请求 URL
+        String url = "GET /ISAPI/Intelligent/FDLib/Count?format=json";
+        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(1024);
+        System.arraycopy(url.getBytes(), 0, ptrByteArray.byValue, 0, url.length());
+        ptrByteArray.write();
+
+        // 构造输入参数结构体
+        HCNetSDK.NET_DVR_XML_CONFIG_INPUT inputParam = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
+        inputParam.dwSize = inputParam.size();
+        inputParam.lpRequestUrl = ptrByteArray.getPointer();  // 设置请求的 URL
+        inputParam.dwRequestUrlLen = url.length();
+
+        // 构造输出参数结构体
+        HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT outputParam = new HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT();
+        outputParam.dwSize = outputParam.size();
+        outputParam.lpOutBuffer = new Memory(1024 * 1024); // 分配 1MB 内存
+        outputParam.dwOutBufferSize = 1024 * 1024;
+        outputParam.lpStatusBuffer = new Memory(1024);
+        outputParam.dwStatusSize = 1024;
+
+        // 调用海康 SDK 接口
+        boolean result = hCNetSDK.NET_DVR_STDXMLConfig(userID, inputParam, outputParam);
+        if (!result) {
+            int errorCode = hCNetSDK.NET_DVR_GetLastError();
+            logger.error("获取人脸数量失败,错误码:" + errorCode);
+            return -1;
+        }
+
+        // 读取输出数据(ISAPI 返回 XML)
+        byte[] responseData = outputParam.lpOutBuffer.getByteArray(0, (int) outputParam.dwOutBufferSize);
+        String responseXml = new String(responseData, java.nio.charset.StandardCharsets.UTF_8).trim();
+
+        // 转为 JSON 并解析数量
+        try {
+            JSONObject responseJson = XML.toJSONObject(responseXml);
+            JSONObject fdCountObj = responseJson.getJSONObject("FDLibCount");
+
+            int faceCount = fdCountObj.getInt("faceNumber");
+            logger.info("获取人脸数量成功,人脸总数:" + faceCount);
+            return faceCount;
+        } catch (Exception e) {
+            logger.error("解析人脸数量失败,返回数据:" + responseXml, e);
+            return -1;
+        }
+    }
+
     /**
      * 删除人脸库中的人脸数据
      * 人脸删除,支持批量删除,json中添加多个工号
      * 通过 ISAPI协议命令透传 删除人脸参数
      *
      * @param userID
-     * @param searchCondition
+     * @param condition
      */
-    public void deleteFaceInfo(int userID, Map<String, Object> searchCondition) {
+    public void deleteFaceInfo(int userID, Map<String, Object> condition) {
 
         // 删除人脸库中的人脸数据
         String deleteFaceUrl = "PUT /ISAPI/Intelligent/FDLib/FDSearch/Delete?format=json&FDID=1&faceLibType=blackFD";
@@ -974,23 +1089,7 @@ public class FaceManage {
         // opt, array, 人脸记录ID列表, subType:object, range:[,]
 
         // 使用模板生成 JSON
-        String deleteFaceJson =
-                ConfigFileUtil.getReqBodyFromTemplate("conf/acs/Face/DeleteFaceInfoInputParam.json", parameter);
-//        {
-//            "FPID": [
-//            /*opt, array, 人脸记录ID列表, subType:object, range:[,]*/
-//                {
-//                    "value":"test",
-//                    /*req, string, 人脸记录ID, range:[0,63]*/
-//                    "rowKey":"test"
-//                    /*opt, string, 人脸记录数据库主键, range:[0,64], desc:可选,人脸记录数据库主键,根据rowKey进行查询,能提高查找效率,string,64字节 在轻量级产品中是必填字段*/
-//                }
-//            ],
-//            "operateType":"byTerminal",
-//            /*opt, enum, 操作类型, subType:string, [byTerminal#按终端操作]*/
-//            "terminalNoList": [1]
-//            /*opt, array, 终端ID列表, subType:int, range:[,], desc:可选,array,type为byTerminal,byTerminalOrg时必填,终端ID列表(目前仅支持单个终端)*/
-//        }
+        String deleteFaceJson = ConfigFileUtil.getReqBodyFromTemplate("conf/acs/Face/DeleteFaceInfoInputParam.json", parameter);
         logger.info("删除人脸图片参数:", deleteFaceJson);
         String result = transIsapi.put_isapi(userID, deleteFaceUrl, deleteFaceJson);
         logger.info("删除人员结果:", result);

+ 1 - 2
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/FingerManage.java

@@ -1,7 +1,7 @@
 package com.supervision.web.ConnectSDK.peopleDoor.Acs;
 
 
-import com.supervision.web.ConnectSDK.peopleDoor.Commom.ConfigFileUtil;
+import com.supervision.web.ConnectSDK.peopleDoor.CommonMethod.ConfigFileUtil;
 import com.supervision.web.ConnectSDK.peopleDoor.NetSDKDemo.HCNetSDK;
 import com.sun.jna.Pointer;
 import com.sun.jna.ptr.IntByReference;
@@ -9,7 +9,6 @@ import org.json.JSONException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
 import java.io.*;

+ 193 - 6
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Acs/UserManage.java

@@ -1,7 +1,8 @@
 package com.supervision.web.ConnectSDK.peopleDoor.Acs;
 
 
-import com.supervision.web.ConnectSDK.peopleDoor.Commom.ConfigFileUtil;
+import com.sun.jna.Memory;
+import com.supervision.web.ConnectSDK.peopleDoor.CommonMethod.ConfigFileUtil;
 import com.supervision.web.ConnectSDK.peopleDoor.NetSDKDemo.HCNetSDK;
 import com.sun.jna.Pointer;
 import com.sun.jna.ptr.IntByReference;
@@ -10,11 +11,10 @@ import org.json.JSONException;
 import org.json.JSONObject;
 import org.json.XML;
 import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
 import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -28,10 +28,119 @@ public class UserManage {
 
     private HCNetSDK hCNetSDK;
 
-    public void deleteUserInfo(int userID) {
+    // 删除用户信息
+
+    /**
+     * 删除人员信息(含进度监控)
+     *
+     *
+     * @param userID     设备登录句柄(通过 {@code NET_DVR_Login_V40} 获取)
+     * @param employeeNo 员工编号(要删除的人员编号)
+     * @throws JSONException                 构造 JSON 请求时可能抛出
+     * @throws UnsupportedEncodingException  编码转换异常
+     * @throws InterruptedException          线程等待过程中被中断
+     */
+    public void deleteUserInfo(int userID, String employeeNo) throws InterruptedException {
+        // 1. Step1: 构造删除请求 JSON
+        JSONObject delJson = new JSONObject();
+        JSONObject info = new JSONObject();
+        info.put("EmployeeNoList", new JSONArray().put(employeeNo));
+        delJson.put("UserInfoDetailDelCond", info);
+
+        String delUrl = "PUT /ISAPI/AccessControl/UserInfoDetail/Delete?format=json";
+
+        // 2. Step2: 调用 NET_DVR_STDXMLConfig 执行删除请求
+        if (!sendDeleteRequest(userID, delUrl, delJson.toString())) {
+            logger.error("删除请求失败");
+            return;
+        }
+
+        // 3. Step3: 建立长连接监控删除进度
+        String processUrl = "GET /ISAPI/AccessControl/UserInfoDetail/DeleteProcess?format=json";
+        monitorDeleteProgress(userID, processUrl);
+
+        logger.info("人员 {} 删除流程完成", employeeNo);
+    }
+
+    /**
+     * 发送删除请求(PUT JSON)
+     */
+    private boolean sendDeleteRequest(int userID, String url, String jsonBody) {
+        HCNetSDK.NET_DVR_XML_CONFIG_INPUT input = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
+        HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT output = new HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT();
+
+        byte[] byUrl = url.getBytes(StandardCharsets.UTF_8);
+        input.dwSize = input.size();
+        input.lpRequestUrl = new Memory(byUrl.length);
+        input.dwRequestUrlLen = byUrl.length;
+        input.lpRequestUrl.write(0, byUrl, 0, byUrl.length);
+
+        byte[] byInBuf = jsonBody.getBytes(StandardCharsets.UTF_8);
+        input.lpInBuffer = new Memory(byInBuf.length);
+        input.dwInBufferSize = byInBuf.length;
+        input.lpInBuffer.write(0, byInBuf, 0, byInBuf.length);
+
+        output.dwSize = output.size();
+        output.lpOutBuffer = new Memory(1024);
+        output.dwOutBufferSize = 1024;
+        output.lpStatusBuffer = new Memory(1024);
+        output.dwStatusSize = 1024;
+
+        boolean result = hCNetSDK.NET_DVR_STDXMLConfig(userID, input, output);
+
+        if (!result) {
+            logger.error("NET_DVR_STDXMLConfig 调用失败,错误码:{}", hCNetSDK.NET_DVR_GetLastError());
+            return false;
+        }
+
+        byte[] outBytes = new byte[1024];
+        output.lpOutBuffer.read(0, outBytes, 0, 1024);
+        String response = new String(outBytes, StandardCharsets.UTF_8).trim();
+        logger.info("删除请求返回:{}", response);
+        return true;
     }
 
-    public void searchUserInfo(int userID) {
+    /**
+     * 查询删除进度
+     */
+    private void monitorDeleteProgress(int userID, String url) throws InterruptedException {
+        HCNetSDK.BYTE_ARRAY urlByte = new HCNetSDK.BYTE_ARRAY(256);
+        byte[] byUrl = url.getBytes(StandardCharsets.UTF_8);
+        System.arraycopy(byUrl, 0, urlByte.byValue, 0, byUrl.length);
+        urlByte.write();
+
+        int lHandle = hCNetSDK.NET_DVR_StartRemoteConfig(
+                userID, HCNetSDK.NET_DVR_JSON_CONFIG, urlByte.getPointer(), byUrl.length, null, null);
+        if (lHandle < 0) {
+            logger.error("启动删除进度长连接失败,错误码:{}", hCNetSDK.NET_DVR_GetLastError());
+            return;
+        }
+
+        HCNetSDK.BYTE_ARRAY outBuff = new HCNetSDK.BYTE_ARRAY(1024);
+
+        logger.info("开始查询删除进度...");
+        while (true) {
+            int state = hCNetSDK.NET_DVR_GetNextRemoteConfig(lHandle, outBuff.getPointer(), 1024);
+            if (state == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {
+                outBuff.read();
+                String json = new String(outBuff.byValue).trim();
+                logger.info("删除进度返回:{}", json);
+                if (json.contains("success")) {
+                    logger.info("人员删除完成!");
+                    break;
+                }
+            } else if (state == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED ||
+                    state == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
+                logger.error("删除进度查询失败,错误码:{}", hCNetSDK.NET_DVR_GetLastError());
+                break;
+            } else if (state == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
+                logger.info("删除进度查询结束。");
+                break;
+            }
+            Thread.sleep(1000);
+        }
+
+        hCNetSDK.NET_DVR_StopRemoteConfig(lHandle);
     }
 
     /**
@@ -225,6 +334,84 @@ public class UserManage {
         return queryCondition.toString();
     }
 
+    /**
+     * 按工号查询单个人员信息
+     *
+     * @param userID 用户登录句柄
+     * @param employeeNo 员工工号
+     */
+    public String getUserInfoByEmployeeNo(int userID, String employeeNo) {
+        String url = "POST /ISAPI/AccessControl/UserInfo/Search?format=json";
+        HCNetSDK.BYTE_ARRAY ptrUrl = new HCNetSDK.BYTE_ARRAY(1024);
+        System.arraycopy(url.getBytes(), 0, ptrUrl.byValue, 0, url.length());
+        ptrUrl.write();
+        String result = null;
+
+        // 构造查询条件 JSON
+        JSONObject queryCond = new JSONObject();
+        JSONObject userInfoSearchCond = new JSONObject();
+        JSONArray employeeList = new JSONArray();
+
+        userInfoSearchCond.put("searchID", String.valueOf(System.currentTimeMillis()));
+        userInfoSearchCond.put("searchResultPosition", 0);
+        userInfoSearchCond.put("maxResults", 1);
+        employeeList.put(new JSONObject().put("employeeNo", employeeNo));
+        userInfoSearchCond.put("EmployeeNoList", employeeList);
+        queryCond.put("UserInfoSearchCond", userInfoSearchCond);
+
+        HCNetSDK.BYTE_ARRAY ptrInput = new HCNetSDK.BYTE_ARRAY(1024);
+        System.arraycopy(queryCond.toString().getBytes(), 0, ptrInput.byValue, 0, queryCond.toString().length());
+        ptrInput.write();
+
+        HCNetSDK.BYTE_ARRAY ptrOut = new HCNetSDK.BYTE_ARRAY(10240);
+        IntByReference pInt = new IntByReference(0);
+
+        // 开始查询
+        int lHandler = hCNetSDK.NET_DVR_StartRemoteConfig(userID, HCNetSDK.NET_DVR_JSON_CONFIG, ptrUrl.getPointer(), url.length(), null, null);
+        if (lHandler == -1) {
+            logger.error("!!!!!!!!!!!!!!!!!!建立查询单个人员长连接失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());
+            return null;
+        }
+
+        int dwState;
+        while (true) {
+            dwState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(
+                    lHandler,
+                    ptrInput.getPointer(),
+                    queryCond.toString().length(),
+                    ptrOut.getPointer(),
+                    10240,
+                    pInt
+            );
+
+            if (dwState == -1) {
+                logger.error("调用失败:" + hCNetSDK.NET_DVR_GetLastError());
+                break;
+            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEED_WAIT) {
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+                continue;
+            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {
+                ptrOut.read();
+                result = new String(ptrOut.byValue).trim();
+                logger.info("查询单个人员成功:" + result);
+                break;
+            } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
+                logger.info("查询完成");
+                break;
+            } else {
+                logger.warn("状态码:" + dwState);
+                break;
+            }
+        }
+
+        hCNetSDK.NET_DVR_StopRemoteConfig(lHandler);
+
+        return  result;
+    }
 
     /**
      * 新增人员
@@ -292,7 +479,7 @@ public class UserManage {
         parameter.put("doorNo", 1); // 门编号
 
         // 使用模板文件生成 JSON 请求报文
-        String input = ConfigFileUtil.getReqBodyFromTemplate("conf/acs/AddUserInfoParam.json", parameter);
+        String input = ConfigFileUtil.getReqBodyFromTemplate("conf/acs/AddUserInfoInputParam.json", parameter);
         logger.info("下发人员参数:" + input);
 
         byte[] byInBuffer = input.getBytes("utf-8");

+ 2 - 1
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Commom/CommonMethod.java → supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/CommonMethod/CommonMethod.java

@@ -1,4 +1,5 @@
-package com.supervision.web.ConnectSDK.peopleDoor.Commom;
+package com.supervision.web.ConnectSDK.peopleDoor.CommonMethod;
+
 
 import com.sun.jna.Pointer;
 import org.springframework.stereotype.Component;

+ 23 - 0
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/CommonMethod/CommonUtil.java

@@ -0,0 +1,23 @@
+package com.supervision.web.ConnectSDK.peopleDoor.CommonMethod;
+
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class CommonUtil {
+
+    // SDK时间解析
+    public static String parseTime(int time)
+    {
+        int year=(time>>26)+2000;
+        int month=(time>>22)&15;
+        int day=(time>>17)&31;
+        int hour=(time>>12)&31;
+        int min=(time>>6)&63;
+        int second=(time>>0)&63;
+        String sTime=year+"-"+month+"-"+day+"-"+hour+":"+min+":"+second;
+//        System.out.println(sTime);
+        return sTime;
+    }
+
+}

+ 1 - 6
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Commom/ConfigFileUtil.java → supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/CommonMethod/ConfigFileUtil.java

@@ -1,4 +1,4 @@
-package com.supervision.web.ConnectSDK.peopleDoor.Commom;
+package com.supervision.web.ConnectSDK.peopleDoor.CommonMethod;
 
 
 import org.apache.commons.text.StrSubstitutor;
@@ -10,11 +10,6 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Map;
 
-/**
- * @author zhengxiaohui
- * @date 2023/8/15 19:07
- * @desc 配置文件处理工具
- */
 @Component
 public class ConfigFileUtil {
 

+ 1 - 1
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/Commom/osSelect.java → supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/CommonMethod/osSelect.java

@@ -1,4 +1,4 @@
-package com.supervision.web.ConnectSDK.peopleDoor.Commom;
+package com.supervision.web.ConnectSDK.peopleDoor.CommonMethod;
 
 
 import org.springframework.stereotype.Component;

+ 3 - 2
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/NetSDKDemo/HCNetSDK.java

@@ -15,7 +15,8 @@ import java.util.List;
 public interface HCNetSDK extends Library {
 
     /*** 宏定义 ***/
-    //常量
+    // 常量
+    HCNetSDK INSTANCE = Native.load("hcnetsdk", HCNetSDK.class);
 
     public static final int MAX_NAMELEN = 16;    //DVR本地登陆名
     public static final int MAX_RIGHT = 32;    //设备支持的权限(1-12表示本地权限,13-32表示远程权限)
@@ -7116,7 +7117,7 @@ DVR实现巡航数据结构
 
     //人体特征识别结果结构体
     public static class NET_VCA_HUMAN_FEATURE extends XStructure {
-        public byte byRes3;    
+        public byte byRes3;
         public byte bySex;         //性别, 0-表示“未知”(算法不支持),1 – 男 , 2 – 女, 0xff-算法支持,但是没有识别出来
         public byte byEyeGlass;    //是否戴眼镜 0-表示“未知”(算法不支持),1 – 不戴, 2 – 戴,0xff-算法支持,但是没有识别出来
         //抓拍图片人脸年龄的使用方式,如byAge为15,byAgeDeviation为1,表示,实际人脸图片年龄的为14-16之间

+ 305 - 10
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/PeopleDoorDeviceManager.java

@@ -1,11 +1,8 @@
 package com.supervision.web.ConnectSDK.peopleDoor;
 
 
-import com.supervision.web.ConnectSDK.peopleDoor.Acs.ACSManage;
-import com.supervision.web.ConnectSDK.peopleDoor.Acs.CardManage;
-import com.supervision.web.ConnectSDK.peopleDoor.Acs.EventSearch;
-import com.supervision.web.ConnectSDK.peopleDoor.Acs.FaceManage;
-import com.supervision.web.ConnectSDK.peopleDoor.Acs.UserManage;
+import com.supervision.web.ConnectSDK.peopleDoor.alarm.PeopleDoorFMSGCallBack_V31;
+import com.supervision.web.ConnectSDK.peopleDoor.Acs.*;
 import com.supervision.web.ConnectSDK.util.DeviceSession;
 import com.supervision.web.ConnectSDK.util.HikSDKManager;
 import com.supervision.web.ConnectSDK.util.SdkType;
@@ -32,6 +29,12 @@ public class PeopleDoorDeviceManager {
 
     private HCNetSDK hCNetSDK;
 
+    /** 报警布防句柄(每个设备一个) */
+    private int lAlarmHandle = -1;
+
+    /** 报警布防回调 */
+    private PeopleDoorFMSGCallBack_V31 fMSFCallBack_V31;
+
     @Autowired
     private UserManage userManage;
 
@@ -47,6 +50,12 @@ public class PeopleDoorDeviceManager {
     @Autowired
     private EventSearch eventSearch;
 
+    @Autowired
+    private FingerManage fingerManage;
+
+    @Autowired
+    private MutilCard mutilCard;
+
     /**
      * key: 设备IP, value: DeviceSession
      */
@@ -64,16 +73,174 @@ public class PeopleDoorDeviceManager {
 //            hCNetSDK = (HCNetSDK) hikSDKManager.getSDK(SdkType.PEOPLE_DOOR);
             hCNetSDK = hikSDKManager.getPeopleDoorSDK(); // 类型安全获取
 
-            if (hCNetSDK != null) {
-                logger.info("PeopleDoor HCNetSDK 已初始化");
-            } else {
-                logger.error("PeopleDoor HCNetSDK 初始化失败");
+            if (hCNetSDK == null) {
+                logger.error("❌ PeopleDoor HCNetSDK 初始化失败");
+                return;
+            }
+            logger.info("✅ PeopleDoor HCNetSDK 初始化成功");
+
+            // 设置连接时间与重连策略
+            this.setupConnectionConfig();
+
+            // 设置报警回调函数(全局仅一次)
+            this.setAlarmCallback();
+
+            // 设置本地SDK配置项(JSON与图片分离)
+            this.setupLocalJsonConfig();
+
+            // 登录车牌识别设备
+            DeviceSession session = loginDevice("10.9.137.17", (short) 8000, "admin", "hik12345");
+            if (session == null) {
+                logger.error("❌ 设备登录失败,初始化中断");
+                return;
             }
+
+            logger.info("✅ 门岗初始化完成, userID={}", session.getUserID());
+
+            // 可选:自动布防(如设备较少可直接启用)
+            this.setupAlarm(session.getUserID());
         } catch (Exception e) {
             logger.error("PeopleDoorDeviceManager 初始化异常: {}", e.getMessage(), e);
         }
     }
 
+    /**
+     * 设置连接时间与重连策略
+     */
+    private void setupConnectionConfig() {
+        hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
+        hCNetSDK.NET_DVR_SetReconnect(10000, true);
+    }
+
+    /**
+     * 设置报警回调函数(全局只需设置一次)
+     * ------------------------------------------------
+     * SDK 初始化后立即调用。
+     * 所有设备报警数据都会通过该回调统一上报。
+     */
+    private void setAlarmCallback() {
+        /*注:多台设备对接时也只需要调用一次设置一个回调函数,不支持不同设备的事件在不同的回调函数里面返回*/
+        // 先调用NET_DVR_SetDVRMessageCallBack_V50设置报警回调函数(V31、V30接口也支持,新接口兼容老接口),
+        // 在SDK初始化之后即可以调用,多台设备对接时也只需要调用一次设置一个回调函数,回调函数里面接收数据之后可以通过报警设备信息(NET_DVR_ALARMER)中lUserID等参数判断区分设备。
+        if (fMSFCallBack_V31 != null) return; // 防止重复注册
+
+        fMSFCallBack_V31 = new PeopleDoorFMSGCallBack_V31();
+        boolean ok = hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(
+                fMSFCallBack_V31,
+                null
+        );
+
+        if (!ok) {
+            logger.error("❌ 设置报警回调函数失败, 错误码={}", hCNetSDK.NET_DVR_GetLastError());
+        } else {
+            logger.info("✅ 报警回调函数设置成功");
+        }
+    }
+
+    /**
+     * 设置 SDK 本地配置
+     * ------------------------------------------------
+     * byAlarmJsonPictureSeparate = 1 表示 JSON 和图片数据分离上传
+     * 这样回调类型为 COMM_ISAPI_ALARM(0x6009),
+     * 报警结构为 NET_DVR_ALARM_ISAPI_INFO,更易解析。
+     */
+    private void setupLocalJsonConfig() {
+        /** 设备上传的报警信息是COMM_VCA_ALARM(0x4993)类型,
+         在SDK初始化之后增加调用NET_DVR_SetSDKLocalCfg(enumType为NET_DVR_LOCAL_CFG_TYPE_GENERAL)设置通用参数NET_DVR_LOCAL_GENERAL_CFG的byAlarmJsonPictureSeparate为1,
+         将Json数据和图片数据分离上传,这样设置之后,报警布防回调函数里面接收到的报警信息类型为COMM_ISAPI_ALARM(0x6009),
+         报警信息结构体为NET_DVR_ALARM_ISAPI_INFO(与设备无关,SDK封装的数据结构),更便于解析。*/
+
+        com.supervision.web.ConnectSDK.carCamera.NetSDKDemo.HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG cfg = new com.supervision.web.ConnectSDK.carCamera.NetSDKDemo.HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG();
+        cfg.byAlarmJsonPictureSeparate = 1;   //设置JSON透传报警数据和图片分离
+        cfg.write();
+        hCNetSDK.NET_DVR_SetSDKLocalCfg(17, cfg.getPointer()); // 17 通用参数配置
+    }
+
+    /**
+     * 启用布防(报警上传)
+     * ------------------------------------------------
+     * 若设备已布防则先关闭旧通道再重新布防。
+     */
+    private void setupAlarm(int userID) {
+        // 若之前已有布防,先关闭
+        if (this.lAlarmHandle >= 0) {
+            hCNetSDK.NET_DVR_CloseAlarmChan_V30(this.lAlarmHandle);
+            this.lAlarmHandle = -1;
+        }
+
+        // 报警布防参数结构体。
+        HCNetSDK.NET_DVR_SETUPALARM_PARAM lpSetupParam = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
+        lpSetupParam.dwSize = lpSetupParam.size(); // 结构体大小
+        lpSetupParam.byLevel = 1;                  // 布防优先级:0- 一等级(高),1- 二等级(中)
+        lpSetupParam.byAlarmInfoType = 1;          // 智能交通报警信息上传类型:0- 老报警信息(NET_DVR_PLATE_RESULT),1- 新报警信息(NET_ITS_PLATE_RESULT)
+        lpSetupParam.byRetAlarmTypeV40 = 1;        // 0- 移动侦测、视频丢失、遮挡、IO信号量等报警信息以普通方式上传(报警类型:COMM_ALARM_V30,报警信息结构体:NET_DVR_ALARMINFO_V30),1- 报警信息以数据可变长方式上传(报警类型:COMM_ALARM_V40,报警信息结构体:NET_DVR_ALARMINFO_V40,设备若不支持则仍以普通方式上传)
+        lpSetupParam.byRetDevInfoVersion = 1;      // CVR上传报警信息类型(仅对接CVR时有效):// 0- COMM_ALARM_DEVICE(对应报警信息结构体:NET_DVR_ALARMINFO_DEV),1- COMM_ALARM_DEVICE_V40(对应报警信息结构体:NET_DVR_ALARMINFO_DEV_V40)
+        lpSetupParam.byDeployType = 0;             // 布防类型:0-客户端布防,1-实时布防
+        lpSetupParam.write();                      // 写入内存
+        // alarmParam.byLevel 布防优先级:0- 一等级(高),1- 二等级(中),2- 三等级(低)
+        // alarmParam.byAlarmInfoType 智能交通报警信息上传类型:0- 老报警信息(NET_DVR_PLATE_RESULT),1- 新报警信息(NET_ITS_PLATE_RESULT)
+        // alarmParam.byRetAlarmTypeV40  0- 移动侦测、视频丢失、遮挡、IO信号量等报警信息以普通方式上传(报警类型:COMM_ALARM_V30,报警信息结构体:NET_DVR_ALARMINFO_V30),1- 报警信息以数据可变长方式上传(报警类型:COMM_ALARM_V40,报警信息结构体:NET_DVR_ALARMINFO_V40,设备若不支持则仍以普通方式上传)
+        // alarmParam.byRetDevInfoVersion  CVR上传报警信息类型(仅对接CVR时有效):0- COMM_ALARM_DEVICE(对应报警信息结构体:NET_DVR_ALARMINFO_DEV),1- COMM_ALARM_DEVICE_V40(对应报警信息结构体:NET_DVR_ALARMINFO_DEV_V40)
+        // alarmParam.byRetVQDAlarmType  VQD报警上传类型(仅对接VQD诊断功能的设备有效):0- COMM_ALARM_VQD(对应报警信息结构体:NET_DVR_VQD_DIAGNOSE_INFO),1- COMM_ALARM_VQD_EX(对应报警信息结构体:NET_DVR_VQD_ALARM,包含前端设备信息和抓拍图片)
+        // alarmParam.byFaceAlarmDetection  人脸报警信息类型:1- 人脸侦测报警(报警类型:COMM_ALARM_FACE_DETECTION,NET_DVR_FACE_DETECTION),0- 人脸抓拍报警(报警类型:COMM_UPLOAD_FACESNAP_RESULT,NET_VCA_FACESNAP_RESULT)
+        // alarmParam.bySupport  按位表示,每一位取值表示不同的能力
+        // bit0- 表示二级布防是否上传图片,值:0-上传,1-不上传
+        // Bit1- 表示是否启用断网重传数据确认机制,值:0-不开启,1-开启
+        // alarmParam.byBrokenNetHttp  断网重传类型(设备目前只支持一个断网重传布防连接),按位表示,值:0- 不重传,1- 重传
+        // bit0- 车牌检测(IPC)
+        // bit1- 客流统计(IPC)
+        // bit2- 热度图统计(IPC)
+        // bit3- 人脸抓拍(IPC)
+        // bit4- 人脸对比(IPC)
+        // bit5- JSON报警透传(IPC)
+        // 例如:byBrokenNetHttp&0x1==0 表示车牌检测结果不重传
+        // alarmParam.wTaskNo  任务处理号
+        // alarmParam.byRes1  保留,置为0
+        // alarmParam.byAlarmTypeURL  报警图片数据类型,按位表示:
+        // bit0- 人脸抓拍(报警类型为COMM_UPLOAD_FACESNAP_RESULT)中图片数据上传类型:0- 二进制传输,1- URL传输
+        // bit1- EVENT_JSON(报警类型为COMM_VCA_ALARM)中图片数据上传类型:0- 二进制传输,1- URL传输
+        // bit2- 人脸比对(报警类型为COMM_SNAP_MATCH_ALARM)中图片数据上传类型:0- 二进制传输,1- URL传输
+        // 如果设备同时支持URL和二进制传输方式,可以布防的时候通过该参数指定上传的数据格式(二进制或者URL),选择URL传输方式时需要设备配置和启用云存储,否则仍默认以二进制数据格式传输。如果设备只支持URL方式,该参数赋值无效。
+        // alarmParam.byCustomCtrl  按位表示,bit0表示是否上传副驾驶人脸子图: 0- 不上传,1- 上传
+
+        // 启用布防
+        // 建立报警上传通道,获取报警等信息。
+        this.lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(
+                userID, // lUserID [in] NET_DVR_Login或者NET_DVR_Login_V30的返回值
+                lpSetupParam // lpSetupParam [in] 报警布防参数
+        );
+        // -1表示失败,其他值作为NET_DVR_CloseAlarmChan_V30函数的句柄参数。接口返回失败请调用NET_DVR_GetLastError获取错误码,通过错误码判断出错原因。
+        if (this.lAlarmHandle < 0) {
+            int err = hCNetSDK.NET_DVR_GetLastError();
+            logger.error("❌ 布防失败, 错误码={}", err);
+            return;
+        }
+
+        logger.info("✅ 布防成功,句柄={},开始监测车辆事件", this.lAlarmHandle);
+
+
+
+//        logger.info("布防成功,开始抓拍...");
+//
+//        // 手动抓拍(使用三参数接口)
+//        HCNetSDK.NET_DVR_MANUALSNAP snapCfg = new HCNetSDK.NET_DVR_MANUALSNAP();
+////                snapCfg.dwSize = snapCfg.size();
+////                snapCfg.bySnapTimes = 1;
+////                snapCfg.byTriggerMode = 1;
+////                snapCfg.byJointSnap = 0;
+//
+//        HCNetSDK.NET_DVR_PLATE_RESULT plateResult = new HCNetSDK.NET_DVR_PLATE_RESULT();
+//
+//        boolean triggered = hCNetSDK.NET_DVR_ManualSnap(userID, snapCfg, plateResult);
+//
+//        if (triggered) {
+//            license = new String(plateResult.struPlateInfo.sLicense, Charset.forName("GBK")).trim();
+//            logger.info("识别到车牌号:" + license);
+//        } else {
+//            logger.error("手动抓拍失败,错误码: " + hCNetSDK.NET_DVR_GetLastError());
+//        }
+    }
+
     /**
      * 登录设备,设备只登录一次,返回共享 DeviceSession
      */
@@ -221,7 +388,7 @@ public class PeopleDoorDeviceManager {
             case "23": {
                 logger.info("[Module]删除人员代码");
                 // 支持按人员和全部删除
-                userManage.deleteUserInfo(userID);
+                userManage.deleteUserInfo(userID, "12345");
                 break;
             }
             case "24": {
@@ -230,6 +397,39 @@ public class PeopleDoorDeviceManager {
                 userManage.setCardTemplate(userID, 2);
                 break;
             }
+            // 新加的
+            case "25": {
+                logger.info("[Module]获取设备上所有人员的数量");
+                userManage.getUserCount(userID);
+                break;
+            }
+            // 新加的
+            case "26": {
+                logger.info("[Module]按条件分页查询人员信息");
+                // 从 request 取出 handle 参数
+                Object handlerObj = request.get("handler");
+                int lHandler = handlerObj != null ? (int) handlerObj : -1;
+
+                userManage.getUserInfo(userID, lHandler);
+                break;
+            }
+            // 新加的
+            case "27": {
+                logger.info("[Module]修改人员信息");
+                userManage.modifyUserInfo(userID,"12345");
+                break;
+            }
+            // 新加的
+            case "28": {
+                logger.info("[Module]注销用户");
+                userManage.logoutDevice(userID);
+            }
+            // 新加的
+            case "29": {
+                logger.info("[Module]设置设备模板代码");
+                userManage.setPeopleTemplate(userID, 2);
+                break;
+            }
             case "31": {
                 // 先下发人员,人员工号上绑定卡号
                 logger.info("[Module]下发卡号代码");
@@ -248,6 +448,24 @@ public class PeopleDoorDeviceManager {
                 cardManage.deleteCardInfo(userID, "12345");
                 break;
             }
+            // 查询所有卡号(新加的)
+            case "34": {
+
+                logger.info("[Module]查询所有卡号");
+                cardManage.searchAllCardInfo(userID);
+                break;
+            }
+            // 新加的
+            case "35": {
+                logger.info("[Module]删除全部卡号信息");
+                cardManage.deleteAllCardInfo(userID);
+                break;
+            }
+            case "36": {
+                logger.info("[Module]获取所有卡数量");
+                cardManage.getAllCardNumber(userID);
+                break;
+            }
             case "41": {
                 // 先下发人员,人员工号上绑定人脸图片
                 logger.info("[Module]二进制方式下发人脸代码");
@@ -277,11 +495,88 @@ public class PeopleDoorDeviceManager {
                 faceManage.captureFaceInfo(userID);
                 break;
             }
+            // 添加人脸信息(新加的)
+            case "46": {  // 添加人脸信息
+                logger.info("[Module]添加人脸信息");
+
+//                // 从 request 获取参数(通常是前端传过来的 JSON)
+//                Map<String, Object> condition = (Map<String, Object>) request.get("condition");
+//
+//                if (condition == null || condition.isEmpty()) {
+//                    logger.warn("缺少添加人脸所需参数 condition");
+//                    return;
+//                }
+                faceManage.addFaceInfo(userID, request);
+                break;
+            }
+            // 新加的
+            case "47": {
+                logger.info("[Module]获取设备上所有人脸的数量");
+                faceManage.getFaceCount(userID);
+                break;
+            }
+            // 新加的
+            case "48": {
+                logger.info("[Module]修改单条人脸信息");
+                faceManage.modifyFaceInfo(userID, request);
+            }
+            // 新加的
+            case "49": {
+                logger.info("[Module]停止远程配置");
+                Object handlerObj = request.get("handler");
+                int lHandler = handlerObj != null ? (int) handlerObj : -1;
+                faceManage.stopRemoteConfig(lHandler);
+                break;
+            }
             case "56": {
                 logger.info("[Module]门禁历史事件查询代码");
                 eventSearch.searchAllEvent(userID);
                 break;
             }
+            // 新加的
+            case "61": {
+                logger.info("[Module]二进制采集指纹模块");
+                fingerManage.fingerCapture(userID);
+                break;
+            }
+            // 新加的
+            case "62": {
+                logger.info("[Module]ISAPI协议方式采集指纹");
+                fingerManage.fingerCpaureByisapi(userID);
+                break;
+            }
+            // 新加的
+            case "63": {
+                logger.info("[Module]下发指纹数据");
+                fingerManage.setOneFinger(userID, "test001", "12345");
+                break;
+            }
+            // 新加的
+            case "64": {
+                logger.info("[Module]基于人员工号查询指纹信息");
+                fingerManage.SearchFingerInfo(userID, "test001");
+                break;
+            }
+            // 新加的
+            case "65": {
+                logger.info("[Module]按工号是逐个删除,按读卡器是批量删除指定读卡器上所有的指纹数据");
+                fingerManage.deleteFinger(userID, "test001");
+                break;
+            }
+            // 新加的
+            // 设置群组参数
+            case "71":{
+                logger.info("[Module]设置群组参数");
+                mutilCard.setGroupCfg(userID);
+                break;
+            }
+            // 新加的
+            // 有权限的任意n张卡刷卡之后才能开门,不限制先后次序,则只需要设置一个群组组合(卡号都配置关联该群组)
+            case "72":{
+                logger.info("[Module]设置多重认证参数");
+                mutilCard.setMultiCardCfg(userID);
+                break;
+            }
             default: {
                 logger.info("未知的指令操作!请重新输入!");
             }

+ 1373 - 0
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/alarm/PeopleDoorAlarmDataParse.java

@@ -0,0 +1,1373 @@
+package com.supervision.web.ConnectSDK.peopleDoor.alarm;
+
+
+import com.sun.jna.Pointer;
+import com.supervision.web.ConnectSDK.peopleDoor.CommonMethod.CommonUtil;
+import com.supervision.web.ConnectSDK.peopleDoor.NetSDKDemo.HCNetSDK;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Component
+public class PeopleDoorAlarmDataParse {
+
+    private static final Logger logger = LoggerFactory.getLogger(PeopleDoorAlarmDataParse.class);
+
+    private HCNetSDK hCNetSDK;
+
+    public static void alarmDataHandle(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
+        logger.info("报警事件类型: lCommand:" + Integer.toHexString(lCommand));
+        String sTime;
+        String MonitoringSiteID;
+        // lCommand是传的报警类型
+        switch (lCommand) {
+            // 异常行为检测信息
+            case HCNetSDK.COMM_ALARM_RULE:
+                HCNetSDK.NET_VCA_RULE_ALARM strVcaAlarm = new HCNetSDK.NET_VCA_RULE_ALARM();
+                strVcaAlarm.write();
+                Pointer pVCAInfo = strVcaAlarm.getPointer();
+                pVCAInfo.write(0, pAlarmInfo.getByteArray(0, strVcaAlarm.size()), 0, strVcaAlarm.size());
+                strVcaAlarm.read();
+
+                switch (strVcaAlarm.struRuleInfo.wEventTypeEx) {
+                    case 1: //穿越警戒面 (越界侦测)
+                        logger.info("越界侦测报警发生");
+                        strVcaAlarm.struRuleInfo.uEventParam.setType(HCNetSDK.NET_VCA_TRAVERSE_PLANE.class);
+                        logger.info("检测目标:"+strVcaAlarm.struRuleInfo.uEventParam.struTraversePlane.byDetectionTarget); //检测目标,0表示所有目标(表示不锁定检测目标,所有目标都将进行检测),其他取值按位表示不同的检测目标:0x01-人,0x02-车
+                        //图片保存
+                        if ((strVcaAlarm.dwPicDataLen > 0) && (strVcaAlarm.byPicTransType == 0)) {
+                            SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                            String newName = sf.format(new Date());
+                            FileOutputStream fout;
+                            try {
+                                String filename = "./pic/" + newName + "VCA_TRAVERSE_PLANE" + ".jpg";
+                                fout = new FileOutputStream(filename);
+                                //将字节写入文件
+                                long offset = 0;
+                                ByteBuffer buffers = strVcaAlarm.pImage.getByteBuffer(offset, strVcaAlarm.dwPicDataLen);
+                                byte[] bytes = new byte[strVcaAlarm.dwPicDataLen];
+                                buffers.rewind();
+                                buffers.get(bytes);
+                                fout.write(bytes);
+                                fout.close();
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                        break;
+                    case 2: //目标进入区域
+                        logger.info("目标进入区域报警发生");
+                        strVcaAlarm.struRuleInfo.uEventParam.setType(HCNetSDK.NET_VCA_AREA.class);
+                        logger.info("检测目标:"+strVcaAlarm.struRuleInfo.uEventParam.struArea.byDetectionTarget);
+                        //图片保存
+                        if ((strVcaAlarm.dwPicDataLen > 0) && (strVcaAlarm.byPicTransType == 0)) {
+                            SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                            String newName = sf.format(new Date());
+                            FileOutputStream fout;
+                            try {
+                                String filename = "./pic/" + newName + "_TargetEnter" + ".jpg";
+                                fout = new FileOutputStream(filename);
+                                //将字节写入文件
+                                long offset = 0;
+                                ByteBuffer buffers = strVcaAlarm.pImage.getByteBuffer(offset, strVcaAlarm.dwPicDataLen);
+                                byte[] bytes = new byte[strVcaAlarm.dwPicDataLen];
+                                buffers.rewind();
+                                buffers.get(bytes);
+                                fout.write(bytes);
+                                fout.close();
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                        break;
+                    case 3: //目标离开区域
+                        logger.info("目标离开区域报警触发");
+                        strVcaAlarm.struRuleInfo.uEventParam.setType(HCNetSDK.NET_VCA_AREA.class);
+                        logger.info("检测目标:"+strVcaAlarm.struRuleInfo.uEventParam.struArea.byDetectionTarget);
+                        //图片保存
+                        if ((strVcaAlarm.dwPicDataLen > 0) && (strVcaAlarm.byPicTransType == 0)) {
+                            SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                            String newName = sf.format(new Date());
+                            FileOutputStream fout;
+                            try {
+                                String filename = "./pic/" + newName + "_TargetLeave" + ".jpg";
+                                fout = new FileOutputStream(filename);
+                                //将字节写入文件
+                                long offset = 0;
+                                ByteBuffer buffers = strVcaAlarm.pImage.getByteBuffer(offset, strVcaAlarm.dwPicDataLen);
+                                byte[] bytes = new byte[strVcaAlarm.dwPicDataLen];
+                                buffers.rewind();
+                                buffers.get(bytes);
+                                fout.write(bytes);
+                                fout.close();
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                        break;
+                    case 4: //周界入侵
+                        logger.info("周界入侵报警发生");
+                        strVcaAlarm.struRuleInfo.uEventParam.setType(HCNetSDK.NET_VCA_INTRUSION.class);
+                        logger.info("检测目标:"+strVcaAlarm.struRuleInfo.uEventParam.struIntrusion.byDetectionTarget);
+                        //图片保存
+                        if ((strVcaAlarm.dwPicDataLen > 0) && (strVcaAlarm.byPicTransType == 0)) {
+                            SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                            String newName = sf.format(new Date());
+                            FileOutputStream fout;
+                            try {
+                                String filename = "./pic/" + newName + "VCA_INTRUSION" + ".jpg";
+                                fout = new FileOutputStream(filename);
+                                //将字节写入文件
+                                long offset = 0;
+                                ByteBuffer buffers = strVcaAlarm.pImage.getByteBuffer(offset, strVcaAlarm.dwPicDataLen);
+                                byte[] bytes = new byte[strVcaAlarm.dwPicDataLen];
+                                buffers.rewind();
+                                buffers.get(bytes);
+                                fout.write(bytes);
+                                fout.close();
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                        break;
+                    case 5: //徘徊
+                        logger.info("徘徊事件触发");
+                        break;
+                    case 8: //快速移动(奔跑),
+                        logger.info("快速移动(奔跑)事件触发");
+                        break;
+                    case 15:
+                        logger.info("事件触发");
+                        strVcaAlarm.struRuleInfo.uEventParam.setType(HCNetSDK.NET_VCA_LEAVE_POSITION.class);
+                        logger.info(String.valueOf(strVcaAlarm.struRuleInfo.uEventParam.struLeavePos.byOnPosition));
+                        //图片保存
+                        if ((strVcaAlarm.dwPicDataLen > 0) && (strVcaAlarm.byPicTransType == 0)) {
+                            SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                            String newName = sf.format(new Date());
+                            FileOutputStream fout;
+                            try {
+                                String filename = "./pic/" + newName + "VCA_LEAVE_POSITION_" + ".jpg";
+                                fout = new FileOutputStream(filename);
+                                //将字节写入文件
+                                long offset = 0;
+                                ByteBuffer buffers = strVcaAlarm.pImage.getByteBuffer(offset, strVcaAlarm.dwPicDataLen);
+                                byte[] bytes = new byte[strVcaAlarm.dwPicDataLen];
+                                buffers.rewind();
+                                buffers.get(bytes);
+                                fout.write(bytes);
+                                fout.close();
+                            } catch (FileNotFoundException e) {
+                                // TODO Auto-generated catch block
+                                e.printStackTrace();
+                            } catch (IOException e) {
+                                // TODO Auto-generated catch block
+                                e.printStackTrace();
+                            }
+                        }
+                    case 20: //倒地检测
+                        logger.info("倒地事件触发");
+                        break;
+                    case 44: //玩手机
+                        logger.info("玩手机报警发生");
+                        //图片保存
+                        if ((strVcaAlarm.dwPicDataLen > 0) && (strVcaAlarm.byPicTransType == 0)) {
+                            SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                            String newName = sf.format(new Date());
+                            FileOutputStream fout;
+                            try {
+                                String filename = "./pic/" + newName + "PLAY_CELLPHONE_" + ".jpg";
+                                fout = new FileOutputStream(filename);
+                                //将字节写入文件
+                                long offset = 0;
+                                ByteBuffer buffers = strVcaAlarm.pImage.getByteBuffer(offset, strVcaAlarm.dwPicDataLen);
+                                byte[] bytes = new byte[strVcaAlarm.dwPicDataLen];
+                                buffers.rewind();
+                                buffers.get(bytes);
+                                fout.write(bytes);
+                                fout.close();
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
+                        }
+                        break;
+                    case 45: //持续检测
+                        logger.info("持续检测事件触发");
+                    default:
+                        logger.info("行为事件类型:" + strVcaAlarm.struRuleInfo.wEventTypeEx);
+                        break;
+                }
+                break;
+            case HCNetSDK.COMM_ALARM_ACS: //门禁主机报警信息
+                HCNetSDK.NET_DVR_ACS_ALARM_INFO strACSInfo = new HCNetSDK.NET_DVR_ACS_ALARM_INFO();
+                strACSInfo.write();
+                Pointer pACSInfo = strACSInfo.getPointer();
+                pACSInfo.write(0, pAlarmInfo.getByteArray(0, strACSInfo.size()), 0, strACSInfo.size());
+                strACSInfo.read();
+                /**门禁事件的详细信息解析,通过主次类型的可以判断当前的具体门禁类型,例如(主类型:0X5 次类型:0x4b 表示人脸认证通过,
+                 主类型:0X5 次类型:0x4c 表示人脸认证失败)*/
+                logger.info("【门禁主机报警信息】卡号:" + new String(strACSInfo.struAcsEventInfo.byCardNo).trim() + ",卡类型:" +
+                        strACSInfo.struAcsEventInfo.byCardType + ",报警主类型:" + Integer.toHexString(strACSInfo.dwMajor) + ",报警次类型:" + Integer.toHexString(strACSInfo.dwMinor));
+                logger.info("工号1:" + strACSInfo.struAcsEventInfo.dwEmployeeNo);
+                //温度信息(如果设备支持测温功能,人脸温度信息从NET_DVR_ACS_EVENT_INFO_EXTEND_V20结构体获取)
+                if (strACSInfo.byAcsEventInfoExtendV20 == 1) {
+                    HCNetSDK.NET_DVR_ACS_EVENT_INFO_EXTEND_V20 strAcsInfoExV20 = new HCNetSDK.NET_DVR_ACS_EVENT_INFO_EXTEND_V20();
+                    strAcsInfoExV20.write();
+                    Pointer pAcsInfoExV20 = strAcsInfoExV20.getPointer();
+                    pAcsInfoExV20.write(0, strACSInfo.pAcsEventInfoExtendV20.getByteArray(0, strAcsInfoExV20.size()), 0, strAcsInfoExV20.size());
+                    strAcsInfoExV20.read();
+                    logger.info("实时温度值:" + strAcsInfoExV20.fCurrTemperature);
+                }
+                //考勤状态
+                if (strACSInfo.byAcsEventInfoExtend == 1) {
+                    HCNetSDK.NET_DVR_ACS_EVENT_INFO_EXTEND strAcsInfoEx = new HCNetSDK.NET_DVR_ACS_EVENT_INFO_EXTEND();
+                    strAcsInfoEx.write();
+                    Pointer pAcsInfoEx = strAcsInfoEx.getPointer();
+                    pAcsInfoEx.write(0, strACSInfo.pAcsEventInfoExtend.getByteArray(0, strAcsInfoEx.size()), 0, strAcsInfoEx.size());
+                    strAcsInfoEx.read();
+                    logger.info("考勤状态:" + strAcsInfoEx.byAttendanceStatus);
+                    logger.info("工号2:" + new String(strAcsInfoEx.byEmployeeNo).trim());
+                }
+
+                /**
+                 * 报警时间
+                 */
+                String year = Integer.toString(strACSInfo.struTime.dwYear);
+                String SwipeTime = year + strACSInfo.struTime.dwMonth + strACSInfo.struTime.dwDay + strACSInfo.struTime.dwHour + strACSInfo.struTime.dwMinute +
+                        strACSInfo.struTime.dwSecond;
+                if (strACSInfo.dwPicDataLen > 0) {
+//                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+//                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+                    try {
+                        /**
+                         * 人脸保存路径
+                         */
+                        String filename = "./pic/" + SwipeTime + "_ACS_Event_" + new String(strACSInfo.struAcsEventInfo.byCardNo).trim() + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strACSInfo.pPicData.getByteBuffer(offset, strACSInfo.dwPicDataLen);
+                        byte[] bytes = new byte[strACSInfo.dwPicDataLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_ID_INFO_ALARM: //身份证信息
+                HCNetSDK.NET_DVR_ID_CARD_INFO_ALARM strIDCardInfo = new HCNetSDK.NET_DVR_ID_CARD_INFO_ALARM();
+                strIDCardInfo.write();
+                Pointer pIDCardInfo = strIDCardInfo.getPointer();
+                pIDCardInfo.write(0, pAlarmInfo.getByteArray(0, strIDCardInfo.size()), 0, strIDCardInfo.size());
+                strIDCardInfo.read();
+                logger.info("报警主类型:" + Integer.toHexString(strIDCardInfo.dwMajor) + ",报警次类型:" + Integer.toHexString(strIDCardInfo.dwMinor));
+                /**
+                 * 身份证信息
+                 */
+                String IDnum = new String(strIDCardInfo.struIDCardCfg.byIDNum).trim();
+                logger.info("【身份证信息】:身份证号码:" + IDnum + ",姓名:" +
+                        new String(strIDCardInfo.struIDCardCfg.byName).trim() + ",住址:" + new String(strIDCardInfo.struIDCardCfg.byAddr));
+
+                /**
+                 * 报警时间
+                 */
+                String year1 = Integer.toString(strIDCardInfo.struSwipeTime.wYear);
+                String SwipeTime1 = year1 + strIDCardInfo.struSwipeTime.byMonth + strIDCardInfo.struSwipeTime.byDay + strIDCardInfo.struSwipeTime.byHour + strIDCardInfo.struSwipeTime.byMinute +
+                        strIDCardInfo.struSwipeTime.bySecond;
+                /**
+                 * 保存图片
+                 */
+                //身份证图片
+                if (strIDCardInfo.dwPicDataLen > 0 || strIDCardInfo.pPicData != null) {
+//                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+//                    String nowtime = sf.format(new Date());
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + SwipeTime1 + "_" + IDnum + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strIDCardInfo.pPicData.getByteBuffer(offset, strIDCardInfo.dwPicDataLen);
+                        byte[] bytes = new byte[strIDCardInfo.dwPicDataLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+
+                if (strIDCardInfo.dwCapturePicDataLen > 0 || strIDCardInfo.pCapturePicData != null) {
+//                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+//                    String nowtime = sf.format(new Date());
+                    FileOutputStream fout;
+                    try {
+                        /**
+                         * 人脸图片保存路径
+                         */
+                        String filename = "./pic/" + SwipeTime1 + "_CapturePic_" + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strIDCardInfo.pCapturePicData.getByteBuffer(offset, strIDCardInfo.dwCapturePicDataLen);
+                        byte[] bytes = new byte[strIDCardInfo.dwCapturePicDataLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_ALARM_VIDEO_INTERCOM: //可视对讲报警信息
+                logger.info("可视对讲报警触发");
+                HCNetSDK.NET_DVR_VIDEO_INTERCOM_ALARM strVideoIntercomAlarm = new HCNetSDK.NET_DVR_VIDEO_INTERCOM_ALARM();
+                strVideoIntercomAlarm.write();
+                Pointer pVideoIntercomAlarm = strVideoIntercomAlarm.getPointer();
+                pVideoIntercomAlarm.write(0, pAlarmInfo.getByteArray(0, strVideoIntercomAlarm.size()), 0, strVideoIntercomAlarm.size());
+                strVideoIntercomAlarm.read();
+                logger.info("byAlarmType:" + strVideoIntercomAlarm.byAlarmType);
+
+                if (strVideoIntercomAlarm.byAlarmType == 1) {
+                    strVideoIntercomAlarm.uAlarmInfo.setType(HCNetSDK.NET_DVR_VIDEO_INTERCOM_ALARM_INFO_UNION.class);
+                    strVideoIntercomAlarm.uAlarmInfo.read();
+                    logger.info("byZoneType :" + strVideoIntercomAlarm.uAlarmInfo.struZoneAlarm.byZoneType);
+                }
+
+                break;
+            case HCNetSDK.COMM_UPLOAD_VIDEO_INTERCOM_EVENT: //可视对讲事件记录信息
+                logger.info("可视对讲事件记录报警触发");
+                HCNetSDK.NET_DVR_VIDEO_INTERCOM_EVENT strVideoIntercomEvent = new HCNetSDK.NET_DVR_VIDEO_INTERCOM_EVENT();
+                strVideoIntercomEvent.write();
+                Pointer pVideoIntercomEvent = strVideoIntercomEvent.getPointer();
+                pVideoIntercomEvent.write(0, pAlarmInfo.getByteArray(0, strVideoIntercomEvent.size()), 0, strVideoIntercomEvent.size());
+                strVideoIntercomEvent.read();
+                logger.info("byEventType:" + strVideoIntercomEvent.byEventType);
+
+                if (strVideoIntercomEvent.byEventType == 1) {
+                    strVideoIntercomEvent.uEventInfo.setType(HCNetSDK.NET_DVR_UNLOCK_RECORD_INFO.class);
+                    strVideoIntercomEvent.uEventInfo.read();
+                    logger.info("byUnlockType:" + strVideoIntercomEvent.uEventInfo.struUnlockRecord.byUnlockType
+                            + ",byControlSrc:" + new String(strVideoIntercomEvent.uEventInfo.struUnlockRecord.byControlSrc).trim());
+                }
+                break;
+            case HCNetSDK.COMM_UPLOAD_FACESNAP_RESULT: //实时特征抓拍上传
+                logger.info("UPLOAD_FACESNAP_Alarm");
+                HCNetSDK.NET_VCA_FACESNAP_RESULT strFaceSnapInfo = new HCNetSDK.NET_VCA_FACESNAP_RESULT();
+                strFaceSnapInfo.write();
+                Pointer pFaceSnapInfo = strFaceSnapInfo.getPointer();
+                pFaceSnapInfo.write(0, pAlarmInfo.getByteArray(0, strFaceSnapInfo.size()), 0, strFaceSnapInfo.size());
+                strFaceSnapInfo.read();
+
+                //事件时间
+                int dwYear = (strFaceSnapInfo.dwAbsTime >> 26) + 2000;
+                int dwMonth = (strFaceSnapInfo.dwAbsTime >> 22) & 15;
+                int dwDay = (strFaceSnapInfo.dwAbsTime >> 17) & 31;
+                int dwHour = (strFaceSnapInfo.dwAbsTime >> 12) & 31;
+                int dwMinute = (strFaceSnapInfo.dwAbsTime >> 6) & 63;
+                int dwSecond = (strFaceSnapInfo.dwAbsTime >> 0) & 63;
+
+                String strAbsTime = "" + String.format("%04d", dwYear) +
+                        String.format("%02d", dwMonth) +
+                        String.format("%02d", dwDay) +
+                        String.format("%02d", dwHour) +
+                        String.format("%02d", dwMinute) +
+                        String.format("%02d", dwSecond);
+
+                //人脸属性信息
+                String sFaceAlarmInfo = "Abs时间:" + strAbsTime + ",是否戴口罩:" +
+                        strFaceSnapInfo.struFeature.byMask + ",是否微笑:" + strFaceSnapInfo.struFeature.bySmile;
+                logger.info("人脸信息:" + sFaceAlarmInfo);
+
+                //人脸测温信息
+                if (strFaceSnapInfo.byAddInfo == 1) {
+                    HCNetSDK.NET_VCA_FACESNAP_ADDINFO strAddInfo = new HCNetSDK.NET_VCA_FACESNAP_ADDINFO();
+                    strAddInfo.write();
+                    Pointer pAddInfo = strAddInfo.getPointer();
+                    pAddInfo.write(0, strFaceSnapInfo.pAddInfoBuffer.getByteArray(0, strAddInfo.size()), 0, strAddInfo.size());
+                    strAddInfo.read();
+
+                    String sTemperatureInfo = "测温是否开启:" + strAddInfo.byFaceSnapThermometryEnabled + "人脸温度:" + strAddInfo.fFaceTemperature + "温度是否异常"
+                            + strAddInfo.byIsAbnomalTemperature + "报警温度阈值:" + strAddInfo.fAlarmTemperature;
+                    logger.info("人脸温度信息:" + sTemperatureInfo);
+
+                }
+
+                try {
+                    SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
+                    String time = df.format(new Date());// new Date()为获取当前系统时间
+
+                    //人脸图片写文件
+                    FileOutputStream small = new FileOutputStream("./pic/" + time + "small.jpg");
+                    FileOutputStream big = new FileOutputStream("./pic/" + time + "big.jpg");
+                    try {
+                        small.write(strFaceSnapInfo.pBuffer1.getByteArray(0, strFaceSnapInfo.dwFacePicLen), 0, strFaceSnapInfo.dwFacePicLen);
+                        small.close();
+                    } catch (IOException ex) {
+                        ex.printStackTrace();
+                    }
+                    try {
+                        big.write(strFaceSnapInfo.pBuffer2.getByteArray(0, strFaceSnapInfo.dwBackgroundPicLen), 0, strFaceSnapInfo.dwBackgroundPicLen);
+                        big.close();
+                    } catch (IOException ex) {
+                        ex.printStackTrace();
+                    }
+                } catch (FileNotFoundException ex) {
+                    ex.printStackTrace();
+                }
+                break;
+
+            //  客流量报警信息
+            case HCNetSDK.COMM_ALARM_PDC:
+                HCNetSDK.NET_DVR_PDC_ALRAM_INFO strPDCResult = new HCNetSDK.NET_DVR_PDC_ALRAM_INFO();
+                strPDCResult.write();
+                Pointer pPDCInfo = strPDCResult.getPointer();
+                pPDCInfo.write(0, pAlarmInfo.getByteArray(0, strPDCResult.size()), 0, strPDCResult.size());
+                strPDCResult.read();
+                // byMode=0-实时统计结果(联合体中struStatFrame有效),
+                if (strPDCResult.byMode == 0) {
+                    strPDCResult.uStatModeParam.setType(HCNetSDK.NET_DVR_STATFRAME.class);
+                    String sAlarmPDC0Info = "实时客流量统计,进入人数:" + strPDCResult.dwEnterNum + ",离开人数:" + strPDCResult.dwLeaveNum +
+                            ", byMode:" + strPDCResult.byMode + ", dwRelativeTime:" + strPDCResult.uStatModeParam.struStatFrame.dwRelativeTime +
+                            ", dwAbsTime:" + strPDCResult.uStatModeParam.struStatFrame.dwAbsTime;
+                }
+                // byMode=1-周期统计结果(联合体中struStatTime有效),
+                if (strPDCResult.byMode == 1) {
+                    strPDCResult.uStatModeParam.setType(HCNetSDK.NET_DVR_STATTIME.class);
+                    String strtmStart = "" + String.format("%04d", strPDCResult.uStatModeParam.struStatTime.tmStart.dwYear) +
+                            String.format("%02d", strPDCResult.uStatModeParam.struStatTime.tmStart.dwMonth) +
+                            String.format("%02d", strPDCResult.uStatModeParam.struStatTime.tmStart.dwDay) +
+                            String.format("%02d", strPDCResult.uStatModeParam.struStatTime.tmStart.dwHour) +
+                            String.format("%02d", strPDCResult.uStatModeParam.struStatTime.tmStart.dwMinute) +
+                            String.format("%02d", strPDCResult.uStatModeParam.struStatTime.tmStart.dwSecond);
+                    String strtmEnd = "" + String.format("%04d", strPDCResult.uStatModeParam.struStatTime.tmEnd.dwYear) +
+                            String.format("%02d", strPDCResult.uStatModeParam.struStatTime.tmEnd.dwMonth) +
+                            String.format("%02d", strPDCResult.uStatModeParam.struStatTime.tmEnd.dwDay) +
+                            String.format("%02d", strPDCResult.uStatModeParam.struStatTime.tmEnd.dwHour) +
+                            String.format("%02d", strPDCResult.uStatModeParam.struStatTime.tmEnd.dwMinute) +
+                            String.format("%02d", strPDCResult.uStatModeParam.struStatTime.tmEnd.dwSecond);
+                    String sAlarmPDC1Info = "周期性客流量统计,进入人数:" + strPDCResult.dwEnterNum + ",离开人数:" + strPDCResult.dwLeaveNum +
+                            ", byMode:" + strPDCResult.byMode + ", tmStart:" + strtmStart + ",tmEnd :" + strtmEnd;
+                }
+                break;
+            case HCNetSDK.COMM_ALARM_V30:  //移动侦测、视频丢失、遮挡、IO信号量等报警信息(V3.0以上版本支持的设备)
+                HCNetSDK.NET_DVR_ALARMINFO_V30 struAlarmInfo = new HCNetSDK.NET_DVR_ALARMINFO_V30();
+                struAlarmInfo.write();
+                Pointer pAlarmInfo_V30 = struAlarmInfo.getPointer();
+                pAlarmInfo_V30.write(0, pAlarmInfo.getByteArray(0, struAlarmInfo.size()), 0, struAlarmInfo.size());
+                struAlarmInfo.read();
+                logger.info("报警类型:" + struAlarmInfo.dwAlarmType);  // 3-移动侦测
+                break;
+            case HCNetSDK.COMM_ALARM_V40: //移动侦测、视频丢失、遮挡、IO信号量等报警信息,报警数据为可变长
+
+                HCNetSDK.NET_DVR_ALARMINFO_V40 struAlarmInfoV40 = new HCNetSDK.NET_DVR_ALARMINFO_V40();
+                struAlarmInfoV40.write();
+                Pointer pAlarmInfoV40 = struAlarmInfoV40.getPointer();
+                pAlarmInfoV40.write(0, pAlarmInfo.getByteArray(0, struAlarmInfoV40.size()), 0, struAlarmInfoV40.size());
+                struAlarmInfoV40.read();
+                switch (struAlarmInfoV40.struAlarmFixedHeader.dwAlarmType) {
+                    case 0:
+                        struAlarmInfoV40.struAlarmFixedHeader.ustruAlarm.setType(HCNetSDK.struIOAlarm.class);
+                        struAlarmInfoV40.read();
+                        logger.info("信号量报警,报警输入口:"+struAlarmInfoV40.struAlarmFixedHeader.ustruAlarm.struioAlarm.dwAlarmInputNo);
+                        break;
+                    case 1:
+                        logger.info("硬盘满");
+                        break;
+                    case 2:
+                        logger.info("信号丢失");
+                        break;
+                    case 3:
+                        String sAlarmType="";
+                        struAlarmInfoV40.struAlarmFixedHeader.ustruAlarm.setType(HCNetSDK.struAlarmChannel.class);
+                        struAlarmInfoV40.read();
+                        int iChanNum = struAlarmInfoV40.struAlarmFixedHeader.ustruAlarm.strualarmChannel.dwAlarmChanNum;
+                        sAlarmType = sAlarmType + new String(":移动侦测") + "," + "报警通道个数:" + iChanNum + "," + "报警通道号:";
+
+                        for (int i = 0; i < iChanNum; i++) {
+                            byte[] byChannel = struAlarmInfoV40.pAlarmData.getByteArray(i * 4, 4);
+
+                            int iChanneNo = 0;
+                            for (int j = 0; j < 4; j++) {
+                                int ioffset = j * 8;
+                                int iByte = byChannel[j] & 0xff;
+                                iChanneNo = iChanneNo + (iByte << ioffset);
+                            }
+
+                            sAlarmType = sAlarmType + "+ch[" + iChanneNo + "]";
+                        }
+                        logger.info(sAlarmType);
+                        break;
+                    case 4:
+                        logger.info("硬盘未格式化");
+                        break;
+                    case 5:
+                        logger.info("读写硬盘出错");
+                        break;
+                    case 6:
+                        logger.info("遮挡报警");
+                        break;
+                    case 7:
+                        logger.info("制式不匹配");
+                        break;
+                    case 8:
+                        logger.info("非法访问");
+                        break;
+                }
+                break;
+            // COMM_UPLOAD_PLATE_RESULT(老报警信息)
+            case HCNetSDK.COMM_UPLOAD_PLATE_RESULT:
+                logger.info("COMM_UPLOAD_PLATE_RESULT(老报警信息)");
+                break;
+            // COMM_ITS_PLATE_RESULT(新报警信息)
+            case HCNetSDK.COMM_ITS_PLATE_RESULT: // 交通抓拍结果(新报警信息)
+                logger.info("COMM_ITS_PLATE_RESULT(新报警信息)");
+                logger.info("【海康车牌摄像头回调】交通抓拍的终端图片上传");
+                break;
+            case HCNetSDK.COMM_ALARM_TFS: //道路违章取证报警
+                HCNetSDK.NET_DVR_TFS_ALARM strTfsAlarm = new HCNetSDK.NET_DVR_TFS_ALARM();
+                strTfsAlarm.write();
+                Pointer pTfsAlarm = strTfsAlarm.getPointer();
+                pTfsAlarm.write(0, pAlarmInfo.getByteArray(0, strTfsAlarm.size()), 0, strTfsAlarm.size());
+                strTfsAlarm.read();
+                sTime = CommonUtil.parseTime(strTfsAlarm.dwAbsTime); //报警绝对时间
+                int IllegalType = strTfsAlarm.dwIllegalType; // 违章类型
+                MonitoringSiteID = strTfsAlarm.byMonitoringSiteID.toString(); //布防点编号
+                // 车牌信息
+                try {
+                    String PlateInfo = "车牌号:" + new String(strTfsAlarm.struPlateInfo.sLicense, "GBK");
+                    logger.info("【道路违章取证报警】时间:" + sTime + "违章类型:" + IllegalType + "车牌信息:" + PlateInfo);
+                } catch (UnsupportedEncodingException e) {
+                    e.printStackTrace();
+                }
+                //报警图片信息
+                for (int i = 0; i < strTfsAlarm.dwPicNum; i++) {
+                    if (strTfsAlarm.struPicInfo[i].dwDataLen > 0) {
+                        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                        String newName = sf.format(new Date());
+                        FileOutputStream fout;
+                        try {
+                            String filename = "./pic/" + newName + "_type[" + strTfsAlarm.struPicInfo[i].byType + "]_TfsPlate.jpg";
+                            fout = new FileOutputStream(filename);
+                            //将字节写入文件
+                            long offset = 0;
+                            ByteBuffer buffers = strTfsAlarm.struPicInfo[i].pBuffer.getByteBuffer(offset, strTfsAlarm.struPicInfo[i].dwDataLen);
+                            byte[] bytes = new byte[strTfsAlarm.struPicInfo[i].dwDataLen];
+                            buffers.rewind();
+                            buffers.get(bytes);
+                            fout.write(bytes);
+                            fout.close();
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_ALARM_AID_V41: //道路事件检测
+                HCNetSDK.NET_DVR_AID_ALARM_V41 strAIDAlarmV41 = new HCNetSDK.NET_DVR_AID_ALARM_V41();
+                strAIDAlarmV41.write();
+                Pointer pstrAIDAlarmV41 = strAIDAlarmV41.getPointer();
+                pstrAIDAlarmV41.write(0, pAlarmInfo.getByteArray(0, strAIDAlarmV41.size()), 0, strAIDAlarmV41.size());
+                strAIDAlarmV41.read();
+                sTime = CommonUtil.parseTime(strAIDAlarmV41.dwAbsTime); //报警触发绝对时间
+                MonitoringSiteID = strAIDAlarmV41.byMonitoringSiteID.toString(); //布防点编号
+                int AIDType = strAIDAlarmV41.struAIDInfo.dwAIDType; //    交通事件类型
+                int AIDTypeEx = strAIDAlarmV41.struAIDInfo.dwAIDTypeEx; //交通事件类型扩展
+                logger.info("【道路事件检测】" + "时间:" + sTime + "布防点:" + MonitoringSiteID + "交通事件类型:" + AIDType + "交通事件类型扩展:" + AIDTypeEx);
+                //报警图片信息
+                if (strAIDAlarmV41.dwPicDataLen > 0 && strAIDAlarmV41.pImage != null) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + newName + "_AIDalarm.jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strAIDAlarmV41.pImage.getByteBuffer(offset, strAIDAlarmV41.dwPicDataLen);
+                        byte[] bytes = new byte[strAIDAlarmV41.dwPicDataLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_ALARM_TPS_V41://交通数据统计的报警
+                HCNetSDK.NET_DVR_TPS_ALARM_V41 strTPSalarmV41 = new HCNetSDK.NET_DVR_TPS_ALARM_V41();
+                strTPSalarmV41.write();
+                Pointer pstrTPSalarmV41 = strTPSalarmV41.getPointer();
+                pstrTPSalarmV41.write(0, pAlarmInfo.getByteArray(0, strTPSalarmV41.size()), 0, strTPSalarmV41.size());
+                strTPSalarmV41.read();
+                sTime = CommonUtil.parseTime(strTPSalarmV41.dwAbsTime);
+                MonitoringSiteID = strTPSalarmV41.byMonitoringSiteID.toString(); //布防点编号
+                String StartTime = CommonUtil.parseTime(strTPSalarmV41.dwStartTime); //开始统计时间;
+                String StopTime = CommonUtil.parseTime(strTPSalarmV41.dwStopTime); //结束统计时间;
+                logger.info("【交通数据统计】" + "时间:" + sTime + "布防点编号:" + MonitoringSiteID + "开始统计时间:" + StartTime + "结束统计时间:" + StopTime);
+                //车道统计参数信息
+                for (int i = 0; i <= HCNetSDK.MAX_TPS_RULE; i++) {
+                    byte LaneNo = strTPSalarmV41.struTPSInfo.struLaneParam[i].byLaneNo; //车道号
+                    byte TrafficState = strTPSalarmV41.struTPSInfo.struLaneParam[i].byTrafficState; //车道状态 0-无效,1-畅通,2-拥挤,3-堵塞
+                    int TpsType = strTPSalarmV41.struTPSInfo.struLaneParam[i].dwTpsType; //数据变化类型标志,表示当前上传的统计参数中,哪些数据有效,按位区分
+                    int LaneVolume = strTPSalarmV41.struTPSInfo.struLaneParam[i].dwLaneVolume; //车道流量
+                    int LaneVelocity = strTPSalarmV41.struTPSInfo.struLaneParam[i].dwLaneVelocity; //车道平均速度
+                    float SpaceOccupyRation = strTPSalarmV41.struTPSInfo.struLaneParam[i].fSpaceOccupyRation;  //车道占有率,百分比计算(空间上,车辆长度与布防路段总长度的比值)
+                    logger.info("车道号:" + LaneNo + "车道状态:" + TrafficState + "车道流量:" + LaneVolume + "车道占有率:" + SpaceOccupyRation + "\n");
+                }
+                break;
+            case HCNetSDK.COMM_ALARM_TPS_REAL_TIME: //实时过车数据数据
+                HCNetSDK.NET_DVR_TPS_REAL_TIME_INFO netDvrTpsParam = new HCNetSDK.NET_DVR_TPS_REAL_TIME_INFO();
+                netDvrTpsParam.write();
+                Pointer pItsParkVehicle = netDvrTpsParam.getPointer();
+                pItsParkVehicle.write(0, pAlarmInfo.getByteArray(0, netDvrTpsParam.size()), 0, netDvrTpsParam.size());
+                netDvrTpsParam.read();
+                String struTime = "" + String.format("%04d", netDvrTpsParam.struTime.wYear) +
+                        String.format("%02d", netDvrTpsParam.struTime.byMonth) +
+                        String.format("%02d", netDvrTpsParam.struTime.byDay) +
+                        String.format("%02d", netDvrTpsParam.struTime.byDay) +
+                        String.format("%02d", netDvrTpsParam.struTime.byHour) +
+                        String.format("%02d", netDvrTpsParam.struTime.byMinute) +
+                        String.format("%02d", netDvrTpsParam.struTime.bySecond);
+                Short wDeviceID = new Short(netDvrTpsParam.struTPSRealTimeInfo.wDeviceID);//设备ID
+                int channel = netDvrTpsParam.dwChan; //触发报警通道号
+                String byLane = new String(String.valueOf(netDvrTpsParam.struTPSRealTimeInfo.byLane)).trim();// 对应车道号
+                String bySpeed = new String(String.valueOf(netDvrTpsParam.struTPSRealTimeInfo.bySpeed)).trim();// 对应车速(KM/H)
+                int dwDownwardFlow = netDvrTpsParam.struTPSRealTimeInfo.dwDownwardFlow;//当前车道 从上到下车流量
+                int dwUpwardFlow = netDvrTpsParam.struTPSRealTimeInfo.dwUpwardFlow;       //当前车道 从下到上车流量
+                logger.info("通道号:" + channel + "; 时间:" + struTime + ";对应车道号:" + byLane + ";当前车道 从上到下车流量:" + dwDownwardFlow + ";dwUpwardFlow:" + dwUpwardFlow);
+                break;
+
+            case HCNetSDK.COMM_ALARM_TPS_STATISTICS: //统计过车数据
+                HCNetSDK.NET_DVR_TPS_STATISTICS_INFO netDvrTpsStatisticsInfo = new HCNetSDK.NET_DVR_TPS_STATISTICS_INFO();
+                netDvrTpsStatisticsInfo.write();
+                Pointer pTpsVehicle = netDvrTpsStatisticsInfo.getPointer();
+                pTpsVehicle.write(0, pAlarmInfo.getByteArray(0, netDvrTpsStatisticsInfo.size()), 0, netDvrTpsStatisticsInfo.size());
+                netDvrTpsStatisticsInfo.read();
+                int Tpschannel = netDvrTpsStatisticsInfo.dwChan; //触发报警通道号
+                //统计开始时间
+                String struStartTime = "" + String.format("%04d", netDvrTpsStatisticsInfo.struTPSStatisticsInfo.struStartTime.wYear) +
+                        String.format("%02d", netDvrTpsStatisticsInfo.struTPSStatisticsInfo.struStartTime.byMonth) +
+                        String.format("%02d", netDvrTpsStatisticsInfo.struTPSStatisticsInfo.struStartTime.byDay) +
+                        String.format("%02d", netDvrTpsStatisticsInfo.struTPSStatisticsInfo.struStartTime.byDay) +
+                        String.format("%02d", netDvrTpsStatisticsInfo.struTPSStatisticsInfo.struStartTime.byHour) +
+                        String.format("%02d", netDvrTpsStatisticsInfo.struTPSStatisticsInfo.struStartTime.byMinute) +
+                        String.format("%02d", netDvrTpsStatisticsInfo.struTPSStatisticsInfo.struStartTime.bySecond);
+                byte TotalLaneNum = netDvrTpsStatisticsInfo.struTPSStatisticsInfo.byTotalLaneNum; //有效车道总数
+                logger.info("通道号:" + Tpschannel + "; 开始统计时间:" + struStartTime + "有效车道总数:" + TotalLaneNum);
+                break;
+            case HCNetSDK.COMM_ITS_PARK_VEHICLE: //停车场数据上传
+                HCNetSDK.NET_ITS_PARK_VEHICLE strParkVehicle = new HCNetSDK.NET_ITS_PARK_VEHICLE();
+                strParkVehicle.write();
+                Pointer pstrParkVehicle = strParkVehicle.getPointer();
+                pstrParkVehicle.write(0, pAlarmInfo.getByteArray(0, strParkVehicle.size()), 0, strParkVehicle.size());
+                strParkVehicle.read();
+                try {
+                    byte ParkError = strParkVehicle.byParkError; //停车异常:0- 正常,1- 异常
+                    String ParkingNo = new String(strParkVehicle.byParkingNo, "UTF-8"); //车位编号
+                    byte LocationStatus = strParkVehicle.byLocationStatus; //车位车辆状态 0- 无车,1- 有车
+                    MonitoringSiteID = strParkVehicle.byMonitoringSiteID.toString();
+                    String plateNo = new String(strParkVehicle.struPlateInfo.sLicense, "GBK"); //车牌号
+                } catch (UnsupportedEncodingException e) {
+                    e.printStackTrace();
+                }
+                //报警图片信息
+                for (int i = 0; i < strParkVehicle.dwPicNum; i++) {
+                    if (strParkVehicle.struPicInfo[i].dwDataLen > 0) {
+                        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                        String newName = sf.format(new Date());
+                        FileOutputStream fout;
+                        try {
+                            String filename = "./pic/" + newName + "_ParkVehicle.jpg";
+                            fout = new FileOutputStream(filename);
+                            //将字节写入文件
+                            long offset = 0;
+                            ByteBuffer buffers = strParkVehicle.struPicInfo[i].pBuffer.getByteBuffer(offset, strParkVehicle.struPicInfo[i].dwDataLen);
+                            byte[] bytes = new byte[strParkVehicle.struPicInfo[i].dwDataLen];
+                            buffers.rewind();
+                            buffers.get(bytes);
+                            fout.write(bytes);
+                            fout.close();
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_ALARMHOST_CID_ALARM://报警主机CID报告报警上传
+                HCNetSDK.NET_DVR_CID_ALARM strCIDalarm = new HCNetSDK.NET_DVR_CID_ALARM();
+                strCIDalarm.write();
+                Pointer pstrCIDalarm = strCIDalarm.getPointer();
+                pstrCIDalarm.write(0, pAlarmInfo.getByteArray(0, strCIDalarm.size()), 0, strCIDalarm.size());
+                strCIDalarm.read();
+                try {
+                    String TriggerTime = "" + String.format("%04d", strCIDalarm.struTriggerTime.wYear) +
+                            String.format("%02d", strCIDalarm.struTriggerTime.byMonth) +
+                            String.format("%02d", strCIDalarm.struTriggerTime.byDay) +
+                            String.format("%02d", strCIDalarm.struTriggerTime.byDay) +
+                            String.format("%02d", strCIDalarm.struTriggerTime.byHour) +
+                            String.format("%02d", strCIDalarm.struTriggerTime.byMinute) +
+                            String.format("%02d", strCIDalarm.struTriggerTime.bySecond);  //触发报警时间
+                    String sCIDCode = new String(strCIDalarm.sCIDCode, "GBK"); //CID事件号
+                    String sCIDDescribe = new String(strCIDalarm.sCIDDescribe, "GBK"); //CID事件名
+                    byte bySubSysNo = strCIDalarm.bySubSysNo; //子系统号
+                    if (strCIDalarm.wDefenceNo != 0xff)
+                    {
+                        logger.info("防区号:"+Integer.sum(strCIDalarm.wDefenceNo,1));
+                    }
+                    logger.info("【CID事件】" + "触发时间:" + TriggerTime + "CID事件号:" + sCIDCode + "CID事件名:" + sCIDDescribe + "子系统号:" +
+                            bySubSysNo);
+                } catch (UnsupportedEncodingException e) {
+                    e.printStackTrace();
+                }
+                break;
+            case HCNetSDK.COMM_IPC_AUXALARM_RESULT: //PIR报警、无线报警、呼救报警信息
+                logger.info("PIR报警、无线报警、呼救报警触发");
+                break;
+            case HCNetSDK.COMM_ISAPI_ALARM: //ISAPI协议报警信息
+                HCNetSDK.NET_DVR_ALARM_ISAPI_INFO struEventISAPI = new HCNetSDK.NET_DVR_ALARM_ISAPI_INFO();
+                struEventISAPI.write();
+                Pointer pEventISAPI = struEventISAPI.getPointer();
+                pEventISAPI.write(0, pAlarmInfo.getByteArray(0, struEventISAPI.size()), 0, struEventISAPI.size());
+                struEventISAPI.read();
+                String sAlarmInfo = new String(pAlarmer.sDeviceIP).trim();
+                //报警数据类型:0- invalid,1- xml,2- json
+                sAlarmInfo = "报警设备IP:" + sAlarmInfo + ":ISAPI协议报警信息, 数据格式:" + struEventISAPI.byDataType +
+                        ", 图片个数:" + struEventISAPI.byPicturesNumber;
+                logger.info(sAlarmInfo);
+                SimpleDateFormat sf1 = new SimpleDateFormat("yyyyMMddHHmmss");
+                String curTime1 = sf1.format(new Date());
+                //报警数据打印
+                HCNetSDK.BYTE_ARRAY m_strISAPIData = new HCNetSDK.BYTE_ARRAY(struEventISAPI.dwAlarmDataLen);
+                m_strISAPIData.write();
+                Pointer pPlateInfo = m_strISAPIData.getPointer();
+                pPlateInfo.write(0, struEventISAPI.pAlarmData.getByteArray(0, m_strISAPIData.size()), 0, m_strISAPIData.size());
+                m_strISAPIData.read();
+                logger.info(new String(m_strISAPIData.byValue).trim() +"\n");
+/*
+                FileOutputStream foutdata;
+                try {
+                    String jsonfilename = "./pic/" + new String(pAlarmer.sDeviceIP).trim() + curTime1 + "_ISAPI_Alarm_" + ".json";
+                    foutdata = new FileOutputStream(jsonfilename);
+                    //将字节写入文件
+                    ByteBuffer jsonbuffers = struEventISAPI.pAlarmData.getByteBuffer(0, struEventISAPI.dwAlarmDataLen);
+                    byte[] jsonbytes = new byte[struEventISAPI.dwAlarmDataLen];
+                    jsonbuffers.rewind();
+                    jsonbuffers.get(jsonbytes);
+                    foutdata.write(jsonbytes);
+                    foutdata.close();
+                } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }*/
+                //图片数据保存
+                for (int i = 0; i < struEventISAPI.byPicturesNumber; i++) {
+                    HCNetSDK.NET_DVR_ALARM_ISAPI_PICDATA struPicData = new HCNetSDK.NET_DVR_ALARM_ISAPI_PICDATA();
+                    struPicData.write();
+                    Pointer pPicData = struPicData.getPointer();
+                    pPicData.write(0, struEventISAPI.pPicPackData.getByteArray(i * struPicData.size(), struPicData.size()), 0, struPicData.size());
+                    struPicData.read();
+
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + new String(pAlarmer.sDeviceIP).trim() + curTime1 +
+                                "_ISAPIPic_" + i + "_" + new String(struPicData.szFilename).trim() + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = struPicData.pPicData.getByteBuffer(offset, struPicData.dwPicLen);
+                        byte[] bytes = new byte[struPicData.dwPicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_VCA_ALARM:  // 智能检测通用报警(Json或者XML数据结构)
+                sAlarmInfo = new String(pAlarmer.sDeviceIP);
+                //报警数据类型:0- invalid,1- xml,2- json
+                sAlarmInfo = "报警设备IP:" + sAlarmInfo;
+                logger.info(sAlarmInfo);
+
+                SimpleDateFormat sf0 = new SimpleDateFormat("yyyyMMddHHmmss");
+                String curTime0 = sf0.format(new Date());
+                FileOutputStream Data;
+                String jsonfile = "../pic" + new String(pAlarmer.sDeviceIP).trim() + curTime0 + "_VCA_ALARM_" + ".json";
+                try {
+                    Data = new FileOutputStream(jsonfile);
+                    //将字节写入文件
+                    ByteBuffer dataBuffer = pAlarmInfo.getByteBuffer(0, dwBufLen);
+                    byte[] dataByte = new byte[dwBufLen];
+                    dataBuffer.rewind();
+                    dataBuffer.get(dataByte);
+                    Data.write(dataByte);
+                    Data.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                break;
+            case HCNetSDK.COMM_SNAP_MATCH_ALARM:    //人脸比对报警
+                HCNetSDK.NET_VCA_FACESNAP_MATCH_ALARM strFaceSnapMatch = new HCNetSDK.NET_VCA_FACESNAP_MATCH_ALARM();
+                strFaceSnapMatch.write();
+                Pointer pFaceSnapMatch = strFaceSnapMatch.getPointer();
+                pFaceSnapMatch.write(0, pAlarmInfo.getByteArray(0, strFaceSnapMatch.size()), 0, strFaceSnapMatch.size());
+                strFaceSnapMatch.read();
+                //比对结果,0-保留,1-比对成功,2-比对失败
+                String sFaceSnapMatchInfo = "比对结果:" + strFaceSnapMatch.byContrastStatus + ",相似度:" + strFaceSnapMatch.fSimilarity;
+                logger.info(sFaceSnapMatchInfo);
+                if (strFaceSnapMatch.struBlockListInfo.dwFDIDLen > 0) {
+                    long offset1 = 0;
+                    ByteBuffer buffers1 = strFaceSnapMatch.struBlockListInfo.pFDID.getByteBuffer(offset1, strFaceSnapMatch.struBlockListInfo.dwFDIDLen);
+                    byte[] bytes1 = new byte[strFaceSnapMatch.struBlockListInfo.dwFDIDLen];
+                    buffers1.get(bytes1);
+                    logger.info("人脸库ID:" + new String(bytes1));
+                }
+                if (strFaceSnapMatch.struBlockListInfo.dwPIDLen > 0) {
+                    long offset2 = 0;
+                    ByteBuffer buffers2 = strFaceSnapMatch.struBlockListInfo.pPID.getByteBuffer(offset2, strFaceSnapMatch.struBlockListInfo.dwPIDLen);
+                    byte[] bytes2 = new byte[strFaceSnapMatch.struBlockListInfo.dwPIDLen];
+                    buffers2.get(bytes2);
+                    logger.info("图片ID:" + new String(bytes2));
+                }
+                if (strFaceSnapMatch.struBlockListInfo.struBlockListInfo.dwFCAdditionInfoLen > 0) {
+                    //抓拍库附加信息解析(解析人脸测温温度,人脸温度存放在附件信息的XML报文中,节点:  <currTemperature> )
+                    SimpleDateFormat sf2 = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String curTime2 = sf2.format(new Date());
+                    FileOutputStream AddtionData;
+                    String AddtionFile = "../pic" + new String(pAlarmer.sDeviceIP).trim() + curTime2 + "_FCAdditionInfo_" + ".xml";
+                    try {
+                        Data = new FileOutputStream(AddtionFile);
+                        //将字节写入文件
+                        ByteBuffer dataBuffer = strFaceSnapMatch.struBlockListInfo.struBlockListInfo.pFCAdditionInfoBuffer.getByteBuffer(0, strFaceSnapMatch.struBlockListInfo.struBlockListInfo.dwFCAdditionInfoLen);
+                        byte[] dataByte = new byte[dwBufLen];
+                        dataBuffer.rewind();
+                        dataBuffer.get(dataByte);
+                        Data.write(dataByte);
+                        Data.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                //人脸比对报警图片保存,图片格式二进制
+                if ((strFaceSnapMatch.dwSnapPicLen > 0) && (strFaceSnapMatch.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + newName + "_pSnapPicBuffer" + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strFaceSnapMatch.pSnapPicBuffer.getByteBuffer(offset, strFaceSnapMatch.dwSnapPicLen);
+                        byte[] bytes = new byte[strFaceSnapMatch.dwSnapPicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                if ((strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen > 0) && (strFaceSnapMatch.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + newName + "_struSnapInfo_pBuffer1" + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strFaceSnapMatch.struSnapInfo.pBuffer1.getByteBuffer(offset, strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen);
+                        byte[] bytes = new byte[strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                if ((strFaceSnapMatch.struBlockListInfo.dwBlockListPicLen > 0) && (strFaceSnapMatch.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + newName + "_fSimilarity_" + strFaceSnapMatch.fSimilarity + "_struBlackListInfo_pBuffer1" + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strFaceSnapMatch.struBlockListInfo.pBuffer1.getByteBuffer(offset, strFaceSnapMatch.struBlockListInfo.dwBlockListPicLen);
+                        byte[] bytes = new byte[strFaceSnapMatch.struBlockListInfo.dwBlockListPicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                //人脸比对报警图片保存,图片格式URL格式
+                if ((strFaceSnapMatch.dwSnapPicLen > 0) && (strFaceSnapMatch.byPicTransType == 1)) {
+                    long offset = 0;
+                    ByteBuffer buffers = strFaceSnapMatch.pSnapPicBuffer.getByteBuffer(offset, strFaceSnapMatch.dwSnapPicLen);
+                    byte[] bytes = new byte[strFaceSnapMatch.dwSnapPicLen];
+                    buffers.rewind();
+                    buffers.get(bytes);
+                    String SnapPicUrl = new String(bytes);
+                    logger.info("抓拍图URL:" + SnapPicUrl);
+                }
+                if ((strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen > 0) && (strFaceSnapMatch.byPicTransType == 1)) {
+                    long offset = 0;
+                    ByteBuffer buffers = strFaceSnapMatch.struSnapInfo.pBuffer1.getByteBuffer(offset, strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen);
+                    byte[] bytes = new byte[strFaceSnapMatch.struSnapInfo.dwSnapFacePicLen];
+                    buffers.rewind();
+                    buffers.get(bytes);
+                    String SnapPicUrl = new String(bytes);
+                    logger.info("抓拍人脸子图URL:" + SnapPicUrl);
+                }
+                if ((strFaceSnapMatch.struBlockListInfo.dwBlockListPicLen > 0) && (strFaceSnapMatch.byPicTransType == 1)) {
+                    long offset = 0;
+                    ByteBuffer buffers = strFaceSnapMatch.struBlockListInfo.pBuffer1.getByteBuffer(offset, strFaceSnapMatch.struBlockListInfo.dwBlockListPicLen);
+                    byte[] bytes = new byte[strFaceSnapMatch.struBlockListInfo.dwBlockListPicLen];
+                    buffers.rewind();
+                    buffers.get(bytes);
+                    String SnapPicUrl = new String(bytes);
+                    logger.info("人脸库人脸图的URL:" + SnapPicUrl);
+                }
+                break;
+
+            case HCNetSDK.COMM_THERMOMETRY_ALARM:  //温度报警信息
+                HCNetSDK.NET_DVR_THERMOMETRY_ALARM struTemInfo = new HCNetSDK.NET_DVR_THERMOMETRY_ALARM();
+                struTemInfo.write();
+                Pointer pTemInfo = struTemInfo.getPointer();
+                pTemInfo.write(0, pAlarmInfo.getByteArray(0, struTemInfo.size()), 0, struTemInfo.size());
+                struTemInfo.read();
+                String sThermAlarmInfo = "规则ID:" + struTemInfo.byRuleID + "预置点号:" + struTemInfo.wPresetNo + "报警等级:" + struTemInfo.byAlarmLevel + "报警类型:" +
+                        struTemInfo.byAlarmType + "当前温度:" + struTemInfo.fCurrTemperature;
+                logger.info(sThermAlarmInfo);
+                //可见光图片保存
+                if ((struTemInfo.dwPicLen > 0) && (struTemInfo.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+
+                    try {
+                        String filename = "./pic/" + newName + "_" + struTemInfo.fCurrTemperature + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = struTemInfo.pPicBuff.getByteBuffer(offset, struTemInfo.dwPicLen);
+                        byte[] bytes = new byte[struTemInfo.dwPicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                if ((struTemInfo.dwThermalPicLen > 0) && (struTemInfo.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+
+                    try {
+                        String filename = "./pic/" + newName + "_" + "_ThermalPiC" + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = struTemInfo.pThermalPicBuff.getByteBuffer(offset, struTemInfo.dwThermalPicLen);
+                        byte[] bytes = new byte[struTemInfo.dwThermalPicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_THERMOMETRY_DIFF_ALARM: //温差检测报警
+                HCNetSDK.NET_DVR_THERMOMETRY_DIFF_ALARM strThermDiffAlarm = new HCNetSDK.NET_DVR_THERMOMETRY_DIFF_ALARM();
+                strThermDiffAlarm.write();
+                Pointer pTemDiffInfo = strThermDiffAlarm.getPointer();
+                pTemDiffInfo.write(0, pAlarmInfo.getByteArray(0, strThermDiffAlarm.size()), 0, strThermDiffAlarm.size());
+                strThermDiffAlarm.read();
+                String sThremDiffInfo = "通道号:" + strThermDiffAlarm.dwChannel + ",报警规则:" + strThermDiffAlarm.byAlarmRule + ",当前温差:" + strThermDiffAlarm.fCurTemperatureDiff;
+                logger.info(sThremDiffInfo);
+                //可见光图片保存
+                if ((strThermDiffAlarm.dwPicLen > 0) && (strThermDiffAlarm.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+
+                    try {
+                        String filename = "./pic/" + newName + "_" + strThermDiffAlarm.fCurTemperatureDiff + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strThermDiffAlarm.pPicBuff.getByteBuffer(offset, strThermDiffAlarm.dwPicLen);
+                        byte[] bytes = new byte[strThermDiffAlarm.dwPicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                //热成像图片保存
+                if ((strThermDiffAlarm.dwThermalPicLen > 0) && (strThermDiffAlarm.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+
+                    try {
+                        String filename = "./pic/" + newName + "_" + "_ThermalDiffPiC" + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strThermDiffAlarm.pThermalPicBuff.getByteBuffer(offset, strThermDiffAlarm.dwThermalPicLen);
+                        byte[] bytes = new byte[strThermDiffAlarm.dwThermalPicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_ALARM_SHIPSDETECTION: //船只检测报警
+                HCNetSDK.NET_DVR_SHIPSDETECTION_ALARM struShipAlarm = new HCNetSDK.NET_DVR_SHIPSDETECTION_ALARM();
+                struShipAlarm.write();
+                Pointer pShipAlarm = struShipAlarm.getPointer();
+                pShipAlarm.write(0, pAlarmInfo.getByteArray(0, struShipAlarm.size()), 0, struShipAlarm.size());
+                struShipAlarm.read();
+                String sShipAlarm = "绝对时间:" + struShipAlarm.dwAbsTime + ",正跨越检测线的船只数:" + struShipAlarm.byShipsNum + ",船头检测的船只数 :" + struShipAlarm.byShipsNumHead
+                        + ", 船尾检测的船只数 :" + struShipAlarm.byShipsNumEnd;
+                logger.info(sShipAlarm);
+                //可见光图片保存
+                if ((struShipAlarm.dwPicLen > 0) && (struShipAlarm.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+
+                    try {
+                        String filename = "./pic/" + newName + "_ShipAlarm" + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = struShipAlarm.pPicBuffer.getByteBuffer(offset, struShipAlarm.dwPicLen);
+                        byte[] bytes = new byte[struShipAlarm.dwPicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                //热成像图片保存
+                if ((struShipAlarm.dwThermalPicLen > 0) && (struShipAlarm.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+
+                    try {
+                        String filename = "./pic/" + newName + "_" + "_ThermalShipAlarm" + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = struShipAlarm.pThermalPicBuffer.getByteBuffer(offset, struShipAlarm.dwThermalPicLen);
+                        byte[] bytes = new byte[struShipAlarm.dwThermalPicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_FIREDETECTION_ALARM://烟火检测
+                HCNetSDK.NET_DVR_FIREDETECTION_ALARM struFireDecAlarm = new HCNetSDK.NET_DVR_FIREDETECTION_ALARM();
+                struFireDecAlarm.write();
+                Pointer pFireDecAlarm = struFireDecAlarm.getPointer();
+                pFireDecAlarm.write(0, pAlarmInfo.getByteArray(0, struFireDecAlarm.size()), 0, struFireDecAlarm.size());
+                struFireDecAlarm.read();
+                String sFireDecAlarmInfo = "绝对时间:" + struFireDecAlarm.dwAbsTime + ",报警子类型:" + struFireDecAlarm.byAlarmSubType + ",火点最高温度 :" +
+                        struFireDecAlarm.wFireMaxTemperature + ",火点目标距离:" + struFireDecAlarm.wTargetDistance;
+                logger.info(sFireDecAlarmInfo);
+                //可见光图片保存
+                if ((struFireDecAlarm.dwVisiblePicLen > 0) && (struFireDecAlarm.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+
+                    try {
+                        String filename = "./pic/" + newName + "_FireDecAlarm" + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = struFireDecAlarm.pVisiblePicBuf.getByteBuffer(offset, struFireDecAlarm.dwVisiblePicLen);
+                        byte[] bytes = new byte[struFireDecAlarm.dwVisiblePicLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                //热成像图片保存
+                if ((struFireDecAlarm.dwPicDataLen > 0) && (struFireDecAlarm.byPicTransType == 0)) {
+                    SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
+                    String newName = sf.format(new Date());
+                    FileOutputStream fout;
+
+                    try {
+                        String filename = "./pic/" + newName + "_" + "_ThermalFireAlarm" + ".jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = struFireDecAlarm.pBuffer.getByteBuffer(offset, struFireDecAlarm.dwPicDataLen);
+                        byte[] bytes = new byte[struFireDecAlarm.dwPicDataLen];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_UPLOAD_AIOP_VIDEO: //AI开放平台接入视频检测报警信息
+                logger.info("AI开放平台接入视频检测报警上传");
+                HCNetSDK.NET_AIOP_VIDEO_HEAD struAIOPVideo = new HCNetSDK.NET_AIOP_VIDEO_HEAD();
+                struAIOPVideo.write();
+                Pointer pAIOPVideo = struAIOPVideo.getPointer();
+                pAIOPVideo.write(0, pAlarmInfo.getByteArray(0, struAIOPVideo.size()), 0, struAIOPVideo.size());
+                struAIOPVideo.read();
+                logger.info("视频任务ID" + new String(struAIOPVideo.szTaskID));
+                logger.info("通道号:" + struAIOPVideo.dwChannel);
+                logger.info("检测模型包ID" + new String(struAIOPVideo.szMPID));
+                String strTime = String.format("%04d", struAIOPVideo.struTime.wYear) +
+                        String.format("%02d", struAIOPVideo.struTime.wMonth) +
+                        String.format("%02d", struAIOPVideo.struTime.wDay) +
+                        String.format("%02d", struAIOPVideo.struTime.wHour) +
+                        String.format("%02d", struAIOPVideo.struTime.wMinute) +
+                        String.format("%02d", struAIOPVideo.struTime.wSecond) +
+                        String.format("%03d", struAIOPVideo.struTime.wMilliSec);
+                //AIOPData数据
+                if (struAIOPVideo.dwAIOPDataSize > 0) {
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + new String(pAlarmer.sDeviceIP).trim() +
+                                "_" + strTime + "_VideoData.json";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = struAIOPVideo.pBufferAIOPData.getByteBuffer(offset, struAIOPVideo.dwAIOPDataSize);
+                        byte[] bytes = new byte[struAIOPVideo.dwAIOPDataSize];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                // 图片数据保存
+                if (struAIOPVideo.dwPictureSize > 0) {
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + new String(pAlarmer.sDeviceIP).trim() +
+                                "_" + strTime + "_VideoPic.jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = struAIOPVideo.pBufferPicture.getByteBuffer(offset, struAIOPVideo.dwPictureSize);
+                        byte[] bytes = new byte[struAIOPVideo.dwPictureSize];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            case HCNetSDK.COMM_UPLOAD_AIOP_PICTURE: //AI开放平台接入图片检测报警信息
+                logger.info("AI开放平台接入图片检测报警上传");
+                HCNetSDK.NET_AIOP_PICTURE_HEAD struAIOPPic = new HCNetSDK.NET_AIOP_PICTURE_HEAD();
+                struAIOPPic.write();
+                Pointer pAIOPPic = struAIOPPic.getPointer();
+                pAIOPPic.write(0, pAlarmInfo.getByteArray(0, struAIOPPic.size()), 0, struAIOPPic.size());
+                struAIOPPic.read();
+                logger.info("图片ID:" + new String(struAIOPPic.szPID));
+                logger.info("检测模型包ID:" + new String(struAIOPPic.szMPID));
+                String strPicTime = "" + String.format("%04d", struAIOPPic.struTime.wYear) +
+                        String.format("%02d", struAIOPPic.struTime.wMonth) +
+                        String.format("%02d", struAIOPPic.struTime.wDay) +
+                        String.format("%02d", struAIOPPic.struTime.wHour) +
+                        String.format("%02d", struAIOPPic.struTime.wMinute) +
+                        String.format("%02d", struAIOPPic.struTime.wSecond) +
+                        String.format("%03d", struAIOPPic.struTime.wMilliSec);
+                //AIOPData数据
+                if (struAIOPPic.dwAIOPDataSize > 0) {
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + new String(pAlarmer.sDeviceIP).trim() +
+                                "_" + strPicTime + "_AIO_PicData.json";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = struAIOPPic.pBufferAIOPData.getByteBuffer(offset, struAIOPPic.dwAIOPDataSize);
+                        byte[] bytes = new byte[struAIOPPic.dwAIOPDataSize];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            // AI开放平台接入轮询抓图检测报警信息
+            case HCNetSDK.COMM_UPLOAD_AIOP_POLLING_SNAP:
+                logger.info("AI开放平台接入轮询抓图检测报警事件上传");
+                HCNetSDK.NET_AIOP_POLLING_SNAP_HEAD strAiopPollingPic = new HCNetSDK.NET_AIOP_POLLING_SNAP_HEAD();
+                strAiopPollingPic.write();
+                Pointer pAiopPollingPic = strAiopPollingPic.getPointer();
+                pAiopPollingPic.write(0, pAlarmInfo.getByteArray(0, strAiopPollingPic.size()), 0, strAiopPollingPic.size());
+                strAiopPollingPic.read();
+                logger.info("通道号:" + strAiopPollingPic.dwChannel);
+                logger.info("轮询抓图任务ID:" + new String(strAiopPollingPic.szTaskID));
+                String strPollingPicTime = "" + String.format("%04d", strAiopPollingPic.struTime.wYear) +
+                        String.format("%02d", strAiopPollingPic.struTime.wMonth) +
+                        String.format("%02d", strAiopPollingPic.struTime.wDay) +
+                        String.format("%02d", strAiopPollingPic.struTime.wHour) +
+                        String.format("%02d", strAiopPollingPic.struTime.wMinute) +
+                        String.format("%02d", strAiopPollingPic.struTime.wSecond) +
+                        String.format("%03d", strAiopPollingPic.struTime.wMilliSec);
+                //AIOPData数据保存
+                if (strAiopPollingPic.dwAIOPDataSize > 0) {
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + new String(pAlarmer.sDeviceIP).trim() +
+                                "_" + strPollingPicTime + "_PollingPicData.json";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strAiopPollingPic.pBufferAIOPData.getByteBuffer(offset, strAiopPollingPic.dwAIOPDataSize);
+                        byte[] bytes = new byte[strAiopPollingPic.dwAIOPDataSize];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                //轮询抓图图片保存
+                if (strAiopPollingPic.dwPictureSize > 0) {
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + new String(pAlarmer.sDeviceIP).trim() +
+                                "_" + strPollingPicTime + "_PollingPic.jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strAiopPollingPic.pBufferPicture.getByteBuffer(offset, strAiopPollingPic.dwPictureSize);
+                        byte[] bytes = new byte[strAiopPollingPic.dwPictureSize];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+
+                break;
+            // AI开放平台接入轮询视频检测报警信息
+            case HCNetSDK.COMM_UPLOAD_AIOP_POLLING_VIDEO:
+                logger.info("AI开放平台接入轮询视频检测报警事件上传");
+                HCNetSDK.NET_AIOP_POLLING_VIDEO_HEAD strAiopPollingVideo = new HCNetSDK.NET_AIOP_POLLING_VIDEO_HEAD();
+                strAiopPollingVideo.write();
+                Pointer pAiopPollingVideo = strAiopPollingVideo.getPointer();
+                pAiopPollingVideo.write(0, pAlarmInfo.getByteArray(0, strAiopPollingVideo.size()), 0, strAiopPollingVideo.size());
+                strAiopPollingVideo.read();
+                logger.info("通道号:" + strAiopPollingVideo.dwChannel);
+                logger.info("轮询视频任务ID:" + new String(strAiopPollingVideo.szTaskID));
+                String AiopPollingVideoTime = "" + String.format("%04d", strAiopPollingVideo.struTime.wYear) +
+                        String.format("%02d", strAiopPollingVideo.struTime.wMonth) +
+                        String.format("%02d", strAiopPollingVideo.struTime.wDay) +
+                        String.format("%02d", strAiopPollingVideo.struTime.wHour) +
+                        String.format("%02d", strAiopPollingVideo.struTime.wMinute) +
+                        String.format("%02d", strAiopPollingVideo.struTime.wSecond) +
+                        String.format("%03d", strAiopPollingVideo.struTime.wMilliSec);
+                //AIOPData数据保存
+                if (strAiopPollingVideo.dwAIOPDataSize > 0) {
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + new String(pAlarmer.sDeviceIP).trim() +
+                                "_" + AiopPollingVideoTime + "_PollingVideoData.json";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strAiopPollingVideo.pBufferAIOPData.getByteBuffer(offset, strAiopPollingVideo.dwAIOPDataSize);
+                        byte[] bytes = new byte[strAiopPollingVideo.dwAIOPDataSize];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                //对应分析图片数据
+                if (strAiopPollingVideo.dwPictureSize > 0) {
+                    FileOutputStream fout;
+                    try {
+                        String filename = "./pic/" + new String(pAlarmer.sDeviceIP).trim() +
+                                "_" + AiopPollingVideoTime + "_PollingVideo.jpg";
+                        fout = new FileOutputStream(filename);
+                        //将字节写入文件
+                        long offset = 0;
+                        ByteBuffer buffers = strAiopPollingVideo.pBufferPicture.getByteBuffer(offset, strAiopPollingVideo.dwPictureSize);
+                        byte[] bytes = new byte[strAiopPollingVideo.dwPictureSize];
+                        buffers.rewind();
+                        buffers.get(bytes);
+                        fout.write(bytes);
+                        fout.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                break;
+            default:
+                logger.info("报警类型" + Integer.toHexString(lCommand));
+                break;
+        }
+    }
+}

+ 23 - 0
supervision-admin/src/main/java/com/supervision/web/ConnectSDK/peopleDoor/alarm/PeopleDoorFMSGCallBack_V31.java

@@ -0,0 +1,23 @@
+package com.supervision.web.ConnectSDK.peopleDoor.alarm;
+
+
+import com.sun.jna.Pointer;
+import com.supervision.web.ConnectSDK.peopleDoor.NetSDKDemo.HCNetSDK;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PeopleDoorFMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {
+
+    // 报警信息回调函数
+    @Override
+    public boolean invoke(
+            int lCommand, // lCommand [out] 上传的消息类型,不同的报警信息对应不同的类型,通过类型区分是什么报警信息,详见“Remarks”中列表
+            HCNetSDK.NET_DVR_ALARMER pAlarmer, // pAlarmer [out] 报警设备信息,包括设备序列号、IP地址、登录IUserID句柄等
+            Pointer pAlarmInfo, // pAlarmInfo [out] 报警信息,通过lCommand值判断pAlarmer对应的结构体,详见“Remarks”中列表
+            int dwBufLen, // dwBufLen [out] 报警信息缓存大小
+            Pointer pUser // pUser[out] 用户数据
+    ) {
+        PeopleDoorAlarmDataParse.alarmDataHandle(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser);
+        return true;
+    }
+}