浏览代码

提交异常识别数据到后台

qzy 8 月之前
父节点
当前提交
8f67ee2af4
共有 68 个文件被更改,包括 1369 次插入350 次删除
  1. 60 27
      config.xml
  2. 7 0
      pom.xml
  3. 44 22
      src/main/java/com/gzlh/api/OpenApi.java
  4. 49 22
      src/main/java/com/gzlh/background/BackgroundClientHandler.java
  5. 6 0
      src/main/java/com/gzlh/bus/CenterActionCommand.java
  6. 20 13
      src/main/java/com/gzlh/bus/ChannelCacheManager.java
  7. 10 8
      src/main/java/com/gzlh/bus/EventThread.java
  8. 53 0
      src/main/java/com/gzlh/bus/SubmitCarToLimitServerThread.java
  9. 8 5
      src/main/java/com/gzlh/bus/SubmitHarborPoleThread.java
  10. 14 5
      src/main/java/com/gzlh/bus/SubmitThread.java
  11. 56 7
      src/main/java/com/gzlh/bus/SysConfig.java
  12. 5 0
      src/main/java/com/gzlh/bus/task/CheckState.java
  13. 11 8
      src/main/java/com/gzlh/cache/CacheManager.java
  14. 8 0
      src/main/java/com/gzlh/cache/PassCacheManager.java
  15. 1 1
      src/main/java/com/gzlh/cache/SubmitCache.java
  16. 1 0
      src/main/java/com/gzlh/config/ModuleEnum.java
  17. 3 0
      src/main/java/com/gzlh/config/dto/ApplicationConfigDTO.java
  18. 36 0
      src/main/java/com/gzlh/config/dto/Face.java
  19. 0 23
      src/main/java/com/gzlh/config/dto/FaceDTO.java
  20. 4 2
      src/main/java/com/gzlh/config/dto/FaceListDTO.java
  21. 15 0
      src/main/java/com/gzlh/config/dto/PassportSetting.java
  22. 5 0
      src/main/java/com/gzlh/config/dto/SerialSetting.java
  23. 5 7
      src/main/java/com/gzlh/config/hksdk/AlarmParseService.java
  24. 3 0
      src/main/java/com/gzlh/config/properties/ExternalProperties.java
  25. 4 0
      src/main/java/com/gzlh/device/capture/action/ICaptureAction.java
  26. 4 0
      src/main/java/com/gzlh/device/capture/event/CaptureEvent.java
  27. 2 0
      src/main/java/com/gzlh/device/capture/handler/impl/CaptureHandlerHk.java
  28. 15 2
      src/main/java/com/gzlh/device/capture/service/CaptureHandlerService.java
  29. 8 1
      src/main/java/com/gzlh/device/capture/task/HandlerCarImage.java
  30. 7 0
      src/main/java/com/gzlh/device/face/action/FaceAction.java
  31. 6 0
      src/main/java/com/gzlh/device/face/event/FaceEvent.java
  32. 32 0
      src/main/java/com/gzlh/device/face/handler/FaceActionHandler.java
  33. 18 9
      src/main/java/com/gzlh/device/face/hkutils/UserManage.java
  34. 1 1
      src/main/java/com/gzlh/device/face/hkutils/transIsapi.java
  35. 47 35
      src/main/java/com/gzlh/device/face/service/FaceService.java
  36. 4 4
      src/main/java/com/gzlh/device/face/service/LoginFaceGate.java
  37. 5 5
      src/main/java/com/gzlh/device/face/task/CheckFaceGateOnlineTask.java
  38. 10 0
      src/main/java/com/gzlh/device/face/task/NoticeCustomersThread.java
  39. 104 0
      src/main/java/com/gzlh/device/face/task/SubmitFaceToLimitServerThread.java
  40. 5 0
      src/main/java/com/gzlh/device/led/handler/impl/LedHandlerFengLiYuan.java
  41. 28 0
      src/main/java/com/gzlh/device/led/task/NotifyToServer.java
  42. 2 1
      src/main/java/com/gzlh/device/led/utils/CRC16.java
  43. 73 0
      src/main/java/com/gzlh/device/passport/PassportReadClient.java
  44. 32 0
      src/main/java/com/gzlh/device/passport/barnd/PassportEventType.java
  45. 15 0
      src/main/java/com/gzlh/device/passport/domain/PackageJson.java
  46. 18 0
      src/main/java/com/gzlh/device/passport/factory/PassportEventHandlerFactory.java
  47. 31 0
      src/main/java/com/gzlh/device/passport/handler/IPassportEventHandler.java
  48. 36 0
      src/main/java/com/gzlh/device/passport/handler/impl/ZAPassportEventHandler.java
  49. 8 0
      src/main/java/com/gzlh/device/plc/action/PLCAction.java
  50. 63 33
      src/main/java/com/gzlh/device/plc/handler/PLCHadnler.java
  51. 1 1
      src/main/java/com/gzlh/device/plc/job/CheckStartWeightTask.java
  52. 13 25
      src/main/java/com/gzlh/device/plc/service/PLCService.java
  53. 2 1
      src/main/java/com/gzlh/device/rfid/brand/ElectronBrandType.java
  54. 3 4
      src/main/java/com/gzlh/device/rfid/handler/impl/WanQuanHandler.java
  55. 110 0
      src/main/java/com/gzlh/device/rfid/handler/impl/ZKRfidHandler.java
  56. 8 3
      src/main/java/com/gzlh/device/rfid/job/ElectronReadJob.java
  57. 4 10
      src/main/java/com/gzlh/device/rfid/service/RfidService.java
  58. 2 1
      src/main/java/com/gzlh/device/rfid/utils/RFIDCommandUtils.java
  59. 64 22
      src/main/java/com/gzlh/device/weighbridge/handler/impl/CommonWeighbridgeHandler.java
  60. 0 17
      src/main/java/com/gzlh/device/weighbridge/handler/impl/WeighbridgeHandlerTuoLiDuo.java
  61. 6 1
      src/main/java/com/gzlh/entity/AddFaceBO.java
  62. 14 0
      src/main/java/com/gzlh/entity/CarCaptureBO.java
  63. 16 3
      src/main/java/com/gzlh/entity/ReqBO.java
  64. 16 17
      src/main/java/com/gzlh/startup/StartupRunner.java
  65. 96 0
      src/main/java/com/gzlh/utils/CRC16Util.java
  66. 1 1
      src/main/java/com/gzlh/utils/DeviceCache.java
  67. 6 0
      src/main/java/com/gzlh/utils/FileUtils.java
  68. 5 3
      src/main/resources/application.yml

+ 60 - 27
config.xml

@@ -3,7 +3,7 @@
 <config>
     <managerSetting>
         <enable>true</enable>
-        <host>10.5.36.109</host>
+        <host>192.168.3.15</host>
         <beatPort>8010</beatPort>
         <serverUrl>http://127.0.0.1:9191</serverUrl>
     </managerSetting>
@@ -12,36 +12,38 @@
         <!--本机IP-->
         <ip>10.5.1.93</ip>
         <channelName>铁山港2#地磅</channelName>
-        <channelCode>TSI2-B</channelCode>
+        <channelCode>TSN5</channelCode>
         <twinChannelCode>TSI2-A</twinChannelCode>
         <!--共生通道地址-->
         <twinService>http://127.0.0.1:9898</twinService>
-        <!--0 货运通道 1 行政通道 2 港内称重-->
+        <!--0 货运通道 1 行政通道 2 港内称重-3行人通道-->
         <channelType>2</channelType>
         <!--车牌保存路径-->
         <fileRootPath>D:\\file</fileRootPath>
     </channelSetting>
     <!--设备相关设置-->
     <faceConfig>
-        <enable>true</enable>
-        <face>
-            <channelCode>01</channelCode>
-            <ip>192.168.1.1</ip>
-            <port>8000</port>
-            <uname>admin</uname>
-            <pwd>ABCabc124</pwd>
-        </face>
-        <face>
-            <channelCode>02</channelCode>
-            <ip>192.168.1.1</ip>
-            <port>8000</port>
-            <uname>admin</uname>
-            <pwd>ABCabc124</pwd>
-        </face>
+        <enable>false</enable>
+        <faceList>
+            <face>
+                <channelCode>01</channelCode>
+                <ip>192.0.0.64</ip>
+                <port>8000</port>
+                <uname>admin</uname>
+                <pwd>ABCabc124</pwd>
+                <userId>ABCabc124</userId>
+                <online>false</online>
+            </face>
+        </faceList>
     </faceConfig>
+    <passport>
+        <enable>true</enable>
+        <host>127.0.0.1</host>
+        <port>90</port>
+    </passport>
     <sysConfig>
         <caputreSetting>
-            <enable>true</enable>
+            <enable>false</enable>
             <brand>5000</brand>
             <host>10.5.36.112</host>
             <port>8000</port>
@@ -50,26 +52,26 @@
         </caputreSetting>
         <!--串口服务器地址-->
         <serialSetting>
-            <host>10.5.36.111</host>
+            <host>192.168.127.254</host>
             <weighbridge>
-                <enable>true</enable>
+                <enable>false</enable>
                 <port>4003</port>
                 <brand>3000</brand>
                 <minKg>1000</minKg>
                 <module>10</module>
             </weighbridge>
             <led>
-                <enable>true</enable>
+                <enable>false</enable>
                 <port>4002</port>
                 <brand>2000</brand>
             </led>
             <electron>
-                <enable>true</enable>
-                <port>4004</port>
-                <brand>3000</brand>
+                <enable>false</enable>
+                <port>4001</port>
+                <brand>4000</brand>
             </electron>
             <print>
-                <enable>true</enable>
+                <enable>false</enable>
                 <ip>10.5.36.113</ip>
                 <port>9100</port>
                 <brand>1000</brand>
@@ -80,6 +82,7 @@
                 <!--输出-->
                 <out>
                     <gatePoint>00</gatePoint>
+                    <downGatePoint>01</downGatePoint>
                     <signalRedPoint>02</signalRedPoint>
                     <signalGreenPoint>03</signalGreenPoint>
                 </out>
@@ -93,6 +96,8 @@
                     <radarPoint>2</radarPoint>
                     <!--前红外-->
                     <fRedPoint>3</fRedPoint>
+                    <!--1正常,-1是相反-->
+                    <infraredMode>-1</infraredMode>
                     <!--后红外-->
                     <bRedPoint>4</bRedPoint>
                     <!--打印榜单-->
@@ -142,6 +147,20 @@
             </actionList>
         </event>
         <event>
+            <!--识别到车牌-->
+            <name>CAPTURE.IDENTIFY_FAIL</name>
+            <actionList>
+                <action>CAPTURE.SUBMIT_ERROR</action>
+            </actionList>
+        </event>
+        <event>
+            <!--识别到车牌-->
+            <name>CAPTURE.CAPTURE_ADMIN</name>
+            <actionList>
+                <action>CAPTURE.SUBMIT_CAR_LIMIT_SERVER</action>
+            </actionList>
+        </event>
+        <event>
             <!--车辆进入通道-->
             <name>PLC.CAR_ENTER</name>
             <actionList>
@@ -177,7 +196,7 @@
             <name>PLC.RAILING_RISE</name>
             <actionList>
                 <action>PLC.RAILING_RISE_ON</action>
-                <action>CENTER.TIMER_SLEEP(100)</action>
+                <action>CENTER.TIMER_SLEEP(1000)</action>
                 <action>PLC.RAILING_RISE_OFF</action>
             </actionList>
         </event>
@@ -225,5 +244,19 @@
                 <action>PLC.RAILING_RISE_OFF</action>
             </actionList>
         </event>
+        <event>
+            <name>FACE.FACE_RESULT</name>
+            <actionList>
+                <action>FACE.FACE_RESULT</action>
+            </actionList>
+        </event>
+        <event>
+            <name>PLC.GATE_DOWN</name>
+            <actionList>
+                <action>PLC.GATE_DOWN</action>
+                <action>CENTER.TIMER_SLEEP(1000)</action>
+                <action>PLC.RELEASE_GATE_DOWN</action>
+            </actionList>
+        </event>
     </eventList>
 </config>

+ 7 - 0
pom.xml

@@ -55,6 +55,11 @@
             <version>20.0</version>
         </dependency>
         <dependency>
+            <groupId>org.java-websocket</groupId>
+            <artifactId>Java-WebSocket</artifactId>
+            <version>1.5.3</version>
+        </dependency>
+        <dependency>
             <groupId>com.sun.jna</groupId>
             <artifactId>jna</artifactId>
             <version>3.0.9</version>
@@ -153,6 +158,8 @@
 <!--                    <code>AE135DDFE7E3871BE848301327CA8E2ED41D8CD98F00B204E9800998ECF8427ED41D8CD98F00B204E9800998ECF8427E</code>-->
                     <!--北海-->
                     <code>AE135DDFE7E3871BE848301327CA8E2ED41D8CD98F00B204E9800998ECF8427ED41D8CD98F00B204E9800998ECF8427E</code>
+                    <!--限定区域-->
+<!--                    <code>C41BF0CE8FF4E89D45E95A3AFB46E2E9D41D8CD98F00B204E9800998ECF8427ED41D8CD98F00B204E9800998ECF8427E</code>-->
                     <packages>com.gzlh</packages> <!--可以多个-->
                     <!--                    <cfgfiles>application.yml</cfgfiles>-->
                     <excludes>org.spring</excludes>

+ 44 - 22
src/main/java/com/gzlh/api/OpenApi.java

@@ -7,21 +7,27 @@ import cn.hutool.log.StaticLog;
 import com.gzlh.background.BackgroundClientNetty;
 import com.gzlh.bus.EventDataManager;
 import com.gzlh.bus.SysConfig;
+import com.gzlh.cache.PassCacheManager;
 import com.gzlh.config.ModuleEnum;
 import com.gzlh.bus.EventBus;
 import com.gzlh.config.SystemObject;
-import com.gzlh.config.dto.FaceDTO;
+import com.gzlh.config.dto.Face;
 import com.gzlh.config.dto.SerialSetting;
 import com.gzlh.constans.AjaxJson;
-import com.gzlh.device.face.FaceService;
-import com.gzlh.device.face.UserManage;
+import com.gzlh.device.face.service.FaceService;
+import com.gzlh.device.face.hkutils.UserManage;
+import com.gzlh.device.led.client.LedNettyConfig;
+import com.gzlh.device.plc.client.PlcNettyConfig;
+import com.gzlh.device.plc.event.PLCEvent;
 import com.gzlh.device.rfid.job.ElectronReadJob;
 import com.gzlh.device.led.event.LedDefaultEvent;
 import com.gzlh.device.led.utils.LedOptions;
 import com.gzlh.entity.AddFaceBO;
 import com.gzlh.entity.ReqBO;
