Explorar el Código

泥人继电器

linfutong hace 2 años
padre
commit
3cfe17bf6a
Se han modificado 24 ficheros con 784 adiciones y 78 borrados
  1. 1 0
      zd-common/common-swagger/src/main/java/com/zd/common/swagger/config/Knife4jConfiguration.java
  2. 2 0
      zd-common/common-swagger/src/main/java/com/zd/common/swagger/config/SwaggerProperties.java
  3. 6 0
      zd-model/src/main/java/com/zd/model/constant/CacheConstants.java
  4. 166 43
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/face/controller/FaceApi.java
  5. 83 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/constant/RelayConstants.java
  6. 22 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/event/LabRelayNrStatusEvent.java
  7. 59 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/event/LabRelayNrStatusListener.java
  8. 21 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/event/LabRelayRegisterEvent.java
  9. 42 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/event/LabRelayRegisterListener.java
  10. 44 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/event/RedisExpiredRelayListener.java
  11. 7 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/mapper/LabRelayMapper.java
  12. 43 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/mqtt/entiy/LabRelayStatus.java
  13. 1 1
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/netty/ChannelMap.java
  14. 24 27
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/netty/NettyServerHandler.java
  15. 14 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/ILabHardwareService.java
  16. 7 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/ILabRelayService.java
  17. 21 3
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/impl/LabExitLineVertexServiceImpl.java
  18. 22 3
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/impl/LabExitPointRelayServiceImpl.java
  19. 21 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/impl/LabHardwareServiceImpl.java
  20. 11 1
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/impl/LabRelayServiceImpl.java
  21. 16 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/socket/constant/SocketTypes.java
  22. 41 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/socket/runner/TCPServer.java
  23. 106 0
      zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/utils/RelayUtils.java
  24. 4 0
      zd-modules/zd-modules-laboratory/src/main/resources/mapper/laboratory/LabRelayMapper.xml

+ 1 - 0
zd-common/common-swagger/src/main/java/com/zd/common/swagger/config/Knife4jConfiguration.java

@@ -48,6 +48,7 @@ public class Knife4jConfiguration {
         return new Docket(DocumentationType.SWAGGER_2)
                 .useDefaultResponseMessages(false)
                 .apiInfo(apiInfo())
+                .enable(swaggerProperties.getEnabled())
                 .select()
                 .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
                 .paths(PathSelectors.any())

+ 2 - 0
zd-common/common-swagger/src/main/java/com/zd/common/swagger/config/SwaggerProperties.java

@@ -1,5 +1,6 @@
 package com.zd.common.swagger.config;
 
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
 
@@ -12,6 +13,7 @@ public class SwaggerProperties {
     /**
      * 是否开启swagger
      */
+    @Value("${knife4j.enable}")
     private Boolean enabled;
 
     /**

+ 6 - 0
zd-model/src/main/java/com/zd/model/constant/CacheConstants.java

@@ -23,6 +23,12 @@ public interface CacheConstants {
 
 
     /**
+     * 继电器前缀
+     */
+    String RELAY_DATA_KEY = "relay_data_key:";
+
+
+    /**
      * 传感器状态前缀
      */
     String RELAY_STATUS_KEY = "sensor_status_key:";

+ 166 - 43
zd-modules/zd-algorithm/src/main/java/com/zd/alg/face/controller/FaceApi.java

@@ -26,8 +26,10 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.*;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.LongAdder;
+import java.util.stream.Collectors;
 
 /**
  * @Author: zhoupan
@@ -41,6 +43,11 @@ import java.util.Map;
 @RequestMapping("/faceApi")
 public class FaceApi {
 
+    private static final int taskSize = 50;
+
+    private static ExecutorService pool = Executors.newFixedThreadPool(taskSize);
+
+
     Logger logger = LoggerFactory.getLogger(FaceApi.class);
 
     @Autowired
@@ -74,6 +81,27 @@ public class FaceApi {
         return ResultData.success(faceFeature.getFeatureData());
     }
 
+
+    @ApiOperation("检测是否是人脸")
+    @PostMapping("/detectFaces")
+    public ResultData detectFaces(@RequestParam("file") MultipartFile file) throws IOException {
+        File fileToFile = null;
+        try {
+            fileToFile = FileUtil.multipartFileToFile(file);
+            ImageInfo  imageInfo = faceService.getImageInfo(fileToFile);
+            List<FaceInfo> faceInfos = faceService.faceDetect(imageInfo);
+            if(null==faceInfos || faceInfos.size()==0){
+                return ResultData.fail("请讲脸放到摄像头正中央!");
+            }
+            return ResultData.success(faceInfos);
+        } finally {
+            if (fileToFile != null) {
+                fileToFile.delete();
+            }
+        }
+    }
+
+
     /**
      * 人脸比较
      *
@@ -96,6 +124,49 @@ public class FaceApi {
         }
     }
 
+    /**
+     * 人脸比较
+     *
+     * @return
+     */
+    @ApiOperation("人脸比较")
+    @PostMapping("/newCompare")
+    public ResultData newCompare(@RequestParam("file") MultipartFile file,FaceCompare faceCompare) throws IOException{
+
+        ImageInfo imageInfo;
+        File file1 = null;
+        try {
+            file1 = FileUtil.multipartFileToFile(file);
+            imageInfo = faceService.getImageInfo(file1);
+        } finally {
+            if (file1 != null) {
+                file1.delete();
+            }
+        }
+        List<FaceInfo> faceInfos = faceService.faceDetect(imageInfo);
+        if(null==faceInfos || faceInfos.size()==0){
+            return ResultData.fail("识别中");
+        }
+        FaceFeature faceFeature = faceService.faceFeature(imageInfo, faceInfos);
+        if(StringUtils.isNotNull(faceFeature.getFeatureData())){
+            logger.info("====人脸比较====");
+            R<LabStudentsInfo> info = remoteStudentsService.getInfo(faceCompare.getUserId());
+            if (info.getCode() == 200 && info.getData() != null) {
+                logger.info("====人脸data组装====");
+                FaceFeature target = new FaceFeature(info.getData().getFaceFeature());
+                FaceFeature source = new FaceFeature(faceFeature.getFeatureData());
+                Boolean compore = faceService.compore(target, source);
+                logger.info("====compore====" + compore);
+                return ResultData.result(compore, () -> "人脸对比不符!");
+            } else {
+                return ResultData.fail("未获取到对比数据!:" + info.getMsg());
+            }
+        }else{
+            return ResultData.fail("未获取到特征码!");
+        }
+    }
+
+
 
     /**
      * 人脸比较
@@ -104,54 +175,78 @@ public class FaceApi {
      */
     @ApiOperation("人脸比较")
     @PostMapping("/multiCompare")
-    public ResultData multiFaceDetection(@RequestBody FaceCompare faceCompare) {
+    public ResultData multiFaceDetection(@RequestBody FaceCompare faceCompare) throws ExecutionException, InterruptedException {
         logger.info("====人脸比较====");
-        Integer isDutyUser=0;
+        long time=System.currentTimeMillis();
         ResultData<List<LabSysUserInfo>> infoList = remoteStudentsService.getFaceBySecuritySubjectId(faceCompare.getLabId());
-        if (infoList.getCode() == 200 && infoList.getData() != null) {
-            logger.info("====人脸data组装====");
-            for(LabSysUserInfo info:infoList.getData()){
-                FaceFeature target = new FaceFeature(info.getFaceFeature());
-                FaceFeature source = new FaceFeature(faceCompare.getData());
-                Boolean compore = faceService.compore(target, source);
-                if(compore){
-                    String userType=info.getUserType();
-                    Integer isWhite=info.getIsWhite();
-                    //如果是学生 或者白名单的老师 进二类页面
-                    if(userType.equals("22") || (userType.equals("11") && isWhite==0)){
-                        info.setPageType(2);
-                    }
-                    ResultData resultData =remoteDutyService.isAdminOrSafeUser(faceCompare.getLabId(),info.getUserId());
-                    //一类首页对应身份为白名单老师、实验室负责人、安全责任人
-                    if(Integer.parseInt(String.valueOf(resultData.getData()))>0 || (userType.equals("11") && isWhite==1)){
-                        info.setPageType(1);
-                    }
-                    info.setFaceFeature(null);
-                    String dateTime = DateUtils.getDate();
-                    ResultData dutyUserData = remoteDutyService.selectDutyUser(faceCompare.getLabId(),dateTime);
-                    //判断是否当天值班
-                    if(null==dutyUserData && dutyUserData.getCode()!= HttpStatus.SUCCESS){
-                        return ResultData.fail("获取值班人员识别!");
-                    }
-                    List<Map<String,Object>> dutyList= (List<Map<String, Object>>) dutyUserData.getData();
-                    for(Map<String,Object> dutyMap:dutyList){
-                        String userObj=String.valueOf(dutyMap.get("userId"));
-                        if(StringUtils.isNotEmpty(userObj) && StringUtils.isNotNull(userObj)){
-                            if(Long.parseLong(userObj)==info.getUserId()){
-                                isDutyUser=1;
-                                break;
+        if(infoList.getCode() == 200 && infoList.getData() != null){
+            List<Future> list = Optional.ofNullable(infoList.getData()).orElseGet(Collections::emptyList)
+                    .stream()
+                    .map(a->{
+                        Future f = pool.submit(new Callable<Object>() {
+                            @Override
+                            public Object call() throws Exception {
+                                return getMultiFaceDetection(a,faceCompare);
                             }
-                        }
+                        });
+                        return f;
+                    })
+                    .collect(Collectors.toList());
+            for(Future future:list){
+                ResultData r=(ResultData)future.get();
+                if(r.getCode()==200){
+                    long time2=System.currentTimeMillis();
+                    System.out.println("执行时间:"+(time2-time));
+                    return r;
+                }
+            }
+            //pool.shutdown();
+        }
+        return ResultData.fail("未获取实验室安全准入人脸数据!");
+    }
+
+    private ResultData getMultiFaceDetection(LabSysUserInfo info,FaceCompare faceCompare){
+        Integer isDutyUser=0;
+        FaceFeature target = new FaceFeature(info.getFaceFeature());
+        FaceFeature source = new FaceFeature(faceCompare.getData());
+        Boolean compore = faceService.compore(target, source);
+        if(compore){
+            String userType=info.getUserType();
+            Integer isWhite=info.getIsWhite();
+            if(StringUtils.isNull(userType)){
+                return ResultData.fail("用户不存在!");
+            }
+            //如果是学生 或者白名单的老师 进二类页面
+            if(userType.equals("22") || (userType.equals("11") && isWhite==0)){
+                info.setPageType(2);
+            }
+            ResultData resultData =remoteDutyService.isAdminOrSafeUser(faceCompare.getLabId(),info.getUserId());
+            //一类首页对应身份为白名单老师、实验室负责人、安全责任人
+            if(Integer.parseInt(String.valueOf(resultData.getData()))>0 || (userType.equals("11") && isWhite==1)){
+                info.setPageType(1);
+            }
+            info.setFaceFeature(null);
+            String dateTime = DateUtils.getDate();
+            ResultData dutyUserData = remoteDutyService.selectDutyUser(faceCompare.getLabId(),dateTime);
+            //判断是否当天值班
+            if(null==dutyUserData && dutyUserData.getCode()!= HttpStatus.SUCCESS){
+                return ResultData.fail("获取值班人员识别!");
+            }
+            List<Map<String,Object>> dutyList= (List<Map<String, Object>>) dutyUserData.getData();
+            for(Map<String,Object> dutyMap:dutyList){
+                String userObj=String.valueOf(dutyMap.get("userId"));
+                if(StringUtils.isNotEmpty(userObj) && StringUtils.isNotNull(userObj)){
+                    if(Long.parseLong(userObj)==info.getUserId()){
+                        isDutyUser=1;
+                        break;
                     }
-                    info.setIsDutyUser(isDutyUser);
-                    logger.info("====compore====" +"对比成功用户ID:"+info.getUserId());
-                    return ResultData.success(info);
                 }
             }
-            return ResultData.fail("未获取实验室安全准入人脸数据!");
-        } else {
-            return ResultData.fail("未获取实验室安全准入人脸数据!");
+            info.setIsDutyUser(isDutyUser);
+            logger.info("====compore====" +"对比成功用户ID:"+info.getUserId());
+            return ResultData.success(info);
         }
+        return ResultData.fail("未获取实验室安全准入人脸数据!");
     }
 
 
@@ -170,4 +265,32 @@ public class FaceApi {
             e.printStackTrace();
         }
     }
+
+    public static void main(String[] args) throws ExecutionException, InterruptedException {
+        long time=System.currentTimeMillis();
+        ExecutorService pool = Executors.newFixedThreadPool(100);
+        List<String> list=new ArrayList();
+        for(int i=0;i<100;i++){
+            list.add("姓名:"+i);
+        }
+        List<Future> lists = Optional.ofNullable(list).orElseGet(Collections::emptyList)
+                    .stream()
+                    .map(a->{
+                        Future f = pool.submit(new Callable<Object>() {
+                            @Override
+                            public Object call() throws Exception {
+                                Thread.sleep(1000);
+                                return a;
+                            }
+                        });
+                        return f;
+                    })
+                    .collect(Collectors.toList());
+            for(Future future:lists){
+                String r=(String)future.get();
+                System.out.println(r);
+            }
+        long time2=System.currentTimeMillis();
+        System.out.println(time2-time);
+    }
 }

+ 83 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/constant/RelayConstants.java

@@ -0,0 +1,83 @@
+package com.zd.laboratory.constant;
+
+/**
+ * @Author donggaosheng
+ * @Date 2023 04 26 13 35
+ * @description 泥人继电器常量类
+ **/
+public class RelayConstants {
+    /**
+     * 回复指令
+     */
+    public static final String AT_ACK = "AT+ACK \r\n";
+
+    /**
+     * 开关指令
+     */
+    public static final String AT_STACH = "AT+STACH";
+
+
+    /**
+     * 开关指令
+     */
+    public static final String AT_STACH_ALL = "AT+STACH0=?\r\n";
+
+    /**
+     * 开关指令字符
+     */
+    public static final String AT_STACH_ALL_STR = "AT+STACH0=?";
+
+
+    /**
+     * 开关指令
+     */
+    public static final String STACH = "STACH";
+
+
+    /**
+     * 开关指令返回
+     */
+    public static final String PLUS_STACH = "+STACH";
+
+
+    /**
+     * 空格换行
+     */
+    public static final String SPACE_WRAP = "\r\n";
+
+    /**
+     * 打开状态
+     */
+    public static final Integer AT_OPEN = 1;
+
+    /**
+     * 关闭状态
+     */
+    public static final Integer AT_CLOSE = 0;
+
+
+    /**
+     * 打开状态
+     */
+    public static final String AT_OPEN_STR = "01";
+
+    /**
+     * 关闭状态
+     */
+    public static final String AT_CLOSE_STR = "00";
+
+    /**
+     * 泥人科技离线
+     */
+    public static final String AT_RELAY_DATA = "at_relay_data:";
+
+    /**
+     * 换行符
+     */
+    public static final String AT_SPLITE = "\r\n";
+
+    /**
+     * 1类型表示继电器
+     */
+    public static final Integer LAB_RELAY_TYPE = 1;
+}

+ 22 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/event/LabRelayNrStatusEvent.java

@@ -0,0 +1,22 @@
+package com.zd.laboratory.event;
+
+import com.zd.laboratory.mqtt.entiy.LabRelayStatus;
+
+/**
+ * @Author donggaosheng
+ * @Date 2023-04-28
+ * @description 继电器状态
+ **/
+public class LabRelayNrStatusEvent extends HardwareStatusEvent{
+
+    public LabRelayNrStatusEvent(LabRelayStatus source) {
+        super(source);
+    }
+
+    @Override
+    public LabRelayStatus getSource() {
+        return (LabRelayStatus)super.getSource();
+    }
+
+
+}

+ 59 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/event/LabRelayNrStatusListener.java

@@ -0,0 +1,59 @@
+package com.zd.laboratory.event;
+
+import cn.hutool.core.collection.CollUtil;
+import com.zd.laboratory.domain.LabHardware;
+import com.zd.laboratory.mapper.LabHardwareMapper;
+import com.zd.laboratory.mqtt.entiy.EquipmentStatus;
+import com.zd.laboratory.mqtt.entiy.LabRelayStatus;
+import com.zd.laboratory.mqtt.service.impl.SubMessageSendManager;
+import com.zd.laboratory.service.ILabHardwareService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * @Author donggaosheng
+ * @Date 2023-04-28
+ * @description 继电器状态
+ **/
+@Component
+public class LabRelayNrStatusListener implements ApplicationListener<LabRelayNrStatusEvent> {
+
+    @Autowired
+    ILabHardwareService labHardwareService;
+
+    @Autowired
+    LabHardwareMapper labHardwareMapper;
+
+    @Autowired
+    SubMessageSendManager subMessageSendManager;
+
+    @Override
+    public void onApplicationEvent(LabRelayNrStatusEvent labRelayNrStatusEvent) {
+        LabRelayStatus source = labRelayNrStatusEvent.getSource();
+        int i = labHardwareService.updateNrRelayStatus(source);
+        if (i > 0) {
+            //这里的前提是继电器下的设备都是属于一个实验室的 切记!!!
+            LabHardware labHardware = new LabHardware();
+            labHardware.setRelayCode(source.getNum());
+            List<LabHardware> labHardwareVOS = labHardwareMapper.selectLabHardwareStatusByRelay(labHardware);
+            List<EquipmentStatus> collect = Optional.ofNullable(labHardwareVOS)
+                    .orElseGet(Collections::emptyList)
+                    .stream()
+                    .map(a -> {
+                        EquipmentStatus equipmentStatus = new EquipmentStatus();
+                        equipmentStatus.setNum(a.getId().toString());
+                        equipmentStatus.setHardwareOperate(a.getOperate());
+                        return equipmentStatus;
+                    }).collect(Collectors.toList());
+            if (CollUtil.isNotEmpty(collect)) {
+                subMessageSendManager.sendHardwareUpdate(labHardwareVOS.get(0), collect, 1);
+            }
+        }
+    }
+}

+ 21 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/event/LabRelayRegisterEvent.java

@@ -0,0 +1,21 @@
+package com.zd.laboratory.event;
+
+import com.zd.laboratory.domain.LabRelay;
+import com.zd.laboratory.mqtt.entiy.EquipmentStatus;
+
+/**
+ * @Author donggaosheng
+ * @Date 2023-04-28
+ * @description 继电器注册
+ **/
+public class LabRelayRegisterEvent extends  HardwareStatusEvent{
+
+    public LabRelayRegisterEvent(Object source) {
+        super(source);
+    }
+
+    @Override
+    public LabRelay getSource() {
+        return (LabRelay)super.getSource();
+    }
+}

+ 42 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/event/LabRelayRegisterListener.java

@@ -0,0 +1,42 @@
+package com.zd.laboratory.event;
+
+import com.zd.common.core.redis.RedisService;
+import com.zd.laboratory.constant.RelayConstants;
+import com.zd.laboratory.domain.LabRelay;
+import com.zd.laboratory.service.ILabRelayService;
+import com.zd.laboratory.service.impl.LabRelayServiceImpl;
+import com.zd.model.constant.CacheConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author donggaosheng
+ * @Date 2023-04-28
+ * @description 继电器注册监听类
+ **/
+@Component
+public class LabRelayRegisterListener implements ApplicationListener<LabRelayRegisterEvent> {
+
+    @Autowired
+    private RedisService redisService;
+    @Autowired
+    private ILabRelayService labRelayService;
+
+    @Override
+    public void onApplicationEvent(LabRelayRegisterEvent labRelayRegisterEvent) {
+        LabRelay labRelay=labRelayRegisterEvent.getSource();
+        labRelay.setType(RelayConstants.LAB_RELAY_TYPE);
+        String relayCode=labRelay.getCode();
+        String key=CacheConstants.RELAY_DATA_KEY+relayCode;
+        if(null==redisService.getCacheObject(key)){
+            int num=labRelayService.selectLabRelayIsExit(relayCode);
+            if(num==0){
+                labRelayService.insertLabRelay(labRelay);
+            }
+            redisService.setCacheObject(key,relayCode,60L, TimeUnit.MINUTES);
+        }
+    }
+}

+ 44 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/event/RedisExpiredRelayListener.java

@@ -0,0 +1,44 @@
+package com.zd.laboratory.event;
+
+import com.zd.common.core.redis.RedisService;
+import com.zd.common.core.utils.SpringUtils;
+import com.zd.laboratory.constant.RelayConstants;
+import com.zd.laboratory.mqtt.entiy.LabRelayStatus;
+import com.zd.model.enums.HardwareOperate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.redis.connection.Message;
+import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Author donggaosheng
+ * @Date 2023-05-04
+ * @description 监听继电器失效
+ **/
+@Component
+public class RedisExpiredRelayListener extends KeyExpirationEventMessageListener {
+
+    private static final Logger logger = LoggerFactory.getLogger(RedisExpiredRelayListener.class);
+
+    private RedisService redisService = SpringUtils.getBean(RedisService.class);
+
+    public RedisExpiredRelayListener(RedisMessageListenerContainer listenerContainer) {
+        super(listenerContainer);
+    }
+
+    @Override
+    public void onMessage(Message message, byte[] bytes) {
+        String expiredKey = new String(message.getBody());
+        if(expiredKey.contains(RelayConstants.AT_RELAY_DATA)){
+            logger.info("过期的key:"+expiredKey);
+            String relayCode=expiredKey.replace(RelayConstants.AT_RELAY_DATA,"");
+            LabRelayStatus labRelayStatus = new LabRelayStatus();
+            labRelayStatus.setNum(relayCode);
+            labRelayStatus.setHardwareOperate(HardwareOperate.OFFLINE);
+            LabRelayNrStatusEvent relayNrStatusEvent=new LabRelayNrStatusEvent(labRelayStatus);
+            SpringUtils.getApplicationContext().publishEvent(relayNrStatusEvent);
+        }
+    }
+}

+ 7 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/mapper/LabRelayMapper.java

@@ -58,4 +58,11 @@ public interface LabRelayMapper
      * @return 结果
      */
     public int deleteLabRelayByIds(Long[] ids);
+
+    /**
+     * 根据编号查询是否存在
+     * @param labRelayCode
+     * @return
+     */
+    Integer selectLabRelayIsExit(String labRelayCode);
 }

+ 43 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/mqtt/entiy/LabRelayStatus.java

@@ -0,0 +1,43 @@
+package com.zd.laboratory.mqtt.entiy;
+
+import com.zd.model.enums.HardwareOperate;
+
+/**
+ * @Author donggaosheng
+ * @Date 2023-05-04
+ * @description 泥人继电器通用类
+ **/
+public class LabRelayStatus {
+    /**
+     * 编码
+     */
+    String num;
+
+    HardwareOperate hardwareOperate;
+
+    Integer bit;
+
+    public String getNum() {
+        return num;
+    }
+
+    public void setNum(String num) {
+        this.num = num;
+    }
+
+    public HardwareOperate getHardwareOperate() {
+        return hardwareOperate;
+    }
+
+    public void setHardwareOperate(HardwareOperate hardwareOperate) {
+        this.hardwareOperate = hardwareOperate;
+    }
+
+    public Integer getBit() {
+        return bit;
+    }
+
+    public void setBit(Integer bit) {
+        this.bit = bit;
+    }
+}

+ 1 - 1
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/netty/ChannelMap.java

@@ -9,7 +9,7 @@ public class ChannelMap {
     /**
      * 存放客户端标识ID(消息ID)与channel的对应关系
      */
-    private static volatile ConcurrentHashMap<String, ChannelHandlerContext> channelMap = null;
+    private static volatile ConcurrentHashMap<String, ChannelHandlerContext> channelMap = new ConcurrentHashMap<>();
 
     private ChannelMap() {
     }

+ 24 - 27
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/netty/NettyServerHandler.java

@@ -4,25 +4,34 @@ import com.zd.common.core.alert.DingTalkAlert;
 import com.zd.common.core.redis.RedisService;
 import com.zd.common.core.utils.DateUtils;
 import com.zd.common.core.utils.SpringUtils;
+import com.zd.common.core.utils.StringUtils;
+import com.zd.laboratory.constant.RelayConstants;
 import com.zd.laboratory.domain.LabAbnormal;
 import com.zd.laboratory.domain.LabHardware;
+import com.zd.laboratory.domain.LabRelay;
 import com.zd.laboratory.domain.vo.LabHardwareVO;
+import com.zd.laboratory.event.LabRelayNrStatusEvent;
+import com.zd.laboratory.event.LabRelayRegisterEvent;
 import com.zd.laboratory.mapper.LabAbnormalMapper;
 import com.zd.laboratory.mapper.LabHardwareMapper;
+import com.zd.laboratory.mqtt.entiy.EquipmentStatus;
+import com.zd.laboratory.mqtt.entiy.LabRelayStatus;
+import com.zd.laboratory.service.ILabHardwareService;
 import com.zd.laboratory.socket.constant.JXCTPacket;
 import com.zd.laboratory.socket.constant.SocketTypes;
 import com.zd.laboratory.socket.runner.TCPServer;
 import com.zd.laboratory.socket.service.BaseRouter;
 import com.zd.laboratory.utils.CRCCHECK;
+import com.zd.laboratory.utils.RelayUtils;
+import com.zd.model.enums.HardwareOperate;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandler;
 import lombok.extern.slf4j.Slf4j;
 
+import java.net.Socket;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.*;
 
 /**
  * 服务器端handler
@@ -37,10 +46,9 @@ public class NettyServerHandler implements ChannelInboundHandler {
     public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
         byte[] msg  = (byte[]) o;
         String data = TCPServer.bytesToHexString(msg).toUpperCase();
-        log.info("netty服务端接受消息为:" + data);
-
+        String dataStr=TCPServer.hexStr2Str(data);
+        log.info("**************************************"+dataStr+"****************************************");
         if(data.startsWith(SocketTypes.RELAY_PREFIX.replaceAll(" ", "").toUpperCase())){
-
             analyticRelayData(data, channelHandlerContext);
         }else if(data.startsWith(SocketTypes.SZZQ_PREFIX)){
             // 采集器规范定义 hex发送  结构  31 11 01 01  后两位递增方式增加
@@ -48,25 +56,31 @@ public class NettyServerHandler implements ChannelInboundHandler {
             // 将通道加入ChannelMap
             if(relayCode.length() == data.length()){
                 ChannelMap.getChannelMap().put(data, channelHandlerContext);
-
             }else if(data.length() > relayCode.length()) {
                 data = data.replaceAll(relayCode, "");
                 // 柜锁bit 位
                 long bit = CRCCHECK.getBitByCommand(data);
                 // 1开锁状态 0关锁状态
                 int status = CRCCHECK.getLockStatus(data);
-
                 String openData = CRCCHECK.getOpenLockOrder((int)bit).replace(" ", "").toUpperCase();
                 if(data.equals(openData)){
                     log.info("netty柜锁指令回调:" + relayCode + ":" + bit + ",指令:" + data);
                     return;
                 }
-
                 log.info("netty柜锁状态回调:" + relayCode + ":" + bit + ",回调结果" + (status == 1 ? "开启": "关闭") + ",指令:" + data);
-
                 RedisService redisService = SpringUtils.getBean(RedisService.class);
                 redisService.setCacheObject(relayCode + ":" + bit, status, 3 * 60L, TimeUnit.SECONDS);
             }
+        }else if(dataStr.endsWith(SocketTypes.NRKJ_PREFIX) || dataStr.contains(SocketTypes.NRKJ_IDENTIFY)){
+            String codeStr=dataStr.substring(0,17);
+            String relayCode=codeStr.replace(":","");
+             //回复ack
+            ChannelMap.getChannelMap().put(relayCode, channelHandlerContext);
+            NettyPushMsgService.push(relayCode,RelayConstants.AT_ACK.getBytes());
+            //注册状态更新
+            RelayUtils.relayRefreshStatus(dataStr,relayCode,codeStr);
+            //继电器开关
+            RelayUtils.relayOpenClose(dataStr,relayCode);
         }
     }
 
@@ -77,7 +91,6 @@ public class NettyServerHandler implements ChannelInboundHandler {
             log.info("netty继电器上报不识别指令:" + packet.order);
             return;
         }
-
         log.info("netty继电器状态上报:" + packet.toString());
         ChannelMap.getChannelMap().put(packet.deviceNumber, channelHandlerContext);
         baseRouter.routePacket(packet);
@@ -152,34 +165,24 @@ public class NettyServerHandler implements ChannelInboundHandler {
     @Override
     public void handlerRemoved(ChannelHandlerContext channelHandlerContext) throws Exception {
         log.info("netty客户端断开连接" + channelHandlerContext.toString());
-
         for (Map.Entry<String, ChannelHandlerContext> a : ChannelMap.getChannelMap().entrySet()) {
-
             if(a.getValue() == channelHandlerContext){
                 ChannelMap.getChannelMap().remove(a.getKey());
                 log.info("netty客户端断开连接清除key: " + a.getKey());
-
                 executorService.schedule(new Runnable() {
                     @Override
                     public void run() {
-
                         String relayCode = a.getKey();
-
                         if(ChannelMap.getChannelMap().get(relayCode) != null){
                             return;
                         }
-
                         LabHardwareMapper labHardwareMapper = SpringUtils.getBean(LabHardwareMapper.class);
-
                         LabHardware labHardware = new LabHardware();
                         labHardware.setRelayCode(relayCode);
-
                         List<LabHardwareVO> list = labHardwareMapper.selectHardwareAndSubInfoByRelay(labHardware);
-
                         if(list.size() == 0){
                             return;
                         }
-
                         LabAbnormalMapper labAbnormalMapper = SpringUtils.getBean(LabAbnormalMapper.class);
                         for (LabHardwareVO hardwareVO : list) {
                             LabAbnormal labAbnormal = new LabAbnormal();
@@ -192,20 +195,14 @@ public class NettyServerHandler implements ChannelInboundHandler {
                             labAbnormal.setCreateBy("系统");
                             labAbnormal.setCreateTime(DateUtils.getNowDate());
                             labAbnormalMapper.insertLabAbnormal(labAbnormal);
-
-
                             String content = hardwareVO.getDeptName() + hardwareVO.getSubjectName() + hardwareVO.getName()
                                     + "netty连接已掉线三分钟未连接!请确认处理!";
                             DingTalkAlert.sendAlert(content);
                         }
-
                     }
                 }, 180, TimeUnit.SECONDS);
-
                 break;
             }
         }
     }
-
-
 }

+ 14 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/ILabHardwareService.java

@@ -1,5 +1,6 @@
 package com.zd.laboratory.service;
 
+import com.zd.laboratory.mqtt.entiy.LabRelayStatus;
 import com.zd.model.enums.HardwareTypeEnum;
 import com.zd.laboratory.domain.LabHardware;
 import com.zd.laboratory.domain.vo.HxpSmartTerminalByExcel;
@@ -45,6 +46,12 @@ public interface ILabHardwareService {
      */
     List<LabHardwareVO> selectLabHardwareList(LabHardware labHardware);
 
+
+    /**
+     * 查询硬件列表根据NUM或者继电器编码
+     */
+    List<LabHardware> selectLabHardwareStatusByRelay(LabHardware labHardware);
+
     /**
      * 新增硬件
      *
@@ -108,6 +115,13 @@ public interface ILabHardwareService {
     int updateRelayStatus(EquipmentStatus equipmentStatus);
 
     /**
+     * 更新泥人继电器状态
+     * @param labRelayStatus
+     * @return
+     */
+    int updateNrRelayStatus(LabRelayStatus labRelayStatus);
+
+    /**
      * 更新视频状态
      */
     int updateStatus(EquipmentStatus equipmentStatus);

+ 7 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/ILabRelayService.java

@@ -28,6 +28,13 @@ public interface ILabRelayService
     public List<LabRelay> selectLabRelayList(LabRelay labRelay);
 
     /**
+     * 根据编号查询是否存在
+     * @param labRelayCode
+     * @return
+     */
+    public Integer selectLabRelayIsExit(String labRelayCode);
+
+    /**
      * 新增继电器和传感器网关
      * 
      * @param labRelay 继电器和传感器网关

+ 21 - 3
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/impl/LabExitLineVertexServiceImpl.java

@@ -11,9 +11,11 @@ import com.zd.common.core.utils.SaveUtil;
 import com.zd.common.core.utils.SecurityUtils;
 import com.zd.common.core.utils.StringUtils;
 import com.zd.laboratory.config.TimeWaitConfigUtils;
+import com.zd.laboratory.constant.RelayConstants;
 import com.zd.laboratory.domain.*;
 import com.zd.laboratory.domain.vo.*;
 import com.zd.laboratory.mapper.*;
+import com.zd.laboratory.netty.NettyPushMsgService;
 import com.zd.laboratory.service.ILabExitLineVertexService;
 import com.zd.laboratory.service.ILabSparseHardwareService;
 import com.zd.laboratory.socket.command.Symbol;
@@ -25,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.io.IOException;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -213,10 +216,18 @@ public class LabExitLineVertexServiceImpl implements ILabExitLineVertexService {
                     //这里打卡继电器的开关(老继电器)
                     socketService.sendCommand(Symbol.order.control, relay.getRelayCode(), Symbol.command.close, relay.getRelayBit());
                     Thread.sleep(timeWaitConfigUtils.getWaitTime());
-                } else {
+                } else if(relay.getRelayType().intValue() == 2){
                     //这里打卡继电器的开关(新继电器)
                     socketService.sendMqttCommand(relay.getRelayCode(), Symbol.command.close, relay.getRelayBit() + "");
                     Thread.sleep(timeWaitConfigUtils.getWaitTime());
+                }else if(relay.getRelayType().intValue() == 3){
+                    try {
+                        String relayCode = relay.getRelayCode();
+                        String commandStr = RelayConstants.AT_STACH + relay.getRelayBit() + "=" + RelayConstants.AT_CLOSE + RelayConstants.SPACE_WRAP;
+                        NettyPushMsgService.push(relayCode, commandStr.getBytes());
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
                 }
             } catch (InterruptedException e) {
                 e.printStackTrace();
@@ -348,12 +359,19 @@ public class LabExitLineVertexServiceImpl implements ILabExitLineVertexService {
                             //这里打卡继电器的开关(老继电器)
                             socketService.sendCommand(Symbol.order.control, a.getRelayCode(), Symbol.command.open, a.getRelayBit());
                             Thread.sleep(timeWaitConfigUtils.getWaitTime());
-                        }else{
+                        }else if(a.getRelayType().intValue()==2){
                             //这里打卡继电器的开关(新继电器)
                             socketService.sendMqttCommand(a.getRelayCode(), Symbol.command.open ,a.getRelayBit()+"");
                             Thread.sleep(timeWaitConfigUtils.getWaitTime());
+                        }else if(a.getRelayType().intValue()==3){
+                            try {
+                                String relayCode = a.getRelayCode();
+                                String commandStr = RelayConstants.AT_STACH + a.getRelayBit() + "=" + RelayConstants.AT_OPEN + RelayConstants.SPACE_WRAP;
+                                NettyPushMsgService.push(relayCode, commandStr.getBytes());
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
                         }
-
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }

+ 22 - 3
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/impl/LabExitPointRelayServiceImpl.java

@@ -6,16 +6,19 @@ import com.alibaba.fastjson.TypeReference;
 import com.alibaba.fastjson.parser.Feature;
 import com.zd.common.core.redis.RedisService;
 import com.zd.laboratory.config.TimeWaitConfigUtils;
+import com.zd.laboratory.constant.RelayConstants;
 import com.zd.laboratory.domain.LabExitPointRelay;
 import com.zd.laboratory.domain.vo.LabExitLineJoinPointVO;
 import com.zd.laboratory.mapper.LabExitPointRelayMapper;
 import com.zd.laboratory.mqtt.service.impl.SubMessageSendManager;
+import com.zd.laboratory.netty.NettyPushMsgService;
 import com.zd.laboratory.service.ILabExitPointRelayService;
 import com.zd.laboratory.socket.command.Symbol;
 import com.zd.laboratory.socket.service.SocketService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.io.IOException;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 
@@ -85,12 +88,20 @@ public class LabExitPointRelayServiceImpl implements ILabExitPointRelayService {
                     //这里打卡继电器的开关(老继电器)
                     socketService.sendCommand(Symbol.order.control, relay.getRelayCode(), Symbol.command.open, relay.getRelayBit());
                     Thread.sleep(timeWaitConfigUtils.getWaitTime());
-                }else{
+                }else if(relay.getRelayType().intValue()==2){
                     //这里打卡继电器的开关(新继电器)
                     socketService.sendMqttCommand(relay.getRelayCode(), Symbol.command.open ,relay.getRelayBit()+"");
                     Thread.sleep(timeWaitConfigUtils.getWaitTime());
+                }else if(relay.getRelayType().intValue()==3){
+                    //这里打卡继电器的开关(新继电器)
+                    try {
+                        String relayCode = relay.getRelayCode();
+                        String commandStr = RelayConstants.AT_STACH + relay.getRelayBit() + "=" + RelayConstants.AT_OPEN + RelayConstants.SPACE_WRAP;
+                        NettyPushMsgService.push(relayCode, commandStr.getBytes());
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
                 }
-
                 boolean flag = true;
                 if(lightPointSet!=null  && lightPointSet.size()>0){
                     for(LabExitLineJoinPointVO pointVO:lightPointSet){
@@ -141,10 +152,18 @@ public class LabExitPointRelayServiceImpl implements ILabExitPointRelayService {
                     //这里打卡继电器的开关(老继电器)
                     socketService.sendCommand(Symbol.order.control, relay.getRelayCode(), Symbol.command.close, relay.getRelayBit());
                     Thread.sleep(timeWaitConfigUtils.getWaitTime());
-                } else {
+                } else if(relay.getRelayType().intValue() == 2){
                     //这里打卡继电器的开关(新继电器)
                     socketService.sendMqttCommand(relay.getRelayCode(), Symbol.command.close, relay.getRelayBit() + "");
                     Thread.sleep(timeWaitConfigUtils.getWaitTime());
+                }else if(relay.getRelayType().intValue() == 3){
+                    try {
+                        String relayCode = relay.getRelayCode();
+                        String commandStr = RelayConstants.AT_STACH + relay.getRelayBit() + "=" + RelayConstants.AT_CLOSE + RelayConstants.SPACE_WRAP;
+                        NettyPushMsgService.push(relayCode, commandStr.getBytes());
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
                 }
                 if(lightPointSet!=null && lightPointSet.size()>0){
                     for(LabExitLineJoinPointVO pointVO:lightPointSet){

+ 21 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/impl/LabHardwareServiceImpl.java

@@ -22,6 +22,7 @@ import com.zd.laboratory.mapper.LabHardwareMapper;
 import com.zd.laboratory.mapper.LabSparseHardwareMapper;
 import com.zd.laboratory.mapper.LabSubjectHardwarePositionMapper;
 import com.zd.laboratory.mqtt.entiy.EquipmentStatus;
+import com.zd.laboratory.mqtt.entiy.LabRelayStatus;
 import com.zd.laboratory.service.ILabHardwareService;
 import com.zd.laboratory.socket.service.SocketService;
 import com.zd.model.constant.CacheConstants;
@@ -188,6 +189,11 @@ public class LabHardwareServiceImpl implements ILabHardwareService {
         return list;
     }
 
+    @Override
+    public List<LabHardware> selectLabHardwareStatusByRelay(LabHardware labHardware) {
+        return labHardwareMapper.selectLabHardwareStatusByRelay(labHardware);
+    }
+
     /**
      * 新增硬件
      *
@@ -531,6 +537,21 @@ public class LabHardwareServiceImpl implements ILabHardwareService {
 
 
     }
+
+    @Override
+    public int updateNrRelayStatus(LabRelayStatus labRelayStatus) {
+        LabHardware labHardware = new LabHardware();
+        labHardware.setOperate(labRelayStatus.getHardwareOperate());
+        labHardware.setRelayCode(labRelayStatus.getNum());
+        labHardware.setBit(labRelayStatus.getBit());
+        int count = labHardwareMapper.updateLabHardwareRelayCodeStatus(labHardware);
+        // 疏散指示灯状态更新
+        if(count == 0){
+            labExitLightMapper.updateStatus(labHardware);
+        }
+        return count;
+    }
+
     /**
      * 更新视频状态
      *

+ 11 - 1
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/service/impl/LabRelayServiceImpl.java

@@ -47,8 +47,18 @@ public class LabRelayServiceImpl implements ILabRelayService
     }
 
     /**
+     * 根据编号查询是否存在
+     * @param labRelayCode
+     * @return
+     */
+    @Override
+    public Integer selectLabRelayIsExit(String labRelayCode) {
+        return labRelayMapper.selectLabRelayIsExit(labRelayCode);
+    }
+
+    /**
      * 新增继电器和传感器网关
-     * 
+     *
      * @param labRelay 继电器和传感器网关
      * @return 结果
      */

+ 16 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/socket/constant/SocketTypes.java

@@ -25,4 +25,20 @@ public class SocketTypes {
      * 深圳智嵌采集器器
      */
     public static final String SZZQ_PREFIX = "3111";
+
+    /**
+     * 继电器表示
+     */
+    public static final String NRKJ_PREFIX = "4111";
+
+    /**
+     * 继电器标识
+     */
+    public static final String NRKJ_IDENTIFY="STACH";
+
+
+    /**
+     * 继电器标识
+     */
+    public static final String AT_NRKJ_IDENTIFY="AT+STACH";
 }

+ 41 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/socket/runner/TCPServer.java

@@ -195,6 +195,47 @@ public class TCPServer implements Runnable {
         return sb.toString();
     }
 
+
+    /**
+     * 字符串转换成为16进制(无需Unicode编码)
+     * @param str
+     * @return
+     */
+    public static String str2HexStr(String str) {
+        char[] chars = "0123456789ABCDEF".toCharArray();
+        StringBuilder sb = new StringBuilder("");
+        byte[] bs = str.getBytes();
+        int bit;
+        for (int i = 0; i < bs.length; i++) {
+            bit = (bs[i] & 0x0f0) >> 4;
+            sb.append(chars[bit]);
+            bit = bs[i] & 0x0f;
+            sb.append(chars[bit]);
+            // sb.append(' ');
+        }
+        return sb.toString().trim();
+    }
+
+
+    /**
+     * 16进制直接转换成为字符串(无需Unicode解码)
+     * @param hexStr
+     * @return
+     */
+    public static String hexStr2Str(String hexStr) {
+        String str = "0123456789ABCDEF";
+        char[] hexs = hexStr.toCharArray();
+        byte[] bytes = new byte[hexStr.length() / 2];
+        int n;
+        for (int i = 0; i < bytes.length; i++) {
+            n = str.indexOf(hexs[2 * i]) * 16;
+            n += str.indexOf(hexs[2 * i + 1]);
+            bytes[i] = (byte) (n & 0xff);
+        }
+        return new String(bytes);
+    }
+
+
     public static void main(String[] args) throws Exception {
         // fe dc 固定头
         // 11  去头尾 的字节长度

+ 106 - 0
zd-modules/zd-modules-laboratory/src/main/java/com/zd/laboratory/utils/RelayUtils.java

@@ -0,0 +1,106 @@
+package com.zd.laboratory.utils;
+
+import com.zd.common.core.redis.RedisService;
+import com.zd.common.core.utils.SpringUtils;
+import com.zd.common.core.utils.StringUtils;
+import com.zd.laboratory.constant.RelayConstants;
+import com.zd.laboratory.domain.LabRelay;
+import com.zd.laboratory.event.LabRelayNrStatusEvent;
+import com.zd.laboratory.event.LabRelayRegisterEvent;
+import com.zd.laboratory.mqtt.entiy.LabRelayStatus;
+import com.zd.laboratory.netty.NettyPushMsgService;
+import com.zd.laboratory.socket.constant.SocketTypes;
+import com.zd.model.enums.HardwareOperate;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author donggaosheng
+ * @Date 2023-05-06
+ * @description 继电器处理类
+ **/
+@Slf4j
+public class RelayUtils {
+
+    private static RedisService redisService = SpringUtils.getBean(RedisService.class);
+
+    public static ConcurrentMap<String, Object> concurrentMap = new ConcurrentHashMap<>();
+
+    /**
+     * 继电器的开和关
+     * @param data
+     */
+    public static void relayOpenClose(String data,String relayCode) throws IOException {
+        if(data.contains(SocketTypes.NRKJ_IDENTIFY) && !data.contains(SocketTypes.AT_NRKJ_IDENTIFY)){
+            //继电器打开关闭
+            String statusData[]= data.split(",")[0].split(":");
+            String bitData[]= data.split(",")[0].split("\\+")[1].split(":");
+            Integer bit=Integer.parseInt(bitData[0].replace(RelayConstants.STACH,""));
+            Integer status=Integer.parseInt(statusData[statusData.length-1]);
+            log.info("status:"+status+"bit:"+bit);
+            LabRelayStatus labRelayStatus = new LabRelayStatus();
+            labRelayStatus.setBit(bit);
+            if(status== RelayConstants.AT_OPEN){
+                log.info("打开了");
+                labRelayStatus.setNum(relayCode);
+                labRelayStatus.setHardwareOperate(HardwareOperate.OPEN);
+            }else{
+                log.info("关闭了");
+                labRelayStatus.setNum(relayCode);
+                labRelayStatus.setHardwareOperate(HardwareOperate.CLOSE);
+            }
+            //抛出继电器开关切换事件
+            LabRelayNrStatusEvent relayNrStatusEvent=new LabRelayNrStatusEvent(labRelayStatus);
+            SpringUtils.getApplicationContext().publishEvent(relayNrStatusEvent);
+        }
+        Object code= concurrentMap.get(RelayConstants.AT_RELAY_DATA+relayCode);
+        Integer activeCode=redisService.getCacheObject(RelayConstants.AT_RELAY_DATA+relayCode);
+        String dataStr= data.substring(0,17)+SocketTypes.NRKJ_PREFIX;
+        log.info("code:"+code+"activeCode:"+activeCode+"data:"+data);
+        if(StringUtils.isNull(code) || StringUtils.isNull(activeCode) || dataStr.equals(data)){
+            NettyPushMsgService.push(relayCode,RelayConstants.AT_STACH_ALL.getBytes());
+            concurrentMap.put(RelayConstants.AT_RELAY_DATA+relayCode,HardwareOperate.CLOSE.getCode());
+        }
+        redisService.setCacheObject(RelayConstants.AT_RELAY_DATA+relayCode,HardwareOperate.CLOSE.getCode(),1L, TimeUnit.MINUTES);
+    }
+
+    public static void relayOpenClose(String relayCode) throws IOException {
+        NettyPushMsgService.push(relayCode,RelayConstants.AT_STACH_ALL.getBytes());
+        redisService.setCacheObject(RelayConstants.AT_RELAY_DATA+relayCode,HardwareOperate.CLOSE.getCode(),15L, TimeUnit.SECONDS);
+
+    }
+
+    /**
+     * 继电器状态保存
+     * @param data
+     */
+    public static void  relayRefreshStatus(String data,String relayCode,String codeStr){
+        LabRelay labRelay=new LabRelay();
+        labRelay.setCode(relayCode);
+        LabRelayRegisterEvent labRelayRegisterEvent=new LabRelayRegisterEvent(labRelay);
+        SpringUtils.getApplicationContext().publishEvent(labRelayRegisterEvent);
+        if(data.contains(RelayConstants.AT_STACH_ALL_STR)){
+            log.info("#############################################");
+            log.info(data);
+            log.info("#############################################");
+            String disposeCommand=data.replace(codeStr+RelayConstants.AT_STACH_ALL,"");
+            String splitCommand[]=disposeCommand.split(RelayConstants.AT_SPLITE);
+            LabRelayStatus labRelayStatus = new LabRelayStatus();
+            for(String split:splitCommand){
+                String status[]=split.split(",")[0].split(":");
+                String bitStr=status[0].replace(RelayConstants.PLUS_STACH,"");
+                log.info("bit:"+bitStr+"========================="+"status[1]:"+status[1]);
+                labRelayStatus.setNum(relayCode);
+                labRelayStatus.setBit(Integer.parseInt(bitStr));
+                HardwareOperate hardwareOperate=status[1].equals("1")?HardwareOperate.OPEN:HardwareOperate.CLOSE;
+                labRelayStatus.setHardwareOperate(hardwareOperate);
+                LabRelayNrStatusEvent relayNrStatusEvent=new LabRelayNrStatusEvent(labRelayStatus);
+                SpringUtils.getApplicationContext().publishEvent(relayNrStatusEvent);
+            }
+        }
+    }
+}

+ 4 - 0
zd-modules/zd-modules-laboratory/src/main/resources/mapper/laboratory/LabRelayMapper.xml

@@ -35,6 +35,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         where id = #{id}
     </select>
 
+    <select id="selectLabRelayIsExit" resultType="java.lang.Integer">
+        select count(*) from lab_relay where code=#{labRelayCode} and type=1
+    </select>
+
     <insert id="insertLabRelay" parameterType="com.zd.laboratory.domain.LabRelay" useGeneratedKeys="true" keyProperty="id">
         insert into lab_relay
         <trim prefix="(" suffix=")" suffixOverrides=",">