+import com.gzlh.utils.ModbusUtils;
 import com.gzlh.utils.ResultJson;
 import com.gzlh.device.weighbridge.event.WeighbridgeEvent;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -39,12 +45,36 @@ public class OpenApi {
     @Resource
     private UserManage userManage;
 
-
     @Resource
     EventBus eventBus;
 
     @Resource
     private BackgroundClientNetty backgroundClientNetty;
+    @Resource
+    private PlcNettyConfig plcNettyConfig;
+
+    public static final String COMMAND_PREFIX = "010500";
+    public static final String COMMAND_ON = "FF00";
+    public static final String COMMAND_OFF = "0000";
+    @RequestMapping("channel/up")
+    public AjaxJson action() {
+        eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.RAILING_RISE);
+        return AjaxJson.getSuccess();
+    }
+    @RequestMapping("channel/down")
+    public AjaxJson down() {
+        eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.DOWN_POINT_READ);
+        return AjaxJson.getSuccess();
+    }
+
+    @RequestMapping("channel/led")
+    public AjaxJson led(String msg, String line) {
+        LedOptions options = new LedOptions().setLine("0" + line).setShowType("00");
+        SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
+                .sendMsg(msg, options);
+        return AjaxJson.getSuccess();
+    }
+
 
     @RequestMapping("test")
     public ResultJson test(String msg, String line, String showType, String color) {
@@ -85,11 +115,11 @@ public class OpenApi {
 
     @RequestMapping("face/add")
     public AjaxJson addFace(@RequestBody AddFaceBO faceBO) throws Exception {
-        List<FaceDTO> faceDTOList = SysConfig.faceDTO.getFace()
+        List<Face> faceDTOList = SysConfig.faceDTO.getFaceList()
                 .stream().filter(dto -> dto.getChannelCode().equals(faceBO.getChannelCode()))
                 .collect(Collectors.toList());
-        for (FaceDTO faceDTO : faceDTOList) {
-            userManage.AddUserInfo(faceDTO.getUserId(), faceBO.getNo(), faceBO.getName());
+        for (Face faceDTO : faceDTOList) {
+            userManage.AddUserInfo(faceDTO.getUserId(), faceBO);
             faceService.AddFaceByBinary(faceDTO.getUserId(), faceBO.getNo(), faceBO.getBase64());
         }
 
@@ -98,27 +128,19 @@ public class OpenApi {
 
     @RequestMapping("face/del")
     public AjaxJson delFace(@RequestBody AddFaceBO faceBO) {
-        List<FaceDTO> faceDTOList = SysConfig.faceDTO.getFace()
+        List<Face> faceDTOList = SysConfig.faceDTO.getFaceList()
                 .stream().filter(dto -> dto.getChannelCode().equals(faceBO.getChannelCode()))
                 .collect(Collectors.toList());
-        for (FaceDTO faceDTO : faceDTOList) {
+        for (Face faceDTO : faceDTOList) {
             userManage.deleteUserInfo(faceDTO.getUserId(), faceBO.getNo());
         }
         return AjaxJson.getSuccess();
     }
 
-    /**
-     * 远程控门
-     *
-     * @param userID
-     */
-    public AjaxJson RemoteControlGate(@RequestBody AddFaceBO faceBO) {
-        List<FaceDTO> faceDTOList = SysConfig.faceDTO.getFace()
-                .stream().filter(dto -> dto.getChannelCode().equals(faceBO.getChannelCode()))
-                .collect(Collectors.toList());
-        for (FaceDTO faceDTO : faceDTOList) {
-            faceService.RemoteControlGate(faceDTO.getUserId(), faceBO.getCommand());
-        }
-        return AjaxJson.getSuccess();
+    @RequestMapping("channel/askResult")
+    public AjaxJson askCustomResult() {
+        return AjaxJson.getSuccessData(PassCacheManager.customerPass);
     }
+
+
 }

+ 49 - 22
src/main/java/com/gzlh/background/BackgroundClientHandler.java

@@ -3,17 +3,24 @@ package com.gzlh.background;
 import cn.hutool.cache.CacheUtil;
 import cn.hutool.cache.impl.TimedCache;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
 import cn.hutool.json.JSONUtil;
 import com.gzlh.bus.EventBus;
+import com.gzlh.bus.EventDataManager;
 import com.gzlh.bus.SysConfig;
 import com.gzlh.config.ModuleEnum;
 import com.gzlh.config.SystemObject;
 import com.gzlh.config.dto.CaputreSetting;
+import com.gzlh.config.dto.SerialSetting;
 import com.gzlh.config.hksdk.HCNetSDK;
 import com.gzlh.config.hksdk.HkUtils;
 import com.gzlh.config.hksdk.bo.HKCacheManager;
+import com.gzlh.device.capture.action.ICaptureAction;
 import com.gzlh.device.capture.brand.CaptureBrandType;
+import com.gzlh.device.capture.event.CaptureEvent;
 import com.gzlh.device.led.utils.LedOptions;
+import com.gzlh.device.weighbridge.event.WeighbridgeEvent;
+import com.gzlh.device.weighbridge.handler.impl.CommonWeighbridgeHandler;
 import com.gzlh.entity.CommandBO;
 import com.gzlh.utils.DeviceCache;
 import io.netty.channel.ChannelHandler;
@@ -24,6 +31,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.util.StringUtils;
 
 import javax.annotation.Resource;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -48,13 +56,15 @@ public class BackgroundClientHandler extends SimpleChannelInboundHandler<String>
     @Override
     protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
 //        System.out.println("Client received: " + msg);
-        if (!"back message".equalsIgnoreCase(msg)){
-            log.info("后端 客户端收到的信息:{}",msg);
-           handlerMsg(msg,ctx);
+        if (!"back message".equalsIgnoreCase(msg)) {
+            log.info("后端 客户端收到的信息:{}", msg);
+            handlerMsg(msg, ctx);
         }
     }
+
     TimedCache<String, String> CONTENT_CACHE = CacheUtil.newTimedCache(2000);
-    void handlerMsg(String str,ChannelHandlerContext ctx){
+
+    void handlerMsg(String str, ChannelHandlerContext ctx) {
         String channelId = ctx.channel().id().asShortText();
         if (!StrUtil.endWith(str, "}") && StrUtil.startWith(str, "{")) {
             CONTENT_CACHE.put(channelId, str);
@@ -74,13 +84,30 @@ public class BackgroundClientHandler extends SimpleChannelInboundHandler<String>
         }
         CommandBO commandBO = JSONUtil.toBean(str, CommandBO.class);
         CommandBO.Command command = commandBO.getCommand();
-        if (!StringUtils.isEmpty(command.getExtra())){
-            LedOptions options = new LedOptions().setLine("04").setColor("03").setShowType("00");
+        if (!StringUtils.isEmpty(command.getExtra())) {
+            LedOptions options = new LedOptions().setLine("03").setShowType("00");
             SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
-                    .sendMsg(command.getExtra(),options);
+                    .sendMsg(command.getExtra(), options);
         }
-        if (StrUtil.isNotEmpty(command.getCommand())&&StrUtil.isNotEmpty(command.getModule())){
-            eventBus.startEvent(command.getModule()+"."+command.getCommand());
+        if (StrUtil.isNotEmpty(command.getCommand()) && StrUtil.isNotEmpty(command.getModule())) {
+            if (StrUtil.equals(command.getCommand(), ICaptureAction.BU_CAI_CAR_NO)) {
+                EventDataManager.cacheData("carNo", command.getExtra());
+                EventDataManager.cacheData("gatherTime", new Date());
+                //雷达
+                String plcStatus = DeviceCache.getPlcStatus();
+                SerialSetting.PlcDTO.StatusDTO status = SysConfig.serialSetting.getPlc().getStatus();
+                String radarPoint = status.getRadarPoint();
+                String radarPointStatus = plcStatus.charAt(Integer.parseInt(radarPoint)) + "";
+                EventBus eventBus = SpringUtil.getBean(EventBus.class);
+                if (radarPointStatus.equals("1")) {
+                    log.info("后台补采,开始称重");
+                    eventBus.startEvent(ModuleEnum.WEIGHBRIDGE_MODULE.getModuleEn() + "." + WeighbridgeEvent.READ);
+                }else {
+                    eventBus.startEvent(ModuleEnum.CAPTURE_MODULE.getModuleEn() + "." + CaptureEvent.CAPTURE_CAR_NO);
+                }
+                return;
+            }
+            eventBus.startEvent(command.getModule() + "." + command.getCommand());
         }
     }
 
@@ -88,22 +115,22 @@ public class BackgroundClientHandler extends SimpleChannelInboundHandler<String>
     protected void sendHeartbeat(ChannelHandlerContext context) {
 //        向后台发送设备信息json字符串
 //        获取海康摄像头连接状态
-        CaputreSetting caputreSetting=SysConfig.caputreSetting;
-        if (caputreSetting.getBrand()== CaptureBrandType.HK_BRAND.getCode()){
-            Map<String,Object> captrue = new HashMap<String,Object>();
+        CaputreSetting caputreSetting = SysConfig.caputreSetting;
+        if (caputreSetting.getBrand() == CaptureBrandType.HK_BRAND.getCode()&&caputreSetting.isEnable()) {
+            Map<String, Object> captrue = new HashMap<String, Object>();
             int userId = HKCacheManager.getUserId(ModuleEnum.CAPTURE_MODULE);
             boolean status = hkUtils.getStatus(hcNetSDK, userId);
-            int loginV40=0;
-            if (!status){
-                short port= (short) caputreSetting.getPort();
-                String ip=caputreSetting.getHost();
+            int loginV40 = 0;
+            if (!status) {
+                short port = (short) caputreSetting.getPort();
+                String ip = caputreSetting.getHost();
                 loginV40 = hkUtils.Login_V40(ip, port, caputreSetting.getUsername(), caputreSetting.getPwd(), hcNetSDK);
-                if (loginV40!=-1){
-                    hkUtils.SetAlarm(hcNetSDK,loginV40);
-                    HKCacheManager.add(ModuleEnum.CAPTURE_MODULE,loginV40);
+                if (loginV40 != -1) {
+                    hkUtils.SetAlarm(hcNetSDK, loginV40);
+                    HKCacheManager.add(ModuleEnum.CAPTURE_MODULE, loginV40);
                 }
-             }
-            DeviceCache.changeDeviceStatus(ModuleEnum.CAPTURE_MODULE.getModuleZh(), loginV40!=-1?1:0);
+            }
+            DeviceCache.changeDeviceStatus(ModuleEnum.CAPTURE_MODULE.getModuleZh(), loginV40 != -1 ? 1 : 0);
         }
 
         String jsonStr = DeviceCache.getDeviceStatusJson();
@@ -152,7 +179,7 @@ public class BackgroundClientHandler extends SimpleChannelInboundHandler<String>
     @Override
     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
         cause.printStackTrace();
-       // ctx.close();
+        // ctx.close();
     }
 
     @Override

+ 6 - 0
src/main/java/com/gzlh/bus/CenterActionCommand.java

@@ -12,5 +12,11 @@ public interface CenterActionCommand {
      */
     String SUBMIT_HARBORPOLE = "SUBMIT_HARBORPOLE";
     String FINISH_WEIGHT = "FINISH_WEIGHT";
+    /**
+     * 提交车牌数据给限定区域
+     */
+    String SUBMIT_CAR_LIMIT_SERVER = "SUBMIT_CAR_LIMIT_SERVER";
+
+    String SUBMIT_FACE_LIMIT_SERVER = "SUBMIT_FACE_LIMIT_SERVER";
 
 }

+ 20 - 13
src/main/java/com/gzlh/bus/ChannelCacheManager.java

@@ -7,25 +7,32 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 public class ChannelCacheManager {
-    private final static TimedCache<String,Integer>CACHE= CacheUtil.newTimedCache(8000);
+    private final static TimedCache<String, Integer> CACHE = CacheUtil.newTimedCache(8000);
     private final static Map<String, Integer> STATE_MAP = new ConcurrentHashMap<>();
-    public static void addCache(String cache){
-        CACHE.put(cache,1);
-    }
-    public static boolean checkExit(String cache){
-        return CACHE.get(cache,false)!=null;
+
+    public static void addCache(String cache) {
+        CACHE.put(cache, 1);
     }
-    public static void setStateMap(String code,Integer state){
-        STATE_MAP.put(code,state);
+
+    public static boolean checkExit(String cache) {
+        return CACHE.get(cache, false) != null;
     }
-    public static Integer getStateMap(String code){
-       return STATE_MAP.get(code);
+
+    public static void setStateMap(String code, Integer state) {
+        STATE_MAP.put(code, state);
     }
-    public static boolean stateEnable(String code){
-        Integer state=STATE_MAP.get(code);
-       return state!=null&&state==0;
+
+    public static Integer getStateMap(String code) {
+        return STATE_MAP.get(code);
     }
 
+    public static boolean stateEnable(String code) {
+        Integer state = STATE_MAP.get(code);
+        if (state == null) {
+            return true;
+        }
+        return state == 0;
+    }
 
 
 }

+ 10 - 8
src/main/java/com/gzlh/bus/EventThread.java

@@ -4,26 +4,20 @@ import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.spring.SpringUtil;
-import cn.hutool.http.HttpRequest;
-import cn.hutool.http.HttpResponse;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
 import com.gzlh.config.dto.CaputreSetting;
 import com.gzlh.config.dto.SerialSetting;
 import com.gzlh.device.capture.factory.CaptureFactory;
 import com.gzlh.config.ModuleEnum;
 import com.gzlh.config.SystemObject;
+import com.gzlh.device.face.handler.FaceActionHandler;
+import com.gzlh.device.face.task.SubmitFaceToLimitServerThread;
 import com.gzlh.device.rfid.factory.ElectronFactory;
 
 import com.gzlh.device.led.factory.LedFactory;
-import com.gzlh.device.led.utils.LedOptions;
-import com.gzlh.device.plc.event.PLCEvent;
 import com.gzlh.device.plc.handler.PLCHadnler;
 import com.gzlh.device.weighbridge.factory.WeighbridgeFactory;
 import com.gzlh.device.weighbridge.handler.impl.CommonWeighbridgeHandler;
-import com.gzlh.entity.CommandBO;
 import com.gzlh.utils.DeviceCache;
-import com.gzlh.utils.WordHandlerUtils;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.List;
@@ -81,6 +75,10 @@ public class EventThread implements Runnable {
                         } else if (StrUtil.equals(module, ModuleEnum.ELECTRON_MODULE.getModuleEn())) {
                             //动作属于电子车牌
                             electronFactory.handler(serialSetting.getElectron().getBrand()).handlerAction(command);
+                        }  else if (StrUtil.equals(module, ModuleEnum.FACE_MODULE.getModuleEn())) {
+                            //动作属于人脸
+                            FaceActionHandler faceActionHandler=SpringUtil.getBean(FaceActionHandler.class);
+                            faceActionHandler.handlerAction(command);
                         } else if (StrUtil.equals(module, ModuleEnum.CENTER_MODULE.getModuleEn())) {
                             //动作属于中心总线
                             handlerAction(command);
@@ -108,6 +106,10 @@ public class EventThread implements Runnable {
             handlerHarborpoleSubmit();
         } else if (StrUtil.equalsIgnoreCase(action, CenterActionCommand.FINISH_WEIGHT)) {
             ThreadUtil.execute(new FinishTask());
+        }else if (StrUtil.equalsIgnoreCase(action, CenterActionCommand.SUBMIT_CAR_LIMIT_SERVER)) {
+            ThreadUtil.execute(new SubmitCarToLimitServerThread());
+        }else if (StrUtil.equalsIgnoreCase(action, CenterActionCommand.SUBMIT_FACE_LIMIT_SERVER)) {
+            ThreadUtil.execute(new SubmitFaceToLimitServerThread());
         }
     }
 

+ 53 - 0
src/main/java/com/gzlh/bus/SubmitCarToLimitServerThread.java

@@ -0,0 +1,53 @@
+package com.gzlh.bus;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.gzlh.cache.PassCacheManager;
+import com.gzlh.config.SystemObject;
+import com.gzlh.config.properties.ExternalProperties;
+import com.gzlh.device.led.utils.LedOptions;
+import com.gzlh.entity.CarCaptureBO;
+import com.gzlh.entity.ReqBO;
+import com.gzlh.utils.DeviceCache;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class SubmitCarToLimitServerThread implements Runnable {
+    @Override
+    public void run() {
+        ExternalProperties externalProperties = SpringUtil.getBean(ExternalProperties.class);
+        ReqBO reqBO = EventDataManager.getCacheData();
+        if (reqBO == null || StrUtil.isEmpty(reqBO.getCarNo())) {
+            log.error("Request empty");
+            return;
+        }
+        CarCaptureBO carCaptureBO = new CarCaptureBO();
+        carCaptureBO.setChannelCode(reqBO.getChannelCode()).setCarNo(reqBO.getCarNo())
+                .setCarImage(reqBO.getCarImg())
+                .setIdentifyTime(DateUtil.now());
+        String body = JSONUtil.toJsonStr(carCaptureBO);
+        log.info("submitCarToLimitServerThread: {}", body);
+        String resp = HttpUtil.createPost(externalProperties.getSubCarValidatePath())
+                .body(body).execute().body();
+        log.info("submitCarToLimitServerThread resp: {},{}",externalProperties.getSubCarValidatePath() ,resp);
+        JSONObject result = JSONUtil.parseObj(resp);
+        Integer code = result.getInt("code");
+        LedOptions options = new LedOptions().setLine("03").setShowType("00");
+        if (code != 200) {
+            SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
+                    .sendMsg(result.getStr("msg"), options);
+            PassCacheManager.carPass = false;
+            DeviceCache.setInterrupt(true);
+        } else {
+            SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
+                    .sendMsg("请进行人脸核验", options);
+            PassCacheManager.carPass = true;
+        }
+
+
+    }
+}

+ 8 - 5
src/main/java/com/gzlh/bus/SubmitHarborPoleThread.java

@@ -18,6 +18,8 @@ import com.gzlh.utils.DeviceCache;
 import com.gzlh.utils.WordHandlerUtils;
 import lombok.extern.slf4j.Slf4j;
 
+import java.util.Date;
+
 @Slf4j
 public class SubmitHarborPoleThread implements Runnable {
     @Override
@@ -27,17 +29,18 @@ public class SubmitHarborPoleThread implements Runnable {
         CacheManager.changeStatus(CacheManager.TEST_BTN_KEY, true);
         String api = SysConfig.managerSetting.getServerUrl() + "/open/submitHarborPole";
         ReqBO reqBO = EventDataManager.getCacheData();
-        String bodyParams = JSONUtil.toJsonStr(reqBO);
-        if (StrUtil.isEmpty(bodyParams)
-                || !ChannelCacheManager.stateEnable(SysConfig.channelSetting.getChannelCode())||reqBO.getGatherTime()==null) {
+        if (!ChannelCacheManager.stateEnable(SysConfig.channelSetting.getChannelCode())) {
             return;
         }
         ChannelCacheManager.addCache(reqBO.getCarNo());
-        String subKey="sub_"+reqBO.getGatherTime().getTime();
+        String subKey = "sub_" + reqBO.getGatherTime().getTime();
         if (SubmitCache.checkExit(subKey)) {
-            log.error("重复提交数据:{}", bodyParams);
+            log.error("重复提交数据:{}", reqBO.getCarNo());
             return;
         }
+        reqBO.setGatherTime(new Date());
+        String bodyParams = JSONUtil.toJsonStr(reqBO);
+        SubmitCache.addCache(subKey);
         log.info("Req:{}", bodyParams);
         EventBus eventBus = SpringUtil.getBean(EventBus.class);
         try (HttpResponse response = HttpUtil.createPost(api).body(WordHandlerUtils.AESEncrypt(bodyParams)).execute()) {

+ 14 - 5
src/main/java/com/gzlh/bus/SubmitThread.java

@@ -1,11 +1,13 @@
 package com.gzlh.bus;
 
+import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.spring.SpringUtil;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
+import com.gzlh.cache.PassCacheManager;
 import com.gzlh.config.ModuleEnum;
 import com.gzlh.config.SystemObject;
 import com.gzlh.device.led.utils.LedOptions;
@@ -17,15 +19,15 @@ import com.gzlh.utils.WordHandlerUtils;
 import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
-public class SubmitThread implements Runnable{
+public class SubmitThread implements Runnable {
     @Override
     public void run() {
         String api = SysConfig.managerSetting.getServerUrl() + "/open/submit";
-        ReqBO reqBO=EventDataManager.getCacheData();
+        ReqBO reqBO = EventDataManager.getCacheData();
         String bodyParams = JSONUtil.toJsonStr(reqBO);
         if (StrUtil.isEmpty(bodyParams)
                 || ChannelCacheManager.checkExit(reqBO.getCarNo())
-        ||!ChannelCacheManager.stateEnable(SysConfig.channelSetting.getChannelCode())) {
+                || !ChannelCacheManager.stateEnable(SysConfig.channelSetting.getChannelCode())) {
             return;
         }
         ChannelCacheManager.addCache(reqBO.getCarNo());
@@ -36,20 +38,27 @@ public class SubmitThread implements Runnable{
             if (response.getStatus() == 200) {
                 String body = response.body();
                 JSONObject jsonObject = JSONUtil.parseObj(body);
-    //            返回数据解密
+                //            返回数据解密
                 String data = WordHandlerUtils.AESDecrypt(jsonObject.get("data").toString());
                 log.info("data:{}", data);
                 CommandBO commandBO = JSONUtil.toBean(data, CommandBO.class);
                 LedOptions options = new LedOptions().setLine("04").setShowType("00");
                 if (jsonObject.getInt("code") == 200) {
                     log.info("抬杆放行============");
-                    eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.RAILING_RISE);
+                    int count=0;
+                    while (count <3){
+                        count++;
+                        eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.RAILING_RISE);
+                        ThreadUtil.sleep(1000);
+                    }
                     options.setColor("02");
                     if (ModuleEnum.LED_MODULE.getModuleEn().equalsIgnoreCase(commandBO.getCommand().getModule())) {
                         SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
                                 .sendMsg(commandBO.getCommand().getExtra(), options);
                     }
+                    PassCacheManager.customerPass = true;
                 } else {
+                    PassCacheManager.customerPass = false;
                     options.setColor("01");
                     if (ModuleEnum.LED_MODULE.getModuleEn().equalsIgnoreCase(commandBO.getCommand().getModule())) {
                         SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())

+ 56 - 7
src/main/java/com/gzlh/bus/SysConfig.java

@@ -1,6 +1,7 @@
 package com.gzlh.bus;
 
 import cn.hutool.core.io.FileUtil;
+import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.XML;
 import com.gzlh.config.dto.*;
@@ -8,7 +9,12 @@ import com.gzlh.utils.DeviceCache;
 import lombok.Data;
 import lombok.extern.slf4j.Slf4j;
 
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
 import java.io.File;
+import java.io.StringReader;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 
@@ -20,6 +26,7 @@ public class SysConfig {
     public static CaputreSetting caputreSetting;
     public static ChannelSetting channelSetting;
     public static ManagerSetting managerSetting;
+    public static PassportSetting passportSetting;
     public static FaceListDTO faceDTO;
 
     public static void initConfig() {
@@ -33,15 +40,57 @@ public class SysConfig {
         }
         String content = FileUtil.readUtf8String(configFile);
         JSONObject result = XML.toJSONObject(content);
-        log.info("result:{}",result.toJSONString(0));
+        log.info("result:{}", result.toJSONString(0));
         ApplicationConfigDTO configDTO = result.toBean(ApplicationConfigDTO.class);
-        eventDTOList=configDTO.getConfig().getEventList().getEvent();
-        serialSetting=configDTO.getConfig().getSysConfig().getSerialSetting();
-        caputreSetting=configDTO.getConfig().getSysConfig().getCaputreSetting();
-        channelSetting=configDTO.getConfig().getChannelSetting();
-        managerSetting=configDTO.getConfig().getManagerSetting();
-       faceDTO= configDTO.getConfig().getFaceConfig();
+        eventDTOList = configDTO.getConfig().getEventList().getEvent();
+        serialSetting = configDTO.getConfig().getSysConfig().getSerialSetting();
+        caputreSetting = configDTO.getConfig().getSysConfig().getCaputreSetting();
+        channelSetting = configDTO.getConfig().getChannelSetting();
+        managerSetting = configDTO.getConfig().getManagerSetting();
+        passportSetting = configDTO.getConfig().getPassport();
+        parseFace(result);
         DeviceCache.deviceStatusInit();
     }
 
+    private static void parseFace(JSONObject result) {
+        JSONObject faceConfig = result.getJSONObject("config").getJSONObject("faceConfig");
+        if (faceConfig==null) return;
+        boolean enable = faceConfig.getBool("enable");
+        // 获取 faceList 节点
+        JSONObject faceList = faceConfig.getJSONObject("faceList");
+        FaceListDTO faceListDTO = new FaceListDTO();
+        faceListDTO.setEnable(enable);
+        List<Face> faceArray = new ArrayList<>();
+        // 检查 face 节点是否存在
+        if (faceList.containsKey("face")) {
+            Object faceObj = faceList.get("face");
+            if (faceObj instanceof JSONArray) {
+                // 多个 face 节点
+                JSONArray faces = faceList.getJSONArray("face");
+                for (int i = 0; i < faces.size(); i++) {
+                    JSONObject face = faces.getJSONObject(i);
+                    // 处理每个 face 节点
+                    faceArray.add(processFace(face));
+                }
+            } else if (faceObj instanceof JSONObject) {
+                // 单个 face 节点
+                JSONObject face = faceList.getJSONObject("face");
+                // 处理单个 face 节点
+                faceArray.add(processFace(face));
+            }
+        }
+        faceListDTO.setFaceList(faceArray);
+        faceDTO = faceListDTO;
+    }
+
+    private static Face processFace(JSONObject face) {
+        String channelCode = face.getStr("channelCode");
+        String ip = face.getStr("ip");
+        short port = face.getShort("port");
+        String uname = face.getStr("uname");
+        String pwd = face.getStr("pwd");
+
+        return new Face(channelCode, ip, port, uname, pwd);
+
+    }
 }

+ 5 - 0
src/main/java/com/gzlh/bus/task/CheckState.java

@@ -1,5 +1,7 @@
 package com.gzlh.bus.task;
 
+import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.spring.SpringUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONObject;
@@ -25,6 +27,9 @@ public class CheckState {
 
     @Scheduled(cron = "0,25,40,55 * * * * ?")
     public void check() {
+        if (!SysConfig.managerSetting.isEnable()) {
+            return;
+        }
         String channelCode = SysConfig.channelSetting.getChannelCode();
         String api = SysConfig.managerSetting.getServerUrl() + "/open/channel/state?channelCode=" + channelCode;
         try {

+ 11 - 8
src/main/java/com/gzlh/cache/CacheManager.java

@@ -1,33 +1,36 @@
 package com.gzlh.cache;
 
+import cn.hutool.cache.CacheUtil;
 import cn.hutool.cache.impl.TimedCache;
 
 import java.util.HashMap;
 import java.util.Map;
 
 public class CacheManager {
-    public static final String TEST_BTN_KEY="test_btn";
-    public static final String REQ_BTN_KEY="req_btn";
-    public static final String CANCEL_BTN_KEY="cancel_btn";
-    private final static Map<String, Boolean> BTN_CACHE = new HashMap<>();
+    public static final String TEST_BTN_KEY = "test_btn";
+    public static final String REQ_BTN_KEY = "req_btn";
+    public static final String CANCEL_BTN_KEY = "cancel_btn";
+    private static final TimedCache<String, Boolean> CACHE_MAP = CacheUtil.newTimedCache(5000);
 
     /**
      * 是否可用
+     *
      * @param key
      * @return
      */
     public static boolean checkEnable(String key) {
-        Boolean result = BTN_CACHE.get(key);
-        return result != null && result;
+        Boolean result = CACHE_MAP.get(key, true);
+        return result == null || result;
     }
 
     /**
      * 改变状态
+     *
      * @param key
      * @param value
      */
-    public static void  changeStatus(String key, boolean value){
-        BTN_CACHE.put(key, value);
+    public static void changeStatus(String key, boolean value) {
+        CACHE_MAP.put(key, value);
     }
 
 

+ 8 - 0
src/main/java/com/gzlh/cache/PassCacheManager.java

@@ -0,0 +1,8 @@
+package com.gzlh.cache;
+
+public class PassCacheManager {
+    public static Boolean carPass=null;
+    public static Boolean facePass=null;
+    public static Boolean customerPass=null;
+
+}

+ 1 - 1
src/main/java/com/gzlh/cache/SubmitCache.java

@@ -4,7 +4,7 @@ import cn.hutool.cache.CacheUtil;
 import cn.hutool.cache.impl.TimedCache;
 
 public class SubmitCache {
-    private final static TimedCache<String,Integer>SUB_MIT_CACHE= CacheUtil.newTimedCache(60000);
+    private final static TimedCache<String,Integer>SUB_MIT_CACHE= CacheUtil.newTimedCache(90000);
     public static void addCache(String cache){
         SUB_MIT_CACHE.put(cache,1);
     }

+ 1 - 0
src/main/java/com/gzlh/config/ModuleEnum.java

@@ -16,6 +16,7 @@ public enum ModuleEnum {
     PRINT_MODULE("打印机","PRINT"),
     CENTER_MODULE("action调度中心","CENTER"),
     ELECTRON_MODULE("电子车牌","ELECTRON"),
+    FACE_MODULE("人脸识别","FACE"),
     ;
     /**
      * 模块(硬件)中文名

+ 3 - 0
src/main/java/com/gzlh/config/dto/ApplicationConfigDTO.java

@@ -30,6 +30,9 @@ public class ApplicationConfigDTO implements Serializable {
         @JsonProperty("faceConfig")
         private FaceListDTO faceConfig;
 
+        @JsonProperty("passport")
+        private PassportSetting passport;
+
         @NoArgsConstructor
         @Data
         public static class EventListDTO {

+ 36 - 0
src/main/java/com/gzlh/config/dto/Face.java

@@ -0,0 +1,36 @@
+package com.gzlh.config.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+
+/**
+ * 人脸机子
+ */
+@Data
+@AllArgsConstructor
+public class Face {
+    @JsonProperty("channelCode")
+    private String channelCode;
+    @JsonProperty("ip")
+    private String ip;
+    @JsonProperty("port")
+    private short port;
+    @JsonProperty("uname")
+    private  String uname;
+    @JsonProperty("pwd")
+    private  String pwd;
+    private Integer userId;
+    private boolean online;
+
+    public Face(String channelCode, String ip, short port, String uname, String pwd) {
+        this.channelCode = channelCode;
+        this.ip = ip;
+        this.port = port;
+        this.uname = uname;
+        this.pwd = pwd;
+    }
+}

+ 0 - 23
src/main/java/com/gzlh/config/dto/FaceDTO.java

@@ -1,23 +0,0 @@
-package com.gzlh.config.dto;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-/**
- * 人脸机子
- */
-@Data
-@AllArgsConstructor
-public class FaceDTO {
-    private String channelCode;
-    private String ip;
-    private short port;
-    @JsonIgnore
-    private  String uname;
-    @JsonIgnore
-    private  String pwd;
-    private Integer userId;
-    private boolean online;
-
-}

+ 4 - 2
src/main/java/com/gzlh/config/dto/FaceListDTO.java

@@ -4,13 +4,15 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
 import java.util.List;
 @NoArgsConstructor
 @Data
+@XmlAccessorType(XmlAccessType.FIELD)
 public class FaceListDTO {
     @JsonProperty("enable")
     private Boolean enable;
-
     @JsonProperty("face")
-    private List<FaceDTO> face;
+    private List<Face> faceList;
 }

+ 15 - 0
src/main/java/com/gzlh/config/dto/PassportSetting.java

@@ -0,0 +1,15 @@
+package com.gzlh.config.dto;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+@Data
+@Accessors(chain = true)
+public class PassportSetting implements Serializable {
+    private boolean enable;
+    private String host;
+    private String port;
+
+}

+ 5 - 0
src/main/java/com/gzlh/config/dto/SerialSetting.java

@@ -74,6 +74,7 @@ public class SerialSetting implements Serializable {
             private String signalRedPoint;
             private String signalGreenPoint;
             private String gatePoint;
+            private String downGatePoint;
         }
 
         @Data
@@ -88,6 +89,10 @@ public class SerialSetting implements Serializable {
              */
             private String downPoint;
             /**
+             * 1等
+             */
+            private String infraredMode;
+            /**
              * 雷达
              */
             private String radarPoint;

+ 5 - 7
src/main/java/com/gzlh/config/hksdk/AlarmParseService.java

@@ -7,19 +7,15 @@ import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
-import cn.hutool.extra.spring.SpringUtil;
 import com.gzlh.bus.ChannelCacheManager;
 import com.gzlh.bus.SysConfig;
-import com.gzlh.config.SystemObject;
 import com.gzlh.config.dto.ChannelSetting;
 import com.gzlh.device.capture.task.HandlerCarImage;
-import com.gzlh.config.FilePropertiesConfig;
 import com.gzlh.config.task.TaskService;
+import com.gzlh.device.face.service.FaceService;
 import com.gzlh.device.rfid.job.ElectronReadJob;
 import com.sun.jna.Pointer;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.autoconfigure.web.ServerProperties;
-import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
@@ -27,9 +23,7 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
-import java.net.InetAddress;
 import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.util.Date;
 
@@ -42,6 +36,8 @@ public class AlarmParseService {
 
     @Resource
     TaskService taskService;
+    @Resource
+    private FaceService faceService;
 
     public static final TimedCache<String, Integer> CACHE_MAP = CacheUtil.newTimedCache(2000);
 
@@ -126,6 +122,8 @@ public class AlarmParseService {
             pInfoV30.write(0, pAlarmInfo.getByteArray(0, strAlarmInfoV30.size()), 0, strAlarmInfoV30.size());
             strAlarmInfoV30.read();
             log.info("dwAlarmType:{}", strAlarmInfoV30.dwAlarmType);
+        }else if (lCommand == HCNetSDK.COMM_ALARM_ACS){
+            faceService.handlerFaceOpenGate(pAlarmer,pAlarmInfo);
         }
     }
 }

+ 3 - 0
src/main/java/com/gzlh/config/properties/ExternalProperties.java

@@ -12,5 +12,8 @@ public class ExternalProperties {
     private String faceStatusCallbackPath;
 
     private String faceOpenGatePath;
+    private String subCarValidatePath;
+
+    private String subFaceValidatePath;
 
 }

+ 4 - 0
src/main/java/com/gzlh/device/capture/action/ICaptureAction.java

@@ -5,8 +5,12 @@ public interface ICaptureAction {
      * 上传车牌号
      */
     String UPLOAD_CAR_NO="UPLOAD_CAR_NO";
+
+    String BU_CAI_CAR_NO="BU_CAI_CAR_NO";
+
     /**
      * 查询预约信息
      */
     String CHECK_HARBORPOLE_VERIFICATION="CHECK_HARBORPOLE_VERIFICATION";
+    String SUBMIT_ERROR="SUBMIT_ERROR";
 }

+ 4 - 0
src/main/java/com/gzlh/device/capture/event/CaptureEvent.java

@@ -14,5 +14,9 @@ public interface CaptureEvent {
      * 行政车道 抓拍到车牌
      */
     String CAPTURE_ADMIN="CAPTURE_ADMIN";
+    /**
+     * 识别失败
+     */
+    String IDENTIFY_FAIL="IDENTIFY_FAIL";
 
 }

+ 2 - 0
src/main/java/com/gzlh/device/capture/handler/impl/CaptureHandlerHk.java

@@ -35,6 +35,8 @@ public class CaptureHandlerHk implements ICaptureHandler {
             //upload file
         } else if (StrUtil.equals(action, ICaptureAction.CHECK_HARBORPOLE_VERIFICATION)) {
             captureHandlerService.checkHarborpoleVerification();
+        } else if (StrUtil.equals(action, ICaptureAction.SUBMIT_ERROR)) {
+            captureHandlerService.submitErrorRecord();
         }
     }
 

+ 15 - 2
src/main/java/com/gzlh/device/capture/service/CaptureHandlerService.java

@@ -30,8 +30,8 @@ public class CaptureHandlerService {
     public void checkHarborpoleVerification() {
         ReqBO reqBO = EventDataManager.getCacheData();
         if (reqBO == null || StrUtil.isEmpty(reqBO.getCarNo())) {
-            log.error("触发预约接口,但是车牌为空,并提交数据:{}", JSONUtil.toJsonStr(reqBO));
-            ThreadUtil.execute(new SubmitHarborPoleThread());
+            //log.error("触发预约接口,但是车牌为空,并提交数据:{}", JSONUtil.toJsonStr(reqBO));
+            //ThreadUtil.execute(new SubmitHarborPoleThread());
             return;
         }
         SerialSetting.PlcDTO.StatusDTO status = SysConfig.serialSetting.getPlc().getStatus();
@@ -92,4 +92,17 @@ public class CaptureHandlerService {
             }
         }
     }
+
+    public void submitErrorRecord() {
+        if (!ChannelCacheManager.stateEnable(SysConfig.channelSetting.getChannelCode())) {
+            return;
+        }
+        String api = SysConfig.managerSetting.getServerUrl() + "/open/submitErrorRecord";
+        String bodyParams = JSONUtil.toJsonStr(EventDataManager.getCacheData());
+        String resp = HttpUtil.createPost(api).body(bodyParams).execute().body();
+        LedOptions options = new LedOptions().setLine("03").setShowType("00");
+        SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
+                .sendMsg("未识别到车牌", options);
+
+    }
 }

+ 8 - 1
src/main/java/com/gzlh/device/capture/task/HandlerCarImage.java

@@ -54,8 +54,15 @@ public class HandlerCarImage extends Task {
                     .sendMsg("请勿跟车,请退出重进", options.setLine("04").setColor("01"));
             return;
         }
-        CommonWeighbridgeHandler.hsCar = true;
         EventBus eventBus = SpringUtil.getBean(EventBus.class);
+        if (StrUtil.isEmpty(carNo)&&StrUtil.isNotEmpty(httpUrl)){
+            EventDataManager.cacheData("carImg", httpUrl);
+            EventDataManager.cacheData("carNo", carNo);
+            EventDataManager.cacheData("gatherTime", new Date());
+            eventBus.startEvent(ModuleEnum.CAPTURE_MODULE.getModuleEn() + "." + CaptureEvent.IDENTIFY_FAIL);
+            return;
+        }
+
         //向总线发送抓拍到车牌事件
         int channelType = SysConfig.channelSetting.getChannelType();
         if (channelType == 0 || channelType == 2) {

+ 7 - 0
src/main/java/com/gzlh/device/face/action/FaceAction.java

@@ -0,0 +1,7 @@
+package com.gzlh.device.face.action;
+
+public interface FaceAction {
+
+    String FACE_RESULT="FACE_RESULT";
+    String NOTICE_CUSTOMERS="NOTICE_CUSTOMERS";
+}

+ 6 - 0
src/main/java/com/gzlh/device/face/event/FaceEvent.java

@@ -0,0 +1,6 @@
+package com.gzlh.device.face.event;
+
+public interface FaceEvent {
+    String FACE_RESULT = "FACE_RESULT";
+    String FACE_DETECT = "FACE_DETECT";
+}

+ 32 - 0
src/main/java/com/gzlh/device/face/handler/FaceActionHandler.java

@@ -0,0 +1,32 @@
+package com.gzlh.device.face.handler;
+
+import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.StrUtil;
+import com.gzlh.bus.EventBus;
+import com.gzlh.bus.SysConfig;
+import com.gzlh.cache.PassCacheManager;
+import com.gzlh.config.SystemObject;
+import com.gzlh.device.face.task.SubmitFaceToLimitServerThread;
+import com.gzlh.device.face.action.FaceAction;
+import com.gzlh.device.led.utils.LedOptions;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+@Service
+@Slf4j
+public class FaceActionHandler {
+
+    public void handlerAction(String action) {
+        log.info("face");
+        if (StrUtil.equals(action, FaceAction.FACE_RESULT)) {
+            //人��识别结果
+            ThreadUtil.execute(new SubmitFaceToLimitServerThread());
+        } else if (StrUtil.equals(action, FaceAction.NOTICE_CUSTOMERS)) {
+            //通知海关闸口放行
+        }
+    }
+
+
+}

+ 18 - 9
src/main/java/com/gzlh/device/face/UserManage.java → src/main/java/com/gzlh/device/face/hkutils/UserManage.java

@@ -1,12 +1,15 @@
-package com.gzlh.device.face;
+package com.gzlh.device.face.hkutils;
 
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONException;
 import cn.hutool.json.JSONObject;
 
 import com.gzlh.config.hksdk.HCNetSDK;
 import com.gzlh.constans.AjaxError;
+import com.gzlh.entity.AddFaceBO;
 import com.sun.jna.Pointer;
 import com.sun.jna.ptr.IntByReference;
 import lombok.extern.slf4j.Slf4j;
@@ -15,6 +18,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.StandardCharsets;
+import java.util.Date;
 
 /**
  * 功能:人脸下发、查询、删除、人员计划模板配置
@@ -34,26 +38,31 @@ public class UserManage {
      * @throws InterruptedException
      * @throws JSONException
      */
-    public void AddUserInfo(int lUserID, String employeeNo, String name) throws UnsupportedEncodingException, InterruptedException, JSONException {
+    public void AddUserInfo(int lUserID, AddFaceBO addFaceBO) throws UnsupportedEncodingException, InterruptedException, JSONException {
         HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(1024);    //数组
         //"POST /ISAPI/AccessControl/UserInfo/Record?format=json" 此URL也是下发人员
         String strInBuffer = "PUT /ISAPI/AccessControl/UserInfo/SetUp?format=json";
         System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
         ptrByteArray.write();
-
+        String name=addFaceBO.getName();
+        String employeeNo=addFaceBO.getNo();
         int lHandler = hcNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_JSON_CONFIG, ptrByteArray.getPointer(), strInBuffer.length(), null, null);
         if (lHandler < 0) {
             log.error("AddUserInfo NET_DVR_StartRemoteConfig 失败,错误码为" + hcNetSDK.NET_DVR_GetLastError());
             throw new AjaxError("添加失败");
         } else {
+
             byte[] Name = name.getBytes(StandardCharsets.UTF_8); //根据iCharEncodeType判断,如果iCharEncodeType返回6,则是UTF-8编码。
             //如果是0或者1或者2,则是GBK编码
             //将中文字符编码之后用数组拷贝的方式,避免因为编码导致的长度问题
-            String strInBuffer1 = "{\"UserInfo\":{\"Valid\":{\"beginTime\":\"2024-08-01T17:30:08\",\"enable\":true,\"endTime\":" +
-                    "\"2030-08-01T17:30:08\"}," +
+            Date now = new Date();
+            String nowTime = DateUtil.formatDate(now) + "T" + DateUtil.formatTime(now);
+            String expireTime = StrUtil.replace(addFaceBO.getExpireTime(), " ","T");
+            String strInBuffer1 = "{\"UserInfo\":{\"Valid\":{\"beginTime\":\"" + nowTime + "\",\"enable\":true,\"endTime\":" +
+                    "\""+expireTime+"\"}," +
                     "\"checkUser\":false,\"belongGroup \":\"1\",\"doorRight\":\"1\",\"RightPlan\":[{\"doorNo\": 1,\"planTemplateNo\": \"1,3,5\"}]," +
                     "\"employeeNo\":\"" + employeeNo + "\",\"floorNumber\":2,\"maxOpenDoorTime\":0,\"name\":\"";
-            String strInBuffer2 = "\",\"openDelayEnabled\":false,\"password\":\"123456\",\"roomNumber\":4,\"userType\":\"normal\"}}";
+            String strInBuffer2 = "\",\"openDelayEnabled\":false,\"password\":\"\",\"roomNumber\":4,\"userType\":\"normal\"}}";
             int iStringSize = Name.length + strInBuffer1.length() + strInBuffer2.length();
 
             HCNetSDK.BYTE_ARRAY ptrByte = new HCNetSDK.BYTE_ARRAY(iStringSize);
@@ -88,14 +97,14 @@ public class UserManage {
                     continue;
                 } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {
                     log.info("下发人员失败, json retun:" + jsonResult.toString());
-                    throw new AjaxError("下发人员"+employeeNo+"失败");
+                    throw new AjaxError("下发人员" + employeeNo + "失败");
                 } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
                     log.info("下发人员异常, json retun:" + jsonResult.toString());
-                    throw new AjaxError("下发人员"+employeeNo+"失败");
+                    throw new AjaxError("下发人员" + employeeNo + "失败");
                 } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {//返回NET_SDK_CONFIG_STATUS_SUCCESS代表流程走通了,但并不代表下发成功,比如有些设备可能因为人员已存在等原因下发失败,所以需要解析Json报文
                     if (statusCode != 1) {
                         log.info("下发人员成功,但是有异常情况:" + jsonResult.toString());
-                        throw new AjaxError("下发人员"+employeeNo+"失败");
+                        throw new AjaxError("下发人员" + employeeNo + "失败");
                     } else {
                         log.info("下发人员成功: json retun:" + jsonResult.toString());
                     }

+ 1 - 1
src/main/java/com/gzlh/device/face/transIsapi.java → src/main/java/com/gzlh/device/face/hkutils/transIsapi.java

@@ -1,4 +1,4 @@
-package com.gzlh.device.face;
+package com.gzlh.device.face.hkutils;
 
 
 import com.gzlh.config.hksdk.HCNetSDK;

+ 47 - 35
src/main/java/com/gzlh/device/face/FaceService.java → src/main/java/com/gzlh/device/face/service/FaceService.java

@@ -1,33 +1,51 @@
-package com.gzlh.device.face;
+package com.gzlh.device.face.service;
 
+import cn.hutool.cache.CacheUtil;
+import cn.hutool.cache.impl.TimedCache;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.extra.spring.SpringUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONException;
 import cn.hutool.json.JSONObject;
 
-import com.gzlh.config.dto.FaceDTO;
+import com.gzlh.bus.EventBus;
+import com.gzlh.bus.EventDataManager;
+import com.gzlh.bus.SysConfig;
+import com.gzlh.cache.PassCacheManager;
+import com.gzlh.config.ModuleEnum;
+import com.gzlh.config.SystemObject;
+import com.gzlh.config.dto.Face;
 import com.gzlh.config.hksdk.HCNetSDK;
 import com.gzlh.config.properties.ExternalProperties;
 import com.gzlh.constans.AjaxError;
+import com.gzlh.device.face.action.FaceAction;
+import com.gzlh.device.face.hkutils.transIsapi;
+import com.gzlh.device.led.utils.LedOptions;
+import com.gzlh.device.plc.event.PLCEvent;
+import com.gzlh.entity.ReqBO;
 import com.gzlh.utils.FileUtils;
 import com.sun.jna.Pointer;
 import com.sun.jna.ptr.IntByReference;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.util.Date;
 
 @Service
 @Slf4j
 public class FaceService {
     @Resource
     private HCNetSDK hcNetSDK;
+    @Resource
+    private EventBus eventBus;
+    @Resource
+    private ExternalProperties externalProperties;
 
-   @Resource
-   private ExternalProperties externalProperties;
+    private final static TimedCache<String, Integer> CAPTURE_CACHE = CacheUtil.newTimedCache(10000);
 
     /**
      * 功能:按照二进制方式下发人脸图片
@@ -108,16 +126,15 @@ public class FaceService {
                 ptrOutuff.read();
                 String strResult = new String(ptrOutuff.byValue).trim();
                 System.out.println("dwState:" + dwState + ",strResult:" + strResult);
-
+                if (dwState == -1) {
+                    System.out.println("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
+                    break;
+                }
                 JSONObject jsonResult = new JSONObject(strResult);
                 int statusCode = jsonResult.getInt("statusCode");
                 String statusString = jsonResult.getStr("statusString");
 
-
-                if (dwState == -1) {
-                    System.out.println("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
-                    break;
-                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEED_WAIT) {
+                if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEED_WAIT) {
                     System.out.println("配置等待");
                     Thread.sleep(10);
                     continue;
@@ -204,8 +221,6 @@ public class FaceService {
                 JSONObject jsonResult = new JSONObject(strResult);
                 int statusCode = jsonResult.getInt("statusCode");
                 String statusString = jsonResult.getStr("statusString");
-
-
                 if (dwState == -1) {
                     System.out.println("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError());
                     break;
@@ -280,7 +295,9 @@ public class FaceService {
         sIP = new String(pAlarmer.sDeviceIP).split("\0", 2);
         //报警设备ip
         String ip = sIP[0];
-        FaceDTO faceDTO = null;
+        Face faceDTO = SysConfig.faceDTO.getFaceList()
+                .stream().filter(face -> face.getIp().equals(ip)).findFirst()
+                .orElse(null);
         if (faceDTO == null) {
             log.error("未找到ip为{}的faceDTO", ip);
             return;
@@ -304,29 +321,24 @@ public class FaceService {
             test.read();
             employeeId = new String(test.byEmployeeNo).trim();
         }
-        log.info("员工employeeId=" + employeeId);
-        String eventTime = DateUtil.now();
-        log.info("刷卡时间eventTime=" + eventTime);
+//        log.info("员工employeeId=" + employeeId);
         //刷脸成功
-        if (strACSInfo.dwMinor == 75) {
-            log.info("刷脸成功============dwMinor============" + strACSInfo.dwMinor);
-        }
-        //刷脸失败
-        else if (strACSInfo.dwMinor == 76) {
-            log.info("刷脸失败============dwMinor============" + strACSInfo.dwMinor);
-        }
-        //门锁打开
-        else if (strACSInfo.dwMinor == 21) {
-            log.info("门锁打开============dwMinor============" + strACSInfo.dwMinor);
+        if (strACSInfo.dwMinor == 75 || strACSInfo.dwMinor == 76) {
+            Integer flag = CAPTURE_CACHE.get(employeeId);
+            if (flag != null) {
+                return;
+            }
+            boolean result = strACSInfo.dwMinor == 75;
+            PassCacheManager.facePass = true;
+            CAPTURE_CACHE.put(employeeId, 1);
+            ReqBO.Face face = new ReqBO.Face();
+            face.setIp(ip).setTime(new Date()).setPass(result)
+                    .setChannelCode(face.getChannelCode())
+                    .setEmployeeNo(employeeId);
+            EventDataManager.cacheData("face", face);
+            eventBus.startEvent(ModuleEnum.FACE_MODULE.getModuleEn() + "." + FaceAction.FACE_RESULT);
+            // log.info("刷脸成功============dwMinor============" + strACSInfo.dwMinor);
         }
-        String uploadFaceGateUrl=externalProperties.getFaceOpenGatePath();
-        JSONObject params = new JSONObject();
-        params.set("employeeNo", employeeId)
-                .set("ip", ip)
-                .set("time", DateUtil.now())
-                .set("channelCode", faceDTO.getChannelCode());
-        String resp = HttpUtil.createPost(uploadFaceGateUrl).body(params.toJSONString(0)).execute().body();
-        log.info("上报开门事件:{},{},{}", uploadFaceGateUrl, params.toJSONString(0), resp);
 
     }
 

+ 4 - 4
src/main/java/com/gzlh/device/face/LoginFaceGate.java → src/main/java/com/gzlh/device/face/service/LoginFaceGate.java

@@ -1,17 +1,17 @@
-package com.gzlh.device.face;
+package com.gzlh.device.face.service;
 
 import cn.hutool.extra.spring.SpringUtil;
 
 import com.gzlh.config.hksdk.HCNetSDK;
 import com.gzlh.config.hksdk.HkUtils;
-import com.gzlh.config.dto.FaceDTO;
+import com.gzlh.config.dto.Face;
 import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
 public class LoginFaceGate implements Runnable{
-    private FaceDTO faceDTO;
+    private Face faceDTO;
 
-    public LoginFaceGate(FaceDTO faceDTO) {
+    public LoginFaceGate(Face faceDTO) {
         this.faceDTO = faceDTO;
     }
 

+ 5 - 5
src/main/java/com/gzlh/device/face/CheckFaceGateOnlineTask.java → src/main/java/com/gzlh/device/face/task/CheckFaceGateOnlineTask.java

@@ -1,15 +1,15 @@
-package com.gzlh.device.face;
+package com.gzlh.device.face.task;
 
 import cn.hutool.extra.spring.SpringUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONUtil;
 
-import com.gzlh.config.dto.FaceDTO;
+import com.gzlh.bus.SysConfig;
+import com.gzlh.config.dto.Face;
 import com.gzlh.config.hksdk.HCNetSDK;
 import com.gzlh.config.hksdk.HkUtils;
 import com.gzlh.config.properties.ExternalProperties;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.core.env.Environment;
 
 import java.util.Collections;
 import java.util.List;
@@ -25,13 +25,13 @@ public class CheckFaceGateOnlineTask implements Runnable {
     public void run() {
         HkUtils hkUtils = SpringUtil.getBean(HkUtils.class);
         ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
-        List<FaceDTO> faceDTOList = Collections.emptyList();
+        List<Face> faceDTOList = SysConfig.faceDTO.getFaceList();
         if (faceDTOList.isEmpty()) {
             return;
         }
         HCNetSDK hcNetSDK = SpringUtil.getBean(HCNetSDK.class);
         Runnable task = () -> {
-            for (FaceDTO faceDTO : faceDTOList) {
+            for (Face faceDTO : faceDTOList) {
                 faceDTO.setOnline(hkUtils.getStatus(hcNetSDK, faceDTO.getUserId()));
             }
         };

+ 10 - 0
src/main/java/com/gzlh/device/face/task/NoticeCustomersThread.java

@@ -0,0 +1,10 @@
+package com.gzlh.device.face.task;
+
+import static sun.management.snmp.jvminstr.JvmThreadInstanceEntryImpl.ThreadStateMap.Byte0.runnable;
+
+public class NoticeCustomersThread implements Runnable{
+    @Override
+    public void run() {
+
+    }
+}

+ 104 - 0
src/main/java/com/gzlh/device/face/task/SubmitFaceToLimitServerThread.java

@@ -0,0 +1,104 @@
+package com.gzlh.device.face.task;
+
+import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.gzlh.bus.EventBus;
+import com.gzlh.bus.EventDataManager;
+import com.gzlh.bus.SysConfig;
+import com.gzlh.cache.CacheManager;
+import com.gzlh.cache.PassCacheManager;
+import com.gzlh.config.ModuleEnum;
+import com.gzlh.config.SystemObject;
+import com.gzlh.config.dto.ChannelSetting;
+import com.gzlh.config.properties.ExternalProperties;
+import com.gzlh.device.led.utils.LedOptions;
+import com.gzlh.device.plc.event.PLCEvent;
+import com.gzlh.entity.ReqBO;
+import com.gzlh.utils.DeviceCache;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class SubmitFaceToLimitServerThread implements Runnable {
+    @Override
+    public void run() {
+        ReqBO reqBO = EventDataManager.getCacheData();
+        int channelType = SysConfig.channelSetting.getChannelType();
+        //非人行通道,需要有车牌
+        if (channelType != 3) {
+            if (reqBO == null || StrUtil.isEmpty(reqBO.getCarNo())) {
+                return;
+            }
+        }
+        ExternalProperties externalProperties = SpringUtil.getBean(ExternalProperties.class);
+        String uploadFaceGateUrl = externalProperties.getFaceOpenGatePath();
+        JSONObject params = new JSONObject();
+        ReqBO.Face face = reqBO.getFace();
+        boolean pass = face.isPass();
+        params.set("employeeNo", face.getEmployeeNo())
+                .set("ip", face.getIp())
+                .set("time", face.getTime())
+                .set("carNo", reqBO.getCarNo())
+                .set("pass", pass)
+                .set("channelCode", reqBO.getChannelCode());
+        String resp = HttpUtil.createPost(uploadFaceGateUrl).body(params.toJSONString(0)).execute().body();
+        log.info("上报开门事件:{},{},{}", uploadFaceGateUrl, params.toJSONString(0), resp);
+
+        //非行人通道
+        if (channelType != 3) {
+            LedOptions options = new LedOptions().setLine("03").setShowType("00");
+            if (pass) {
+                //行政通道---直接抬杆
+                if (channelType == 1) {
+                    SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
+                            .sendMsg("请通行", options);
+                    EventBus eventBus = SpringUtil.getBean(EventBus.class);
+                    eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.RAILING_RISE);
+                    PassCacheManager.carPass = null;
+                    PassCacheManager.customerPass = null;
+                    PassCacheManager.facePass = null;
+                    return;
+                }
+
+                SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
+                        .sendMsg("请等待核验", options);
+                EventBus eventBus = SpringUtil.getBean(EventBus.class);
+                int count = 0;
+                String serverUrl = SysConfig.channelSetting.getTwinService();
+                while (count < 15) {
+                    String response = HttpUtil.get(serverUrl);
+                    JSONObject result = JSONUtil.parseObj(response);
+                    Boolean re = result.getBool("data");
+                    if (re == null) {
+                        count++;
+                        ThreadUtil.sleep(1000);
+                        continue;
+                    }
+                    if (re) {
+                        PassCacheManager.carPass = null;
+                        PassCacheManager.customerPass = null;
+                        PassCacheManager.facePass = null;
+                        //抬杆
+                        eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.RAILING_RISE);
+                    } else {
+                        SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
+                                .sendMsg("核验失败,请退出通道", options);
+                        DeviceCache.setInterrupt(true);
+                        break;
+                    }
+                }
+            } else {
+                SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
+                        .sendMsg("核验失败,请退出通道", options);
+                DeviceCache.setInterrupt(true);
+            }
+
+
+        }
+
+
+    }
+}

+ 5 - 0
src/main/java/com/gzlh/device/led/handler/impl/LedHandlerFengLiYuan.java

@@ -1,5 +1,6 @@
 package com.gzlh.device.led.handler.impl;
 
+import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.StrUtil;
 import com.gzlh.bus.EventDataManager;
 import com.gzlh.bus.SysConfig;
@@ -8,6 +9,7 @@ import com.gzlh.device.led.action.LedAction;
 import com.gzlh.device.led.brand.LedBrandType;
 import com.gzlh.device.led.client.LedNettyConfig;
 import com.gzlh.device.led.handler.ILedHandler;
+import com.gzlh.device.led.task.NotifyToServer;
 import com.gzlh.device.led.utils.FengLiYuanPackUtils;
 import com.gzlh.device.led.utils.LedOptions;
 import com.gzlh.entity.ReqBO;
@@ -34,6 +36,9 @@ public class LedHandlerFengLiYuan implements ILedHandler {
         String msgHex = FengLiYuanPackUtils.build(content, options);
 //        log.info("数据包:{}", msgHex);
         ledNettyConfig.send(msgHex);
+        if (options.getLine().equals("03")){
+            ThreadUtil.execute(new NotifyToServer(content));
+        }
     }
 
     @Override

+ 28 - 0
src/main/java/com/gzlh/device/led/task/NotifyToServer.java

@@ -0,0 +1,28 @@
+package com.gzlh.device.led.task;
+
+import cn.hutool.extra.spring.SpringUtil;
+import cn.hutool.json.JSONObject;
+import com.gzlh.background.BackgroundClientNetty;
+import com.gzlh.bus.EventDataManager;
+import com.gzlh.bus.SysConfig;
+import com.gzlh.device.led.utils.LedOptions;
+import com.gzlh.entity.ReqBO;
+
+public class NotifyToServer implements Runnable {
+    String content;
+
+    public NotifyToServer(String content) {
+        this.content = content;
+    }
+
+    @Override
+    public void run() {
+        BackgroundClientNetty backgroundClientNetty = SpringUtil.getBean(BackgroundClientNetty.class);
+        JSONObject msg = new JSONObject();
+        msg.set("channelCode", SysConfig.channelSetting.getChannelCode());
+        msg.set("content", content);
+        msg.set("field", "message");
+        msg.set("module", "channelMonitor");
+        backgroundClientNetty.send(msg.toJSONString(0));
+    }
+}

+ 2 - 1
src/main/java/com/gzlh/device/led/utils/CRC16.java

@@ -40,7 +40,8 @@ public class CRC16 {
 
     public static void main(String[] args) {
         String crc="781D";
-        String packData="0106004B0002";
+
+        String packData="040001";
         int[] a = new int[packData.length() / 2];
         for (int i = 0; i < packData.length(); i += 2) {
             a[i / 2] = Integer.parseInt(packData.substring(i, i + 2), 16);

+ 73 - 0
src/main/java/com/gzlh/device/passport/PassportReadClient.java

@@ -0,0 +1,73 @@
+package com.gzlh.device.passport;
+
+import cn.hutool.json.JSONUtil;
+
+import com.gzlh.device.passport.domain.PackageJson;
+import lombok.extern.slf4j.Slf4j;
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.handshake.ServerHandshake;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+@Slf4j
+
+public class PassportReadClient extends WebSocketClient {
+    private final int reconnectInterval = 5000; // 重连间隔时间(毫秒)
+    private boolean connected = false;
+
+    private String websocketServerUrl;
+
+
+    public PassportReadClient(String websocketServerUrl) throws URISyntaxException {
+        super(new URI(websocketServerUrl));  // 在构造函数中初始化连接
+
+    }
+
+
+    @Override
+    public void onOpen(ServerHandshake handshakedata) {
+        connected=true;
+        System.out.println("Opened connection");
+        send("Hello from Spring managed WebSocket client!");
+
+    }
+
+    @Override
+    public void onMessage(String message) {
+        log.info("Received message: " + message);
+        PackageJson packageJson= JSONUtil.toBean(message, PackageJson.class);
+        log.info(" message Type: " + packageJson.getType());
+    }
+
+    @Override
+    public void onClose(int code, String reason, boolean remote) {
+        System.out.println("Connection closed by " + (remote ? "server" : "client") + ": " + reason);
+        connected=false;
+    }
+
+    @Override
+    public void onError(Exception ex) {
+        ex.printStackTrace();
+    }
+
+    @Override
+    public void reconnect() {
+        try {
+            Thread.sleep(reconnectInterval); // 等待一段时间后重连
+            log.info("reconnecting");
+            connect();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+    }
+
+
+    // 添加一个 connect 方法,以便在需要时手动连接
+    public void connectClient() {
+        if (!this.getConnection().isOpen()) {
+            this.connect();
+        }
+    }
+
+}

+ 32 - 0
src/main/java/com/gzlh/device/passport/barnd/PassportEventType.java

@@ -0,0 +1,32 @@
+package com.gzlh.device.passport.barnd;
+
+public enum PassportEventType {
+    ZA_PASS_PORT(2000,"中安护照")
+    ;
+
+
+    private int code;
+    private String brand;
+
+    PassportEventType(int code, String brand) {
+        this.code = code;
+        this.brand = brand;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getBrand() {
+        return brand;
+    }
+
+    public static String getBrandByCode(int code) {
+        for (PassportEventType brandType : PassportEventType.values()) {
+            if (brandType.getCode() == code) {
+                return brandType.getBrand();
+            }
+        }
+        return null;
+    }
+}

+ 15 - 0
src/main/java/com/gzlh/device/passport/domain/PackageJson.java

@@ -0,0 +1,15 @@
+package com.gzlh.device.passport.domain;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@Accessors(chain = true)
+public class PackageJson {
+    private String Type;
+    private String Command;
+    private String Operand;
+    private String Param;
+    private String Succeeded;
+    private String Result;
+}

+ 18 - 0
src/main/java/com/gzlh/device/passport/factory/PassportEventHandlerFactory.java

@@ -0,0 +1,18 @@
+package com.gzlh.device.passport.factory;
+import com.gzlh.device.passport.handler.IPassportEventHandler;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class PassportEventHandlerFactory {
+    @Autowired
+    private List<IPassportEventHandler>handlers;
+
+    public IPassportEventHandler handler(int code){
+       return handlers.stream().filter(h->h.brandType().getCode()==code)
+                .findAny().orElseThrow(()->new IllegalArgumentException("不支持电子车牌"));
+    }
+
+}

+ 31 - 0
src/main/java/com/gzlh/device/passport/handler/IPassportEventHandler.java

@@ -0,0 +1,31 @@
+package com.gzlh.device.passport.handler;
+
+
+import com.gzlh.device.passport.barnd.PassportEventType;
+
+public interface IPassportEventHandler {
+
+    PassportEventType brandType();
+
+
+    /**
+     * 处理命令
+     * @param action
+     */
+    void handlerAction(String action);
+
+    /**
+     * 发送信息
+     * @param msg
+     */
+    void sendMsg(String msg);
+
+    /**
+     * 处理信息
+     * @param msg
+     */
+    void handlerMsg(String msg);
+
+
+
+}

+ 36 - 0
src/main/java/com/gzlh/device/passport/handler/impl/ZAPassportEventHandler.java

@@ -0,0 +1,36 @@
+package com.gzlh.device.passport.handler.impl;
+
+
+import com.gzlh.device.passport.barnd.PassportEventType;
+import com.gzlh.device.passport.handler.IPassportEventHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+
+
+/**
+ * 中安护照
+ */
+@Component
+@Slf4j
+public class ZAPassportEventHandler implements IPassportEventHandler {
+    @Override
+    public PassportEventType brandType() {
+        return PassportEventType.ZA_PASS_PORT;
+    }
+
+    @Override
+    public void handlerAction(String action) {
+
+    }
+
+    @Override
+    public void sendMsg(String msg) {
+
+    }
+
+    @Override
+    public void handlerMsg(String msg) {
+
+    }
+}

+ 8 - 0
src/main/java/com/gzlh/device/plc/action/PLCAction.java

@@ -38,4 +38,12 @@ public interface PLCAction {
      * 重置
      */
     String REQ_TWIN_IDLE="REQ_TWIN_IDLE";
+    /**
+     * 落杆
+     */
+    String GATE_DOWN="GATE_DOWN";
+    /**
+     * 释放落杆PLC断开
+     */
+    String RELEASE_GATE_DOWN="RELEASE_GATE_DOWN";
 }

+ 63 - 33
src/main/java/com/gzlh/device/plc/handler/PLCHadnler.java

@@ -28,6 +28,7 @@ import com.gzlh.device.plc.service.PLCService;
 import com.gzlh.device.print.action.PrintCommonAction;
 import com.gzlh.device.print.event.PrintEvent;
 import com.gzlh.device.print.factory.PrintFactory;
+import com.gzlh.device.rfid.job.ElectronReadJob;
 import com.gzlh.device.weighbridge.event.WeighbridgeEvent;
 import com.gzlh.device.weighbridge.handler.impl.CommonWeighbridgeHandler;
 import com.gzlh.entity.ReqBO;
@@ -106,6 +107,7 @@ public class PLCHadnler {
             plcNettyConfig.send(packData);
             taskService.addTask(new CheckDownTask(RandomUtil.randomNumbers(10), 200, 1));
         } else if (StrUtil.equals(action, PLCAction.REQ_PRINT)) {
+
             plcService.reqPrint();
         } else if (StrUtil.equals(action, PLCAction.TEST_PRINT)) {
             plcService.testPrint();
@@ -119,6 +121,18 @@ public class PLCHadnler {
             plcService.reqTwinRightDisable();
         } else if (StrUtil.equals(action, PLCAction.REQ_TWIN_IDLE)) {
             plcService.reqTwinIdle();
+        } else if (StrUtil.equals(action, PLCAction.GATE_DOWN)) {
+            String downGatePoint = serialSetting.getPlc().getOut().getDownGatePoint();
+            String command = COMMAND_PREFIX + downGatePoint + COMMAND_ON;
+            // log.info("plc发送消息:{}", command);
+            String packData = ModbusUtils.buildRequestPacket(command);
+            plcNettyConfig.send(packData);
+        } else if (StrUtil.equals(action, PLCAction.RELEASE_GATE_DOWN)) {
+            String downGatePoint = serialSetting.getPlc().getOut().getDownGatePoint();
+            String command = COMMAND_PREFIX + downGatePoint + COMMAND_OFF;
+            // log.info("plc发送消息:{}", command);
+            String packData = ModbusUtils.buildRequestPacket(command);
+            plcNettyConfig.send(packData);
         }
     }
 
@@ -196,17 +210,23 @@ public class PLCHadnler {
             String cancelPrintPoint = status.getCancelPrint();
             String cancelPrintPointStatus = newReverse.charAt(Integer.parseInt(cancelPrintPoint)) + "";
             //试榜单
-            String testPrintPoint = status.getCancelPrint();
+            String testPrintPoint = status.getTestPrint();
             String testPrintPointStatus = newReverse.charAt(Integer.parseInt(testPrintPoint)) + "";
+            String infraredMode = status.getInfraredMode();
             //前红外发生变化
             if (judgePoint.equals(redPoint)) {
                 if (redPointStatus.equals("0")) {
                     log.info("前红外断开&磅上有车--->触发3秒后是否开始称重,{}", CommonWeighbridgeHandler.hsCar);
                     taskService.addTask(new CheckStartWeightTask(RandomUtil.randomNumbers(16), 3000));
                 } else if (redPointStatus.equals("1")) {
+                    if (StrUtil.equals(infraredMode, "-1")) {
+                        log.info("安派---前红外断开&磅上有车--->触发3秒后是否开始称重,{}", CommonWeighbridgeHandler.hsCar);
+                        taskService.addTask(new CheckStartWeightTask(RandomUtil.randomNumbers(16), 3000));
+                    }
                     //前红外触碰并且磅上有车===>发布车辆进入地磅事件
-                    if (reqBO != null && StrUtil.isNotEmpty(reqBO.getCarNo())) {
-                        log.info("前红外触碰");
+                    if (reqBO == null || StrUtil.isEmpty(reqBO.getCarNo())) {
+                        log.info("前红外触碰,读取RFID====");
+                        ThreadUtil.execute(new ElectronReadJob());
                         //eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.CAR_ENTER);
                     }
                 }
@@ -221,15 +241,28 @@ public class PLCHadnler {
                     eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.DOWN_POINT_READ);
                 }
             } else if (bRedPoint.equals(judgePoint)) {
-                //车触碰到后红外&在磅上&下到位==>提醒推车
-                if (bRedPointStatus.equals("1") && downPointStatus.equals("1") && radarPointStatus.equals("1")) {
-                    DeviceCache.setInterrupt(true);
-                    LedOptions options = new LedOptions().setLine("03").setColor("01").setShowType("00");
-                    SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
-                            .sendMsg("请倒车", options);
-                } else if (bRedPointStatus.equals("0") && downPointStatus.equals("1") && radarPointStatus.equals("1")) {
-                    //倒车完成
-                    eventBus.startEvent(ModuleEnum.WEIGHBRIDGE_MODULE.getModuleEn() + "." + WeighbridgeEvent.READ);
+                if (StrUtil.equals(infraredMode,"-1")){
+                    //车触碰到后红外&在磅上&下到位==>提醒推车
+                    if (bRedPointStatus.equals("0") && downPointStatus.equals("1") && radarPointStatus.equals("1")) {
+                        DeviceCache.setInterrupt(true);
+                        LedOptions options = new LedOptions().setLine("03").setColor("01").setShowType("00");
+                        SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
+                                .sendMsg("超出称重位置,请倒车!", options);
+                    } else if (bRedPointStatus.equals("1") && downPointStatus.equals("1") && radarPointStatus.equals("1")) {
+                        //倒车完成
+                        eventBus.startEvent(ModuleEnum.WEIGHBRIDGE_MODULE.getModuleEn() + "." + WeighbridgeEvent.READ);
+                    }
+                }else {
+                    //车触碰到后红外&在磅上&下到位==>提醒推车
+                    if (bRedPointStatus.equals("1") && downPointStatus.equals("1") && radarPointStatus.equals("1")) {
+                        DeviceCache.setInterrupt(true);
+                        LedOptions options = new LedOptions().setLine("03").setColor("01").setShowType("00");
+                        SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
+                                .sendMsg("超出称重位置,请倒车!", options);
+                    } else if (bRedPointStatus.equals("0") && downPointStatus.equals("1") && radarPointStatus.equals("1")) {
+                        //倒车完成
+                        eventBus.startEvent(ModuleEnum.WEIGHBRIDGE_MODULE.getModuleEn() + "." + WeighbridgeEvent.READ);
+                    }
                 }
             } else if (judgePoint.equals(radarPoint)) {
                 if (radarPointStatus.equals("0")) {
@@ -237,13 +270,20 @@ public class PLCHadnler {
                 } else if (radarPointStatus.equals("1")) {
                     taskService.addTask(new CheckCarInTask(RandomUtil.randomNumbers(16), 200));
                 }
-            } else if (printPointStatus.equals("1") && judgePoint.equals(printPoint)) {
-                eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.START_PRINT);
-            } else if (cancelPrintPointStatus.equals("1") && judgePoint.equals(cancelPrintPoint)) {
-                eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.CANCEL_PRINT);
-            } else if (testPrintPointStatus.equals("1") && judgePoint.equals(testPrintPoint)) {
-                eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.TEST_PRINT);
+            } else if (testPrintPoint.equals(judgePoint)) {
+                if (testPrintPointStatus.equals("1")) {
+                    eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.TEST_PRINT);
+                }
+            } else if (cancelPrintPoint.equals(judgePoint)) {
+                if (cancelPrintPointStatus.equals("1")) {
+                    eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.CANCEL_PRINT);
+                }
+            } else if (printPoint.equals(judgePoint)) {
+                if (printPointStatus.equals("1")) {
+                    eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.START_PRINT);
+                }
             }
+
         }
     }
 
@@ -409,22 +449,12 @@ public class PLCHadnler {
     }
 
     public static void main(String[] args) {
-        String str = "10";
-        String result = Integer.toBinaryString(Integer.parseInt(str, 16));
-        System.out.println(result);
-//        将plc的设备信息补到8存入缓存
-        String newPlcInfo = String.format("%8s", result).replace(" ", "0");
-        System.out.println(newPlcInfo);
-        String newReverse = new StringBuffer(newPlcInfo).reverse().toString();
-        System.out.println(newReverse);
 
-        int i = 0, j = 2, k = 4;
-
-        if (i == 0 && j == 2 && k == 4) {
-            System.out.println(1);
-        } else if (i == 0) {
-            System.out.println(2);
-        }
+        String command = COMMAND_PREFIX + "00" + COMMAND_ON;
+//        String command = COMMAND_PREFIX + "00" + COMMAND_OFF;
+        // log.info("plc发送消息:{}", command);
+        String packData = ModbusUtils.buildRequestPacket(command);
+        System.out.println(packData);
 
     }
 }

+ 1 - 1
src/main/java/com/gzlh/device/plc/job/CheckStartWeightTask.java

@@ -32,7 +32,7 @@ public class CheckStartWeightTask extends Task {
             String radarPointStatus = plcStatus.charAt(Integer.parseInt(radarPoint)) + "";
             EventBus eventBus = SpringUtil.getBean(EventBus.class);
             log.info("地磅是否有车,{}", CommonWeighbridgeHandler.hsCar);
-            if (radarPointStatus.equals("1") && CommonWeighbridgeHandler.hsCar) {
+            if (radarPointStatus.equals("1")) {
                 log.info("雷达触碰,开始称重");
                 eventBus.startEvent(ModuleEnum.WEIGHBRIDGE_MODULE.getModuleEn() + "." + WeighbridgeEvent.READ);
                 break;

+ 13 - 25
src/main/java/com/gzlh/device/plc/service/PLCService.java

@@ -23,29 +23,27 @@ import com.gzlh.device.print.factory.PrintFactory;
 import com.gzlh.device.weighbridge.handler.impl.CommonWeighbridgeHandler;
 import com.gzlh.entity.CommandBO;
 import com.gzlh.entity.ReqBO;
+import com.gzlh.utils.ModbusUtils;
 import com.gzlh.utils.WordHandlerUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 
+import javax.annotation.Resource;
+import java.time.chrono.IsoChronology;
+
 @Service
 @Slf4j
 public class PLCService {
-    private static final TimedCache<String, Integer> CACHE_MAP = CacheUtil.newTimedCache(10000);
-
     @Resource
     private EventBus eventBus;
 
     /**
-     * 试榜单
+     * 试榜单==确认
      */
     public void testPrint() {
-        if (!CacheManager.checkEnable(CacheManager.TEST_BTN_KEY)
-                || CACHE_MAP.get(CacheManager.TEST_BTN_KEY, true) != null) {
-            return;
-        }
-        CACHE_MAP.put(CacheManager.TEST_BTN_KEY, 1);
+
         ReqBO reqBO = EventDataManager.getCacheData();
         String bodyParams = JSONUtil.toJsonStr(reqBO);
         if (StrUtil.isEmpty(bodyParams)
@@ -56,16 +54,16 @@ public class PLCService {
         log.info("Req test weight:{}", bodyParams);
         String api = SysConfig.managerSetting.getServerUrl() + "/open/testWeight";
         try (HttpResponse response = HttpUtil.createPost(api).body(WordHandlerUtils.AESEncrypt(bodyParams)).execute()) {
-            log.info("提交港内地磅数据-返回结果:{}", response.body());
+            log.info("提交港内确认地磅数据-返回结果:{}", response.body());
             if (response.getStatus() == 200) {
+                LedOptions options = new LedOptions().setLine("03").setShowType("00");
                 JSONObject result = JSONUtil.parseObj(response.body());
                 String msg = result.getStr("msg");
                 Integer code = result.getInt("code");
                 if (code == 200) {
+                    EventDataManager.cleanData();
                     eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.RAILING_RISE);
                 }
-                LedOptions options = new LedOptions().setLine("04").setShowType("00");
-                options.setColor("01");
                 SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
                         .sendMsg(msg, options);
             }
@@ -76,11 +74,6 @@ public class PLCService {
      * 取消榜单
      */
     public void cancelPrint() {
-        if (!CacheManager.checkEnable(CacheManager.CANCEL_BTN_KEY)
-                || CACHE_MAP.get(CacheManager.CANCEL_BTN_KEY, true) != null) {
-            return;
-        }
-        CACHE_MAP.put(CacheManager.CANCEL_BTN_KEY, 1);
         ReqBO reqBO = EventDataManager.getCacheData();
         String bodyParams = JSONUtil.toJsonStr(reqBO);
         if (StrUtil.isEmpty(reqBO.getCarNo())) {
@@ -90,19 +83,19 @@ public class PLCService {
         log.info("Req cancel weight:{}", bodyParams);
         String api = SysConfig.managerSetting.getServerUrl() + "/open/cancelWeight";
         try (HttpResponse response = HttpUtil.createPost(api).body(WordHandlerUtils.AESEncrypt(bodyParams)).execute()) {
-            log.info("提交港内地磅数据-返回结果:{}", response.body());
+            log.info("提交港内取消地磅数据-返回结果:{}", response.body());
             if (response.getStatus() == 200) {
                 String body = response.body();
                 JSONObject jsonObject = JSONUtil.parseObj(body);
                 String data = WordHandlerUtils.AESDecrypt(jsonObject.get("data").toString());
                 log.info("data:{}", data);
                 CommandBO commandBO = JSONUtil.toBean(data, CommandBO.class);
-                LedOptions options = new LedOptions().setLine("04").setShowType("00");
+                LedOptions options = new LedOptions().setLine("03").setShowType("00");
                 int code = jsonObject.getInt("code");
                 if (code == 200) {
+                    EventDataManager.cleanData();
                     eventBus.startEvent(ModuleEnum.PLC_MODULE.getModuleEn() + "." + PLCEvent.RAILING_RISE);
                 }
-                options.setColor(code == 200 ? "02" : "01");
                 SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
                         .sendMsg(commandBO.getCommand().getExtra(), options);
             }
@@ -113,11 +106,6 @@ public class PLCService {
      * 打印榜单
      */
     public void reqPrint() {
-        if (!CacheManager.checkEnable(CacheManager.REQ_BTN_KEY)
-                || CACHE_MAP.get(CacheManager.REQ_BTN_KEY, true) != null) {
-            return;
-        }
-        CACHE_MAP.put(CacheManager.REQ_BTN_KEY, 1);
         SerialSetting serialSetting = SysConfig.serialSetting;
         PrintFactory printFactory = SystemObject.printFactory;
         printFactory.handler(serialSetting.getPrint().getBrand()).reqPrint();
@@ -129,7 +117,7 @@ public class PLCService {
      * @param event
      */
     public void startPlcEvent(String event) {
-        if (StrUtil.equalsIgnoreCase(event, PLCEvent.IDLE) && CommonWeighbridgeHandler.hsCar) {
+        if (StrUtil.equalsIgnoreCase(event,PLCEvent.IDLE)&& CommonWeighbridgeHandler.hsCar){
             return;
         }
         event = event.toUpperCase();

+ 2 - 1
src/main/java/com/gzlh/device/rfid/brand/ElectronBrandType.java

@@ -8,7 +8,8 @@ import lombok.Getter;
 public enum ElectronBrandType {
 
     RUI_BRAND(2000,"瑞德电子车牌"),
-    WANQUAN_BRAND(3000,"深圳万全vf-946Pro")
+    WANQUAN_BRAND(3000,"深圳万全vf-946Pro"),
+    ZH_BRAND(4000,"中科华益")
     ;
 
 

+ 3 - 4
src/main/java/com/gzlh/device/rfid/handler/impl/WanQuanHandler.java

@@ -51,7 +51,7 @@ public class WanQuanHandler implements IElectronHandler {
 
     @Override
     public void sendMsg(String msg) {
-        //log.info("send rfid msg:{}", msg);
+        log.info("send rfid msg:{}", msg);
         electronNettyConfig.send(msg);
     }
 
@@ -65,7 +65,6 @@ public class WanQuanHandler implements IElectronHandler {
        List<String>rfidList=new ArrayList<>();
         for (String msg : list) {
             msg = "F0" + msg;
-            log.info("{}", msg);
             if (StrUtil.length(msg) < 16) {
                 continue;
             }
@@ -73,10 +72,10 @@ public class WanQuanHandler implements IElectronHandler {
             if (StrUtil.isEmpty(data)) {
                 return;
             }
-            log.info("rfid msg:{}", msg);
+            //log.info("rfid msg:{}", msg);
             int len = Integer.parseInt(StrUtil.sub(data, 0, 2), 16);
             String dataHex = StrUtil.sub(data, 2, len * 2 + 2);
-            log.info("rfid dataHex :{}", dataHex);
+            //log.info("rfid dataHex :{}", dataHex);
             rfidList.add(dataHex);
         }
         String cacheKey=StrUtil.join(",",rfidList);

+ 110 - 0
src/main/java/com/gzlh/device/rfid/handler/impl/ZKRfidHandler.java

@@ -0,0 +1,110 @@
+package com.gzlh.device.rfid.handler.impl;
+
+import cn.hutool.cache.CacheUtil;
+import cn.hutool.cache.impl.TimedCache;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import com.gzlh.bus.EventBus;
+import com.gzlh.bus.EventDataManager;
+import com.gzlh.config.ModuleEnum;
+import com.gzlh.device.led.utils.CRC16;
+import com.gzlh.device.rfid.action.IElectronAction;
+import com.gzlh.device.rfid.brand.ElectronBrandType;
+import com.gzlh.device.rfid.client.ElectronNettyConfig;
+import com.gzlh.device.rfid.enums.CardType;
+import com.gzlh.device.rfid.event.RFIDDefaultEvent;
+import com.gzlh.device.rfid.handler.IElectronHandler;
+import com.gzlh.device.rfid.service.RfidService;
+import com.gzlh.utils.CRC16Util;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import javax.xml.bind.DatatypeConverter;
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Component
+public class ZKRfidHandler implements IElectronHandler {
+    private static final TimedCache<String, Integer> TIMED_CACHE = CacheUtil.newTimedCache(30000);
+
+    @Resource
+    private ElectronNettyConfig electronNettyConfig;
+    @Resource
+    private RfidService rfidService;
+    @Override
+    public ElectronBrandType brandType() {
+        return ElectronBrandType.ZH_BRAND;
+    }
+
+    @Override
+    public void handlerAction(String action) {
+        if (action.equals(IElectronAction.START_READ_CARD)) {
+            startToRead(CardType.TYPE_6C);
+        } else if (action.equals(IElectronAction.CHECK_HARBORPOLE_VERIFICATION)) {
+            rfidService.checkHarborpoleVerification();
+        } else if (action.equalsIgnoreCase(IElectronAction.FIND_CAR_NO_BY_RFID)) {
+            rfidService.findCarNoByRfid();
+        }
+    }
+
+    @Override
+    public void sendMsg(String msg) {
+        electronNettyConfig.send(msg);
+    }
+
+    @Override
+    public void handlerMsg(String msg) {
+        int len = msg.length();
+        String crcStr = StrUtil.sub(msg, len - 4, len);
+        String packetStr = StrUtil.sub(msg, 0, len - 4);
+        String checkCRC16 = CRC16Util.getCRC16Hex(packetStr);
+        if (!StrUtil.equals(crcStr, checkCRC16)) {
+            return;
+        }
+        String dataPack = StrUtil.subSuf(packetStr, 10);
+        //卡数量
+        int cardNum = Integer.parseInt(StrUtil.sub(packetStr, 8, 10));
+        List<String> cardList = new ArrayList<>();
+        int startIndex = 2;
+        for (int i = 0; i < cardNum; i++) {
+            String cardHex = StrUtil.sub(dataPack, startIndex, startIndex + 24);
+            startIndex += 26;
+            System.out.println(cardHex);
+            cardList.add(cardHex);
+        }
+        String cacheKey = StrUtil.join(",", cardList);
+        Integer count = TIMED_CACHE.get(cacheKey, true);
+        if (count != null && count == 5) {
+            log.info("rfid dataHex zk==== :{}", cacheKey);
+            EventBus eventBus = SpringUtil.getBean(EventBus.class);
+            EventDataManager.cacheData("eri", cacheKey);
+            eventBus.startEvent(ModuleEnum.ELECTRON_MODULE.getModuleEn() + "." + RFIDDefaultEvent.RFID_READ);
+            return;
+        }
+        if (count == null) {
+            count = 0;
+        }
+        count = count + 1;
+        TIMED_CACHE.put(cacheKey, count);
+
+        //13 00 01   01 01 0C   E2 00 00 00 1A 0C 02 72 18 20 EC B8    16EA
+        //20 00 01   01 02 0C   E200001D8817007817602D1F 0C E20000001A0C02721820ECB8    2813
+        //3A000101040CFEDC000000000000008102BA0CE200001B170902202610C3A60CE200001D8817007817602D1F0CE20000001A0C02721820ECB81F29
+        // log.info("接收到ZKRfid消息:{}", msg);
+        // TODO 卡号处理
+    }
+
+    @Override
+    public void setReaderCmdModule(boolean commandModule) {
+
+    }
+
+    @Override
+    public void startToRead(CardType cardType) {
+        String command = "040001DB4B";
+//        String command="040036E70E";
+        sendMsg(command);
+    }
+}

+ 8 - 3
src/main/java/com/gzlh/device/rfid/job/ElectronReadJob.java

@@ -3,6 +3,7 @@ package com.gzlh.device.rfid.job;
 import cn.hutool.core.thread.ThreadUtil;
 import com.gzlh.bus.SysConfig;
 import com.gzlh.config.SystemObject;
+import com.gzlh.config.dto.SerialSetting;
 import com.gzlh.device.rfid.action.IElectronAction;
 import lombok.extern.slf4j.Slf4j;
 
@@ -15,14 +16,18 @@ public class ElectronReadJob implements Runnable {
 
     @Override
     public void run() {
+        SerialSetting serialSetting = SysConfig.serialSetting;
+        if (!serialSetting.getElectron().getEnable()) {
+            return;
+        }
         log.info("start to read rfid");
-        int count = 15;
+        int count=15;
         while (count > 0) {
-            count--;
-            ThreadUtil.sleep(300); // 1s 读取一次卡
             SystemObject.electronFactory.handler(SysConfig.serialSetting.getElectron().getBrand())
                     .handlerAction(IElectronAction.START_READ_CARD);
+            count--;
         }
 
+
     }
 }

+ 4 - 10
src/main/java/com/gzlh/device/rfid/service/RfidService.java

@@ -46,28 +46,22 @@ public class RfidService {
         if (!ChannelCacheManager.stateEnable(SysConfig.channelSetting.getChannelCode())) {
             return;
         }
-        if (reqBO != null && StrUtil.isNotEmpty(reqBO.getCarNo())) {
-            return;
-        }
         String api = SysConfig.managerSetting.getServerUrl() + "/open/findCarNoByRfid?rfid=" + reqBO.getEri();
         try (HttpResponse response = HttpUtil.createGet(api).execute()) {
-            log.info("根据rfid查找车牌-返回结果,{}:{}", reqBO.getEri(),response.body());
+            log.info("根据rfid查找车牌-返回结果,{}:{}", reqBO.getEri(), response.body());
             if (response.getStatus() == 200) {
                 String body = response.body();
                 JSONObject resp = JSONUtil.parseObj(body);
                 int code = resp.getInt("code");
-                LedOptions options = new LedOptions().setLine("03").setShowType("00");
                 if (code == 200) {
                     String carNo = resp.getStr("carNo");
-                    if (StrUtil.isNotEmpty(carNo)) {
+                    //查询到车牌,且与当前光学车牌不一致时,则更新车牌并触发车牌识别事件
+                    if (StrUtil.isNotEmpty(carNo) && !StrUtil.equals(reqBO.getCarNo(), carNo)) {
                         EventDataManager.cacheData("carNo", carNo);
+                        EventDataManager.cacheData("gatherTime", new Date());
                         eventBus.startEvent(ModuleEnum.CAPTURE_MODULE.getModuleEn() + "." + CaptureEvent.CAPTURE_CAR_NO);
-                    } else {
-                        SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
-                                .sendMsg("IC卡" + reqBO.getEri() + "无对应车牌", options);
                     }
                 }
-
             }
         }
     }

+ 2 - 1
src/main/java/com/gzlh/device/rfid/utils/RFIDCommandUtils.java

@@ -12,6 +12,7 @@ import java.util.stream.Collectors;
 @Slf4j
 public class RFIDCommandUtils {
     /**
+     * 40 0004 00 0D00AF
      * header+length+address+cmd+params+check_num
      * Header:1个字节,包头,固定为40H。
      * Length:2个字节,包有效长度。该长度为后4个部分(Address+Cmd+Param+Check)的总字节数。先发高字节,后发低字节。例如:长度为270字节时,发送顺序为01H 0EH。
@@ -19,7 +20,7 @@ public class RFIDCommandUtils {
      * Cmd:1个字节,命令码。
      * Param:若干字节,命令参数,其长度随命令而变化。
      * Check:1个字节,校验和。Header+Length+Address+Cmd+Param求和后取反加1。
-     *
+     *40 000A 00 80 01000000000000 35
      * @return
      */
     public static String buildWanQuanCommand(String cmd, String[]params){

+ 64 - 22
src/main/java/com/gzlh/device/weighbridge/handler/impl/CommonWeighbridgeHandler.java

@@ -1,6 +1,7 @@
 package com.gzlh.device.weighbridge.handler.impl;
 
 import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.spring.SpringUtil;
 import cn.hutool.json.JSONUtil;
 import cn.hutool.log.StaticLog;
@@ -19,6 +20,7 @@ import java.util.*;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+
 @Slf4j
 public class CommonWeighbridgeHandler {
 
@@ -48,7 +50,7 @@ public class CommonWeighbridgeHandler {
      */
     public static void startToRead() {
         //不启用
-        if (!ChannelCacheManager.stateEnable(SysConfig.channelSetting.getChannelCode())){
+        if (!ChannelCacheManager.stateEnable(SysConfig.channelSetting.getChannelCode())) {
             return;
         }
         isStart = true;
@@ -65,47 +67,87 @@ public class CommonWeighbridgeHandler {
         @Override
         public void run() {
             int averaWeight = 0;
-            String deviceStatus = null;
             SerialSetting serialSetting = SysConfig.serialSetting;
-            SerialSetting.PlcDTO.StatusDTO status = serialSetting.getPlc().getStatus();
-            EventBus eventBus = SpringUtil.getBean(EventBus.class);
             while (time > 0) {
                 if (!isStart) {
                     return;
                 }
                 time = time - 1000;
 //                检查前后红外和雷达的触发情况
-  //              deviceStatus = new StringBuffer(DeviceCache.getPlcStatus()).reverse().toString();
+                //              deviceStatus = new StringBuffer(DeviceCache.getPlcStatus()).reverse().toString();
                 ThreadUtil.sleep(1000);
             }
             isStart = false;
             averaWeight = handlerWeight();
             log.info("----------weight---------:{}", averaWeight);
-            if (averaWeight == 0 || serialSetting.getWeighbridge().getMinKg() > averaWeight) {
-                //todo read timeout
-                //读取超时
-                DeviceCache.setInterrupt(true);
-                LedOptions options = new LedOptions().setLine("03").setColor("04").setShowType("0B");
-                SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
-                        .sendMsg("称重异常", options);
-                SystemObject.ledFactory.handler(SysConfig.serialSetting.getLed().getBrand())
-                        .sendMsg("请退出通道", options.setLine("04").setColor("01"));
-                return;
-            }
             EventDataManager.cacheData("weight", averaWeight);
         }
 
         private int handlerWeight() {
-            List<Integer>list=WEIGHT_CACHE;
+            List<Integer> list = WEIGHT_CACHE;
             log.info("w:{}", JSONUtil.toJsonStr(list));
-            if (list.isEmpty()){
+            if (list.isEmpty()) {
                 return 0;
             }
-            Collections.sort(list);
-            int size=list.size();
-            int index=( size*3)/4;
-           return list.get(index);
+            int size = list.size();
+            int index = (size * 3) / 4;
+            return list.get(index);
         }
+
+        public static int findClosestWithHighestFrequency(List<Integer> numbers) {
+            if (numbers == null || numbers.size() == 0) {
+                throw new IllegalArgumentException("数组不能为空");
+            }
+
+            // 计算平均值
+            double sum = 0;
+            for (int number : numbers) {
+                sum += number;
+            }
+            double average = sum / numbers.size();
+
+            // 使用Map存储每个数字的出现次数
+            Map<Integer, Integer> frequencyMap = new HashMap<>();
+            // 使用Map存储每个数字与平均值的误差
+            Map<Integer, Double> differenceMap = new HashMap<>();
+
+            // 计算每个数字的频率和误差
+            for (int number : numbers) {
+                frequencyMap.put(number, frequencyMap.getOrDefault(number, 0) + 1);
+                differenceMap.put(number, Math.abs(number - average));
+            }
+
+            int result = numbers.get(0);
+            double minDifference = Double.MAX_VALUE;
+            int maxFrequency = 0;
+
+            // 遍历所有不同的数字
+            for (int number : frequencyMap.keySet()) {
+                double currentDifference = differenceMap.get(number);
+                int currentFrequency = frequencyMap.get(number);
+
+                // 如果找到误差更小的数字
+                if (currentDifference < minDifference) {
+                    minDifference = currentDifference;
+                    maxFrequency = currentFrequency;
+                    result = number;
+                }
+                // 如果误差相同,比较频率
+                else if (currentDifference == minDifference && currentFrequency > maxFrequency) {
+                    maxFrequency = currentFrequency;
+                    result = number;
+                }
+            }
+
+            return result;
+        }
+    }
+
+    public static void main(String[] args) {
+        String str = "51200,51180,51100,51160,51140,51160,51160";
+        List<Integer> list = StrUtil.split(str, ",").stream().map(s -> Integer.parseInt(s)).collect(Collectors.toList());
+        System.out.println(list.stream().collect(Collectors.averagingLong(Integer::intValue)));
+        System.out.println(WatchThread.findClosestWithHighestFrequency(list));
     }
 
 }

+ 0 - 17
src/main/java/com/gzlh/device/weighbridge/handler/impl/WeighbridgeHandlerTuoLiDuo.java

@@ -103,23 +103,6 @@ public class WeighbridgeHandlerTuoLiDuo implements IWeighbridgeHandler {
     }
 
 
-    /**
-     * 处理10开头 00结尾的数据
-     *
-     * @param msg
-     */
-    private static int handlerModuleOne(String msg) {
-        if (!StrUtil.startWith(msg, "10")) {
-            return 0;
-        }
-        msg = StrUtil.replace(msg, " ", "");
-        if (StrUtil.contains(msg, "0010")) {
-            msg = StrUtil.split(msg, "0010").get(0) + "00";
-        }
-        String weightStr = StrUtil.sub(msg, 2, msg.length() - 2);
-        return Integer.parseInt(weightStr);
-    }
-
     private static int handlerModule(String msg) {
         msg = StrUtil.trim(msg);
         msg = StrUtil.replace(msg, "0018", "0010");

+ 6 - 1
src/main/java/com/gzlh/entity/AddFaceBO.java

@@ -1,13 +1,18 @@
 package com.gzlh.entity;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 
+import java.util.Date;
+
 @Data
 public class AddFaceBO {
     private String ip;
     private String channelCode;
     private String no;
     private String name;
-    private Integer command;
     private String base64;
+    private Integer command;
+
+    private String expireTime;
 }

+ 14 - 0
src/main/java/com/gzlh/entity/CarCaptureBO.java

@@ -0,0 +1,14 @@
+package com.gzlh.entity;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@Accessors(chain = true)
+public class CarCaptureBO {
+    private String channelCode; //通道号
+    private String carNo; //车牌号
+
+    private String carImage;//抓拍照片(Base64字符串,第一次传即可)
+    private String identifyTime; //车牌识别时间
+}

+ 16 - 3
src/main/java/com/gzlh/entity/ReqBO.java

@@ -45,6 +45,7 @@ public class ReqBO implements Serializable {
      * 箱数据
      */
     private Box box;
+    private Face face;
 
     /**
      * 采集时间
@@ -83,22 +84,34 @@ public class ReqBO implements Serializable {
         private String boxNum="";
     }
 
+
+
+    @Data
+    @Accessors(chain = true)
+    public static class Face{
+        private String employeeNo;
+        private String ip;
+        private Date time;
+        private String channelCode;
+        private boolean pass;
+    }
+
     public static void main(String[] args) {
         //进
 //        String placeCode="TSI1";
         //出
 //        String placeCode="TSO10";
         //内港
-        String placeCode="SBL2";
+        String placeCode="TSN5";
         String carNo="桂E01287";
         Double weight=5000D;
         ReqBO reqBO=new ReqBO();
         reqBO.setChannelCode(placeCode).setWeight(weight)
-                .setCarNo(carNo).setId("12753")
+                .setCarNo(carNo).setId("12763")
                 .setGatherTime(new Date())
-                .setId("12753")
                 .setEri("G1D5425873");
         String str=JSONUtil.toJsonStr(reqBO);
+//        System.out.println(str);
         System.out.println(WordHandlerUtils.AESEncrypt(str));
     }
 

+ 16 - 17
src/main/java/com/gzlh/startup/StartupRunner.java

@@ -3,22 +3,20 @@ package com.gzlh.startup;
 import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.RandomUtil;
 import com.gzlh.background.BackgroundClientNetty;
+import com.gzlh.bus.EventDataManager;
 import com.gzlh.bus.SysConfig;
 import com.gzlh.bus.task.CheckInitTask;
 import com.gzlh.config.SystemObject;
-import com.gzlh.config.dto.CaputreSetting;
-import com.gzlh.config.dto.FaceDTO;
-import com.gzlh.config.dto.FaceListDTO;
-import com.gzlh.config.dto.SerialSetting;
+import com.gzlh.config.dto.*;
 import com.gzlh.config.ModuleEnum;
-import com.gzlh.bus.EventBus;
 import com.gzlh.config.hksdk.HCNetSDK;
 import com.gzlh.config.hksdk.HkUtils;
 import com.gzlh.config.hksdk.bo.HKCacheManager;
 import com.gzlh.config.task.TaskService;
 import com.gzlh.device.capture.brand.CaptureBrandType;
-import com.gzlh.device.face.CheckFaceGateOnlineTask;
-import com.gzlh.device.face.LoginFaceGate;
+import com.gzlh.device.face.task.CheckFaceGateOnlineTask;
+import com.gzlh.device.face.service.LoginFaceGate;
+import com.gzlh.device.passport.PassportReadClient;
 import com.gzlh.device.print.client.CheckPrintOnlineTask;
 import com.gzlh.device.rfid.client.ElectronNettyConfig;
 import com.gzlh.device.led.client.LedNettyConfig;
@@ -67,7 +65,9 @@ public class StartupRunner implements CommandLineRunner {
 
     @Override
     public void run(String... args) throws Exception {
-
+        if (SysConfig.managerSetting.isEnable()) {
+            ThreadUtil.execute(() -> backgroundClientNetty.connect());
+        }
         SerialSetting serialSetting = SysConfig.serialSetting;
         if (serialSetting.getWeighbridge().getEnable()) {
             ThreadUtil.execute(() -> weighbridgeNettyConfig.connect());
@@ -92,14 +92,11 @@ public class StartupRunner implements CommandLineRunner {
                     .setReaderCmdModule(true);
             SystemObject.electronFactory.handler(SysConfig.serialSetting.getElectron().getBrand())
                     .startToRead(CardType.TYPE_6C);
-            ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
+//            ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
 //            long initialDelay = 0;
-//            long period = 1; // 5秒
+//            long period = 5; // 5秒
 //            scheduler.scheduleAtFixedRate(new ElectronReadJob(), initialDelay, period, TimeUnit.SECONDS);
         }
-        if (SysConfig.managerSetting.isEnable()) {
-            ThreadUtil.execute(() -> backgroundClientNetty.connect());
-        }
 
         CaputreSetting caputreSetting = SysConfig.caputreSetting;
         if (caputreSetting.isEnable()) {
@@ -122,12 +119,14 @@ public class StartupRunner implements CommandLineRunner {
         }
 
         FaceListDTO faceListDTO = SysConfig.faceDTO;
-        if (faceListDTO.getEnable()) {
-            List<FaceDTO> faceDTOList = faceListDTO.getFace();
+        if (faceListDTO!=null&&faceListDTO.getEnable()) {
+            List<Face> faceDTOList = faceListDTO.getFaceList();
             faceDTOList.forEach(faceDTO -> ThreadUtil.execute(new LoginFaceGate(faceDTO)));
-            ThreadUtil.execute(new CheckFaceGateOnlineTask());
         }
-
+        PassportSetting passportSetting=SysConfig.passportSetting;
+        if (passportSetting!=null&&passportSetting.isEnable()){
+            new PassportReadClient("ws://"+passportSetting.getHost()+":"+passportSetting.getPort()+"/echo").connectClient();
+        }
 
     }
 

+ 96 - 0
src/main/java/com/gzlh/utils/CRC16Util.java

@@ -0,0 +1,96 @@
+package com.gzlh.utils;
+
+import cn.hutool.core.util.StrUtil;
+
+import javax.xml.bind.DatatypeConverter;
+
+public class CRC16Util {
+    private static final int PRESET_VALUE = 0xFFFF;
+    private static final int POLYNOMIAL = 0x8408;
+
+    /**
+     * 计算CRC16校验值
+     * @param bytes 需要计算的字节数组
+     * @return CRC16校验值
+     */
+    /**
+     * 计算CRC16校验值
+     * @param bytes 需要计算的字节数组
+     * @return CRC16校验值
+     */
+    /**
+     * 计算CRC16校验值
+     *
+     * @param bytes 需要计算的字节数组
+     * @return CRC16校验值
+     */
+    public static int calculateCRC16(byte[] bytes) {
+        int crcValue = PRESET_VALUE;
+
+        for (byte b : bytes) {
+            // 将byte转换为无符号整数
+            int unsignedByte = b & 0xFF;
+            crcValue = crcValue ^ unsignedByte;
+
+            for (int j = 0; j < 8; j++) {
+                if ((crcValue & 0x0001) != 0) {
+                    crcValue = (crcValue >> 1) ^ POLYNOMIAL;
+                } else {
+                    crcValue = crcValue >> 1;
+                }
+            }
+        }
+
+        return swapCRC16Bytes(crcValue);
+    }
+
+    /**
+     * 将CRC16的高低位进行交换
+     *
+     * @param crc 原始CRC16值
+     * @return 交换后的CRC16值
+     */
+    public static int swapCRC16Bytes(int crc) {
+        // 获取高字节和低字节
+        int highByte = (crc >> 8) & 0xFF;  // 右移8位得到高字节
+        int lowByte = crc & 0xFF;          // 与0xFF相与得到低字节
+
+        // 交换高低字节
+        return (lowByte << 8) | highByte;
+    }
+
+    /**
+     * 获取CRC16校验值的十六进制字符串
+     *
+     * @param bytes 需要计算的字节数组
+     * @return CRC16校验值的十六进制字符串
+     */
+    public static String getCRC16Hex(byte[] bytes) {
+        int crc = calculateCRC16(bytes);
+        return String.format("%04X", crc);
+    }
+
+    public static String getCRC16Hex(String hexStr) {
+        int crc = calculateCRC16(DatatypeConverter.parseHexBinary(hexStr));
+        return String.format("%04X", crc);
+    }
+
+
+    // 测试方法
+    public static void main(String[] args) {
+        System.out.println("E20000001A0C02721820ECB8".length());
+        // 测试数据
+        String command = "2D000101030CE200001B170902202610C3A60CFEDC000000000000008102BA0CE200001D8817007817602D1F793F";
+        int len = command.length();
+        String crcStr = StrUtil.sub(command, len - 4, len);
+        String packetStr = StrUtil.sub(command, 0, len - 4);
+        String dataPack=StrUtil.subSuf(packetStr,10);
+        int cardNum=Integer.parseInt(StrUtil.sub(packetStr,8,10));
+        int startIndex=2;
+        for (int i = 0; i < cardNum; i++) {
+            String cardHex = StrUtil.sub(dataPack, startIndex, startIndex+24);
+            startIndex += 26;
+            System.out.println(cardHex);
+        }
+    }
+}

+ 1 - 1
src/main/java/com/gzlh/utils/DeviceCache.java

@@ -26,7 +26,7 @@ public class DeviceCache {
 
     static boolean interrupt = false;
 
-    static String plcStatus = null;
+    static String plcStatus = "";
 
     public static void setPlcStatus(String status) {
         plcStatus = status;

+ 6 - 0
src/main/java/com/gzlh/utils/FileUtils.java

@@ -1,6 +1,8 @@
 package com.gzlh.utils;
 
 
+import cn.hutool.core.io.FileUtil;
+
 import java.io.*;
 import java.net.URL;
 import java.net.URLConnection;
@@ -125,4 +127,8 @@ public class FileUtils {
 
     }
 
+    public static void main(String[] args) {
+        System.out.println(cn.hutool.core.codec.Base64.encode(new File("E:\\111.jpg")));
+    }
+
 }

+ 5 - 3
src/main/resources/application.yml

@@ -22,7 +22,9 @@ hk:
 
 external:
     base-url: http://external-service.com
-    status-callback-path: ${external.service}/api/barrier/status-callback
     status-report-interval: 30000
-    face-status-callback-path:  ${external.service}/api/face-status-callback
-    face-open-gate-path:  ${external.service}/api/face-open-callback
+    status-callback-path: ${external.base-url}/api/barrier/status-callback
+    face-status-callback-path:  ${external.base-url}/api/face-status-callback
+    face-open-gate-path:  ${external.base-url}/api/channel/face-open-callback
+    sub-car-validate-path:  ${external.base-url}/api/channel/carNoIdentify
+