Kaynağa Gözat

算法服务一键灭火代码提交

xuxiaofei 3 yıl önce
ebeveyn
işleme
d73c022500
19 değiştirilmiş dosya ile 2351 ekleme ve 0 silme
  1. 198 0
      zd-api/zd-algorithm-api/src/main/java/com/zd/algorithm/api/firedevice/entity/HardwareFireDevice.java
  2. 150 0
      zd-api/zd-algorithm-api/src/main/java/com/zd/algorithm/api/firedevice/entity/HardwareFireDeviceLog.java
  3. 68 0
      zd-api/zd-algorithm-api/src/main/java/com/zd/algorithm/api/firedevice/entity/vo/HardwareFireDeviceVO.java
  4. 379 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/controller/FireDeviceController.java
  5. 64 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/mapper/FireDeviceLogMapper.java
  6. 64 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/mapper/FireDeviceMapper.java
  7. 71 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/service/IFireDeviceLogService.java
  8. 63 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/service/IFireDeviceService.java
  9. 145 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/service/impl/FireDeviceLogServiceImpl.java
  10. 150 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/service/impl/FireDeviceServiceImpl.java
  11. 78 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/utils/FireDeviceStatusTask.java
  12. 210 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/utils/FireLaborUtil.java
  13. 243 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/mqtt/MqttConfig.java
  14. 39 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/mqtt/MqttProducerUtils.java
  15. 65 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/mqtt/MqttSend.java
  16. 95 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/mqtt/entiy/MessageBody.java
  17. 26 0
      zd-modules/zd-algorithm/src/main/java/com/zd/alg/mqtt/enums/SendMode.java
  18. 108 0
      zd-modules/zd-algorithm/src/main/resources/mapper/firedevice/FireDeviceLogMapper.xml
  19. 135 0
      zd-modules/zd-algorithm/src/main/resources/mapper/firedevice/FireDeviceMapper.xml

+ 198 - 0
zd-api/zd-algorithm-api/src/main/java/com/zd/algorithm/api/firedevice/entity/HardwareFireDevice.java

@@ -0,0 +1,198 @@
+package com.zd.algorithm.api.firedevice.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.zd.model.annotation.Excel;
+import com.zd.model.entity.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Date;
+
+/**
+ * 灭火设备 lab_fire_device
+ *
+ * @author  xxf
+ * @date 2022-11-24
+ */
+@ApiModel("灭火设备表")
+public class HardwareFireDevice extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键id
+     */
+    @ApiModelProperty(value = "${comment}")
+    private Long id;
+
+    /**
+     * 设备名称
+     */
+    @ApiModelProperty("设备名称")
+    @Excel(name = "设备名称")
+    private String deviceName;
+
+    /**
+     * 采集器编号
+     */
+    @ApiModelProperty("采集器编号")
+    @Excel(name = "采集器编号")
+    private String deviceCode;
+
+    /**
+     * 继电器编号
+     */
+    @ApiModelProperty("继电器编号")
+    @Excel(name = "继电器编号")
+    private String relayCode;
+
+    /**
+     * 设备地址
+     */
+    @ApiModelProperty("设备地址")
+    @Excel(name = "设备地址")
+    private Integer deviceUrl;
+
+    /**
+     * 倒计时时间
+     */
+    @ApiModelProperty("倒计时时间(秒)")
+    @Excel(name = "倒计时时间(秒)")
+    private Integer deviceCountDown;
+
+    /**
+     * 设备状态 1离线 2在线  3异常
+     */
+    @ApiModelProperty("设备状态")
+    @Excel(name = "设备状态")
+    private Integer deviceStatus;
+
+    @ApiModelProperty("用户id")
+    private Long userId;
+
+    @ApiModelProperty("创建人")
+    private String createBy;
+
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @ApiModelProperty("部门名称")
+    private String deptName;
+
+    @ApiModelProperty("部门id")
+    private Long deptId;
+
+    /**
+     * 实验室id
+     */
+    @ApiModelProperty("实验室id")
+    private Long subjectId;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getDeviceName() {
+        return deviceName;
+    }
+
+    public void setDeviceName(String deviceName) {
+        this.deviceName = deviceName;
+    }
+
+    public String getDeviceCode() {
+        return deviceCode;
+    }
+
+    public void setDeviceCode(String deviceCode) {
+        this.deviceCode = deviceCode;
+    }
+
+    public String getRelayCode() {        return relayCode;    }
+
+    public void setRelayCode(String relayCode) {        this.relayCode = relayCode;    }
+
+    public Integer getDeviceUrl() {
+        return deviceUrl;
+    }
+
+    public void setDeviceUrl(Integer deviceUrl) {
+        this.deviceUrl = deviceUrl;
+    }
+
+    public Integer getDeviceCountDown() {
+        return deviceCountDown;
+    }
+
+    public void setDeviceCountDown(Integer deviceCountDown) {
+        this.deviceCountDown = deviceCountDown;
+    }
+
+    public Integer getDeviceStatus() {
+        return deviceStatus;
+    }
+
+    public void setDeviceStatus(Integer deviceStatus) {        this.deviceStatus = deviceStatus;    }
+
+    public Long getSubjectId() {
+        return subjectId;
+    }
+
+    public void setSubjectId(Long subjectId) {
+        this.subjectId = subjectId;
+    }
+
+    @Override
+    public Long getUserId() {
+        return userId;
+    }
+
+    @Override
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    @Override
+    public String getCreateBy() {
+        return createBy;
+    }
+
+    @Override
+    public void setCreateBy(String createBy) {
+        this.createBy = createBy;
+    }
+
+    @Override
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    @Override
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    @Override
+    public String getDeptName() {
+        return deptName;
+    }
+
+    @Override
+    public void setDeptName(String deptName) {
+        this.deptName = deptName;
+    }
+
+    @Override
+    public Long getDeptId() {
+        return deptId;
+    }
+
+    @Override
+    public void setDeptId(Long deptId) {
+        this.deptId = deptId;
+    }
+}

+ 150 - 0
zd-api/zd-algorithm-api/src/main/java/com/zd/algorithm/api/firedevice/entity/HardwareFireDeviceLog.java

@@ -0,0 +1,150 @@
+package com.zd.algorithm.api.firedevice.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.zd.model.annotation.Excel;
+import com.zd.model.entity.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.Date;
+
+/**
+ * 灭火设备日志 lab_fire_device_log
+ *
+ * @author  xxf
+ * @date 2022-11-24
+ */
+@ApiModel("灭火设备日志表")
+public class HardwareFireDeviceLog extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键id
+     */
+    @ApiModelProperty(value = "${comment}")
+    private Long id;
+
+    /**
+     * 灭火装置表id
+     */
+    @ApiModelProperty("灭火装置表id")
+    @Excel(name = "灭火装置表id")
+    private Long fireDeviceId;
+
+    /**
+     * 灭火类型 1自动 2手动
+     */
+    @ApiModelProperty("灭火类型")
+    private Integer runType;
+
+    /**
+     * 执行结果
+     */
+    @ApiModelProperty("执行结果")
+    @Excel(name = "执行结果")
+    private String runResult;
+
+    @ApiModelProperty("用户id")
+    private Long userId;
+
+    @ApiModelProperty("创建人")
+    private String createBy;
+
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    @ApiModelProperty("部门名称")
+    private String deptName;
+
+    @ApiModelProperty("部门id")
+    private Long deptId;
+
+    private Date flgTime;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getFireDeviceId() {
+        return fireDeviceId;
+    }
+
+    public void setFireDeviceId(Long fireDeviceId) {
+        this.fireDeviceId = fireDeviceId;
+    }
+
+    public Integer getRunType() {
+        return runType;
+    }
+
+    public void setRunType(Integer runType) {
+        this.runType = runType;
+    }
+
+    public String getRunResult() {
+        return runResult;
+    }
+
+    public void setRunResult(String runResult) {
+        this.runResult = runResult;
+    }
+
+    @Override
+    public Long getUserId() {
+        return userId;
+    }
+
+    @Override
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    @Override
+    public String getCreateBy() {
+        return createBy;
+    }
+
+    @Override
+    public void setCreateBy(String createBy) {
+        this.createBy = createBy;
+    }
+
+    @Override
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    @Override
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    @Override
+    public String getDeptName() {
+        return deptName;
+    }
+
+    @Override
+    public void setDeptName(String deptName) {
+        this.deptName = deptName;
+    }
+
+    @Override
+    public Long getDeptId() {
+        return deptId;
+    }
+
+    @Override
+    public void setDeptId(Long deptId) {
+        this.deptId = deptId;
+    }
+
+    public Date getFlgTime() {        return flgTime;    }
+
+    public void setFlgTime(Date flgTime) {        this.flgTime = flgTime;    }
+}

+ 68 - 0
zd-api/zd-algorithm-api/src/main/java/com/zd/algorithm/api/firedevice/entity/vo/HardwareFireDeviceVO.java

@@ -0,0 +1,68 @@
+package com.zd.algorithm.api.firedevice.entity.vo;
+
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDevice;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * 灭火设备 lab_fire_device
+ *
+ * @author xxf
+ * @date 2022-11-24
+ */
+@ApiModel("灭火设备表")
+public class HardwareFireDeviceVO extends HardwareFireDevice {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 楼栋
+     */
+    @ApiModelProperty(value = "楼栋")
+    private String buildName;
+
+    /**
+     * 实验室名称
+     */
+    @ApiModelProperty(value = "实验室名称")
+    private String subjectName;
+
+    /**
+     * 房间号
+     */
+    @ApiModelProperty(value = "房间号")
+    private String room;
+
+    /**
+     * 描述
+     */
+    @ApiModelProperty(value = "描述")
+    private String describe;
+
+    public String getBuildName() {
+        return buildName;
+    }
+
+    public void setBuildName(String buildName) {
+        this.buildName = buildName;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getRoom() {
+        return room;
+    }
+
+    public void setRoom(String room) {
+        this.room = room;
+    }
+
+    public String getDescribe() {        return describe;    }
+
+    public void setDescribe(String describe) {        this.describe = describe;    }
+}

+ 379 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/controller/FireDeviceController.java

@@ -0,0 +1,379 @@
+package com.zd.alg.firedevice.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.zd.alg.firedevice.service.IFireDeviceLogService;
+import com.zd.alg.firedevice.service.IFireDeviceService;
+import com.zd.alg.firedevice.utils.FireDeviceStatusTask;
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDevice;
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDeviceLog;
+import com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO;
+import com.zd.common.core.annotation.Log;
+import com.zd.common.core.annotation.PreAuthorize;
+import com.zd.common.core.exception.ServiceException;
+import com.zd.common.core.log.BusinessType;
+import com.zd.common.core.redis.RedisService;
+import com.zd.common.core.utils.StringUtils;
+import com.zd.common.core.web.controller.BaseController;
+import com.zd.laboratory.api.feign.RemoteLaboratoryService;
+import com.zd.model.domain.ResultData;
+import com.zd.model.domain.per.PerFun;
+import com.zd.model.domain.per.PerPrefix;
+import com.zd.model.entity.RemoteLabHardware;
+import com.zd.model.page.TableDataInfo;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+
+/**
+ * 灭火装置
+ *
+ * @Author: xxf
+ * @Date: 2022/11/18/16:29
+ * @Description:
+ */
+@RestController
+@Component
+@RequestMapping("/firedevice")
+public class FireDeviceController extends BaseController {
+
+    @Autowired
+    private IFireDeviceService fireDeviceService;
+
+    @Autowired
+    private IFireDeviceLogService fireDeviceLogService;
+
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private RemoteLaboratoryService remoteLaboratoryService;
+
+    @Value("${time.waitTime}")
+    private Long waitTime;
+
+    @Value("${time.onlineTime}")
+    private Long onlineTime;
+
+
+    /**
+     * 获取主机状态(首次加载)
+     *
+     * @return
+     */
+    @GetMapping(value = "/getStatus")
+    public ResultData getStatus(Long subjectId) {
+        Map<String, Object> map = new HashMap<>();
+        boolean smoke = false;//烟雾
+        boolean temperature = false;//温度
+        boolean fire = false;//火焰
+        boolean online = false;//是否在线
+        boolean isexist = false;//是否配置灭火设备
+
+        if (StringUtils.isNull(subjectId)) {
+            return ResultData.fail("实验室id参数为空");
+        }
+
+        //获取灭火主机最后一次响应时间,判断响应是否超时
+        Long timeJson = redisService.getCacheObject(FireDeviceStatusTask.TOPIC_FD_RESPOND_TIME);
+        if (StringUtils.isNotNull(timeJson)) {
+            Long timeDiff = (System.currentTimeMillis() - timeJson) / 1000;
+            //时间差 在设置时间内
+            if (timeDiff < onlineTime) {
+                online = true;
+            }
+        }
+
+        //查询实验室是否配置灭火设备
+        HardwareFireDeviceVO vo = new HardwareFireDeviceVO();
+        vo.setSubjectId(subjectId);
+        List<HardwareFireDeviceVO> list = fireDeviceService.selectHardwareFireDeviceList(vo);
+        if (list.size() == 0) {
+            map.put("smoke", smoke);
+            map.put("temperature", temperature);
+            map.put("fire", fire);
+            map.put("isexist", isexist);
+            return ResultData.success(map);
+        } else {
+            isexist = true;
+        }
+
+        //根据编码从redis获取该设备状态
+        //String str = "{\"msg\":\"NO:5号设备故障 NO:10号设备火警 \",\"fireNumber\":1,\"fireStatus\":true,\"startSpray\":\"0\",\"gasSpray\":\"0\"}";
+        //JSONObject strJson = JSONObject.parseObject(str);
+        JSONObject strJson = redisService.getCacheObject(list.get(0).getDeviceCode());
+        if (StringUtils.isNotNull(strJson)) {
+            Integer fireNumber = (Integer) strJson.get("fireNumber");
+            if (fireNumber == 1) {
+                temperature = true;
+            } else if (fireNumber == 2) {
+                smoke = true;
+                temperature = true;
+            }
+        }
+
+        //查询该实验室是否存在火焰摄像头报警
+        JSONObject fireJson = redisService.getCacheObject("/lab/fire/85");
+        if (StringUtils.isNotNull(fireJson)) {
+            fire = true;
+        }
+        map.put("smoke", smoke);
+        map.put("temperature", temperature);
+        map.put("fire", fire);
+        map.put("online", online);
+        map.put("isexist", isexist);
+        map.put("deviceCode", list.get(0).getDeviceCode());
+        return ResultData.success(map);
+    }
+
+    /**
+     * 定时状态请求
+     *
+     * @param deviceCode
+     * @return
+     */
+    @GetMapping(value = "/getStatusDetails")
+    public ResultData getStatus(String deviceCode) {
+        Map<String, Object> map = new HashMap<>();
+        boolean smoke = false;//烟雾
+        boolean temperature = false;//温度
+        boolean fire = false;//火焰
+        boolean online = false;//是否在线
+
+        if (StringUtils.isNull(deviceCode)) {
+            throw new ServiceException("设备编号参数为空");
+        }
+
+        //获取灭火主机最后一次响应时间,判断响应是否超时
+        Long timeJson = redisService.getCacheObject(FireDeviceStatusTask.TOPIC_FD_RESPOND_TIME);
+        if (StringUtils.isNotNull(timeJson)) {
+            Long timeDiff = (System.currentTimeMillis() - timeJson) / 1000;
+            //时间差 在设置时间内
+            if (timeDiff < onlineTime) {
+                online = true;
+            }
+        }
+
+        //根据编码从redis获取该设备状态
+        /*String str = "{\"msg\":\"NO:5号设备故障 NO:10号设备火警 \",\"fireNumber\":1,\"fireStatus\":true,\"startSpray\":\"0\",\"gasSpray\":\"0\"}";
+        JSONObject strJson = JSONObject.parseObject(str);*/
+        JSONObject strJson = redisService.getCacheObject(deviceCode);
+        if (StringUtils.isNotNull(strJson)) {
+            Integer fireNumber = (Integer) strJson.get("fireNumber");
+            if (fireNumber == 1) {
+                temperature = true;
+            } else if (fireNumber == 2) {
+                smoke = true;
+                temperature = true;
+            }
+        }
+
+        //查询该实验室是否存在火焰摄像头报警
+        JSONObject fireJson = redisService.getCacheObject("/lab/fire/85");
+        if (StringUtils.isNotNull(fireJson)) {
+            fire = true;
+        }
+        map.put("smoke", smoke);
+        map.put("temperature", temperature);
+        map.put("fire", fire);
+        map.put("online", online);
+        return ResultData.success(map);
+    }
+
+    /***
+     * 发送灭火请求
+     * @return
+     */
+    @GetMapping(value = "/outfire")
+    public ResultData outFire(Long subjectId) throws InterruptedException {
+        logger.info("=========开始一键灭火=======");
+        //查询实验室下的硬件
+        RemoteLabHardware hd = new RemoteLabHardware();
+        //实验室id
+        hd.setSubjectId(subjectId);
+        //灭火设备类型
+        hd.setType(10);
+        List<RemoteLabHardware> hdlist = remoteLaboratoryService.remoteList(hd).getData();
+        if (hdlist.size() == 0) {
+            return ResultData.fail("该实验室尚未配置关联硬件!");
+        } else if (hdlist.size() != 2) {
+            return ResultData.fail("该实验室尚未配置2路控制器!");
+        }
+
+
+        Map<String, Object> map = new HashMap<>();
+        //获取当前实验室下灭火设备状态
+        HardwareFireDeviceVO fireDeviceVO = new HardwareFireDeviceVO();
+        fireDeviceVO.setSubjectId(subjectId);
+        List<HardwareFireDeviceVO> list = fireDeviceService.selectHardwareFireDeviceList(fireDeviceVO);
+        JSONObject object = redisService.getCacheObject(list.get(0).getDeviceCode());
+        logger.info("灭火设备状态:" + object);
+
+        if (StringUtils.isNotNull(object)) {
+            //异常传感器数量
+            Integer fireNumber = (Integer) object.get("fireNumber");
+            if (fireNumber == 1) {
+                logger.info("手动灭火,灭火设备1路信号异常,补发一路信号,触发灭火!");
+                //随机补充一路信号 触发灭火
+                List<RemoteLabHardware> li = new ArrayList<>();
+                li.add(hdlist.get(0));
+                map = sendOutFireMsg(li);
+            } else if (fireNumber == 0) {
+                logger.info("手动灭火,灭火设备2路信号正常,发送两路电信号,触发灭火!");
+                map = sendOutFireMsg(hdlist);
+            }
+        } else {
+            logger.info("手动灭火,redis中没有获取到信息,但是仍然需要执行灭火流程,发送两路电信号,触发灭火");
+            map = sendOutFireMsg(hdlist);
+        }
+
+        //灭火日志添加
+        HardwareFireDeviceLog fireDeviceLog = new HardwareFireDeviceLog();
+        fireDeviceLog.setFireDeviceId(list.get(0).getId());
+        //手动
+        fireDeviceLog.setRunType(2);
+        fireDeviceLog.setRunResult(map.toString());
+        fireDeviceLog.setCreateTime(new Date());
+        fireDeviceLogService.insertFireDeviceLog(fireDeviceLog);
+        return ResultData.success(map);
+    }
+
+    /**
+     * 发送灭火消息通知
+     *
+     * @param hdlist
+     * @return
+     * @throws InterruptedException
+     */
+    private Map<String, Object> sendOutFireMsg(List<RemoteLabHardware> hdlist) throws InterruptedException {
+        Map<String, Object> map = new HashMap<>();
+        StringBuilder msg = new StringBuilder();
+        //执行动作结果
+        boolean flg = true;
+        //打开继电器
+        for (RemoteLabHardware hardware : hdlist) {
+            String str = null;
+            //设备id 类型 01打开  00 关闭
+            LinkedHashMap<String, Object> o = (LinkedHashMap<String, Object>) remoteLaboratoryService.controlByInside(hardware.getId(), "01");
+            for (Map.Entry<String, Object> enty : o.entrySet()) {
+                if (enty.getKey().equals("code") && Integer.valueOf(enty.getValue().toString()) == 500) {
+                    flg = false;
+                }
+                if (enty.getKey().equals("msg")) {
+                    str = enty.getValue().toString();
+                    msg.append("继电器编码:" + hardware.getRelayCode() + ",继电器位数:" + hardware.getBit() + ",执行结果:" + str);
+                }
+            }
+            logger.info("打开继电器,发送灭火信号,实验室id:" + hardware.getSubjectId() + ",继电器编码:" + hardware.getRelayCode() + "继电器位数:" + hardware.getBit() + ",执行结果:" + o + ",");
+            Thread.sleep(waitTime);
+        }
+
+        //关闭继电器
+        for (RemoteLabHardware hardware : hdlist) {
+            Thread.sleep(waitTime);
+            //设备id 类型 01打开  00 关闭
+            LinkedHashMap<String, Object> o = (LinkedHashMap<String, Object>) remoteLaboratoryService.controlByInside(hardware.getId(), "00");
+            logger.info("关闭继电器,执行结果:" + o);
+        }
+        map.put("msg", msg);
+        map.put("flg", flg);
+        return map;
+    }
+
+    /**
+     * 查询实验室灭火设备列表
+     */
+    @PreAuthorize(hasPermi = PerPrefix.ALGORITHM_FIREDEVICE + PerFun.LIST)
+    @GetMapping("/list")
+    @ApiOperation(value = "查询实验室灭火设备列表", notes = "权限字符:" + PerPrefix.ALGORITHM_FIREDEVICE + PerFun.LIST)
+    public TableDataInfo<HardwareFireDeviceVO> list(HardwareFireDeviceVO fireDeviceVO) {
+        startPage();
+        List<HardwareFireDeviceVO> list = fireDeviceService.selectHardwareFireDeviceList(fireDeviceVO);
+        for (HardwareFireDeviceVO vo : list) {
+            JSONObject jsonObject = redisService.getCacheObject(vo.getDeviceCode());
+            // 1离线 2在线 3异常
+            if (StringUtils.isNull(jsonObject)) {
+                vo.setDeviceStatus(1);
+            } else if (StringUtils.isNotNull(jsonObject.get("msg").toString())) {
+                vo.setDeviceStatus(3);
+                vo.setDescribe(jsonObject.get("msg").toString());
+            } else {
+                vo.setDeviceStatus(2);
+            }
+        }
+        return getDataTable(list);
+    }
+
+
+    /**
+     * 获取实验室灭火设备详细信息
+     */
+    @ApiOperation(value = "获取实验室灭火设备详细信息", notes = "权限字符:" + PerPrefix.ALGORITHM_FIREDEVICE + PerFun.QUERY)
+    @PreAuthorize(hasPermi = PerPrefix.ALGORITHM_FIREDEVICE + PerFun.QUERY)
+    @GetMapping(value = "/{id}")
+    public ResultData<HardwareFireDeviceVO> getInfo(@PathVariable("id") Long id) {
+        HardwareFireDeviceVO vo = fireDeviceService.selectHardwareFireDeviceById(id);
+        JSONObject jsonObject = redisService.getCacheObject(vo.getDeviceCode());
+        // 1离线 2在线 3异常
+        if (StringUtils.isNull(jsonObject)) {
+            vo.setDeviceStatus(1);
+        } else if (StringUtils.isNotNull(jsonObject.get("msg").toString())) {
+            vo.setDeviceStatus(3);
+            vo.setDescribe(jsonObject.get("msg").toString());
+        } else {
+            vo.setDeviceStatus(2);
+        }
+        return ResultData.success(vo);
+    }
+
+    /**
+     * 新增实验室灭火设备
+     */
+    @ApiOperation(value = "新增实验室灭火设备", notes = "权限字符:" + PerPrefix.ALGORITHM_FIREDEVICE + PerFun.ADD)
+    @PreAuthorize(hasPermi = PerPrefix.ALGORITHM_FIREDEVICE + PerFun.ADD)
+    @Log(title = "灭火设备", businessType = BusinessType.INSERT)
+    @PostMapping
+    public ResultData add(@RequestBody HardwareFireDevice fireDevice) {
+        return ResultData.result(fireDeviceService.insertHardwareFireDevice(fireDevice));
+    }
+
+    /**
+     * 修改实验室灭火设备
+     */
+    @ApiOperation(value = "修改实验室灭火设备", notes = "权限字符:" + PerPrefix.ALGORITHM_FIREDEVICE + PerFun.EDIT)
+    @PreAuthorize(hasPermi = PerPrefix.ALGORITHM_FIREDEVICE + PerFun.EDIT)
+    @Log(title = "灭火设备", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public ResultData edit(@RequestBody HardwareFireDevice fireDevice) {
+        return ResultData.result(fireDeviceService.updateHardwareFireDevice(fireDevice));
+    }
+
+    /**
+     * 删除实验室灭火设备
+     */
+    @ApiOperation(value = "删除实验室灭火设备", notes = "权限字符:" + PerPrefix.ALGORITHM_FIREDEVICE + PerFun.REMOVE)
+    @PreAuthorize(hasPermi = PerPrefix.ALGORITHM_FIREDEVICE + PerFun.REMOVE)
+    @Log(title = "灭火设备", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public ResultData remove(@PathVariable Long[] ids) {
+        return ResultData.result(fireDeviceService.deleteHardwareFireDeviceByIds(ids));
+    }
+
+    @GetMapping(value = "/test")
+    public ResultData test(Long subjectId) {
+        String str = fireDeviceLogService.insertFireAutomatic("28613608F0CA1");
+        String fireJson = redisService.getCacheObject("alarm/sendFire/28613608F0CA");
+        logger.info(waitTime + "");
+        return ResultData.success(str);
+    }
+
+    public static void main(String[] args) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("flg", false);
+        map.put("str", "AAA,222,DFR");
+        System.out.println(map.toString());
+    }
+}

+ 64 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/mapper/FireDeviceLogMapper.java

@@ -0,0 +1,64 @@
+package com.zd.alg.firedevice.mapper;
+
+
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDeviceLog;
+
+import java.util.List;
+
+
+/**
+ * 灭火设备日志 Mapper接口
+ *
+ * @author xxf
+ * @date 2022-11-24
+ */
+public interface FireDeviceLogMapper
+{
+    /**
+     * 查询实验室灭火设备日志
+     *
+     * @param labFireDeviceLog 灭火设备日志
+     * @return 灭火设备日志
+     */
+    public List<HardwareFireDeviceLog> selectLabFireDeviceLogList(HardwareFireDeviceLog labFireDeviceLog);
+
+
+    /****
+     *根据id查询
+     * @param id
+     * @return
+     */
+    public HardwareFireDeviceLog selectLabFireDeviceLogById(Long id);
+
+    /**
+     * 新增灭火设备日志
+     *
+     * @param labFireDeviceLog 灭火设备日志
+     * @return 结果
+     */
+    public int insertLabFireDeviceLog(HardwareFireDeviceLog labFireDeviceLog);
+
+    /**
+     * 修改灭火设备日志
+     *
+     * @param labFireDeviceLog 灭火设备日志
+     * @return 结果
+     */
+    public int updateLabFireDeviceLog(HardwareFireDeviceLog labFireDeviceLog);
+
+    /**
+     * 删除灭火设备日志
+     *
+     * @param id 灭火设备日志主键
+     * @return 结果
+     */
+    public int deleteLabFireDeviceLogById(Long id);
+
+    /**
+     * 批量删除灭火设备日志
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteLabFireDeviceLogByIds(Long[] ids);
+}

+ 64 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/mapper/FireDeviceMapper.java

@@ -0,0 +1,64 @@
+package com.zd.alg.firedevice.mapper;
+
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDevice;
+import com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO;
+
+import java.util.List;
+
+
+/**
+ * 灭火设备 Mapper接口
+ *
+ * @author xxf
+ * @date 2022-11-24
+ */
+public interface FireDeviceMapper
+{
+    /**
+     * 查询实验室灭火设备
+     *
+     * @param fireDeviceVO 灭火设备
+     * @return 灭火设备
+     */
+    public List<HardwareFireDeviceVO> selectHardwareFireDeviceList(HardwareFireDeviceVO fireDeviceVO);
+
+
+    /****
+     *根据id查询
+     * @param id
+     * @return
+     */
+    public HardwareFireDeviceVO selectHardwareFireDeviceById(Long id);
+
+    /**
+     * 新增灭火设备
+     *
+     * @param fireDevice 灭火设备
+     * @return 结果
+     */
+    public int insertHardwareFireDevice(HardwareFireDevice fireDevice);
+
+    /**
+     * 修改灭火设备
+     *
+     * @param labFireDevice 灭火设备
+     * @return 结果
+     */
+    public int updateHardwareFireDevice(HardwareFireDevice labFireDevice);
+
+    /**
+     * 删除灭火设备
+     *
+     * @param id 灭火设备主键
+     * @return 结果
+     */
+    public int deleteHardwareFireDeviceById(Long id);
+
+    /**
+     * 批量删除灭火设备
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteHardwareFireDeviceByIds(Long[] ids);
+}

+ 71 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/service/IFireDeviceLogService.java

@@ -0,0 +1,71 @@
+package com.zd.alg.firedevice.service;
+
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDevice;
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDeviceLog;
+import com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO;
+
+import java.util.List;
+
+/**
+ * 灭火设备日志Service接口
+ *
+ * @author xxf
+ * @date 2022-11-24
+ */
+public interface IFireDeviceLogService
+{
+    /**
+     * 查询实验室灭火设备日志
+     *
+     * @param fireDeviceLog 灭火设备日志
+     * @return 灭火设备日志
+     */
+    public List<HardwareFireDeviceLog> selectFireDeviceLogList(HardwareFireDeviceLog fireDeviceLog);
+
+
+    /****
+     *根据id查询
+     * @param id
+     * @return
+     */
+    public HardwareFireDeviceLog selectFireDeviceLogById(Long id);
+
+    /**
+     * 新增灭火设备日志
+     *
+     * @param fireDeviceLog 灭火设备日志
+     * @return 结果
+     */
+    public int insertFireDeviceLog(HardwareFireDeviceLog fireDeviceLog);
+
+    /**
+     * 修改灭火设备日志
+     *
+     * @param fireDeviceLog 灭火设备日志
+     * @return 结果
+     */
+    public int updateFireDeviceLog(HardwareFireDeviceLog fireDeviceLog);
+
+    /**
+     * 删除灭火设备日志
+     *
+     * @param id 灭火设备日志主键
+     * @return 结果
+     */
+    public int deleteFireDeviceLogById(Long id);
+
+    /**
+     * 批量删除灭火设备日志
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteFireDeviceLogByIds(Long[] ids);
+
+    /***
+     * 自动灭火日志添加
+     * @param code 继电器编号
+     * @return
+     */
+    public String insertFireAutomatic(String code);
+}

+ 63 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/service/IFireDeviceService.java

@@ -0,0 +1,63 @@
+package com.zd.alg.firedevice.service;
+
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDevice;
+import com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO;
+
+import java.util.List;
+
+/**
+ * 灭火设备Service接口
+ *
+ * @author xxf
+ * @date 2022-11-24
+ */
+public interface IFireDeviceService
+{
+    /**
+     * 查询实验室灭火设备
+     *
+     * @param fireDeviceVO 灭火设备
+     * @return 灭火设备
+     */
+    public List<HardwareFireDeviceVO> selectHardwareFireDeviceList(HardwareFireDeviceVO fireDeviceVO);
+
+
+    /****
+     *根据id查询
+     * @param id
+     * @return
+     */
+    public HardwareFireDeviceVO selectHardwareFireDeviceById(Long id);
+
+    /**
+     * 新增灭火设备
+     *
+     * @param fireDevice 灭火设备
+     * @return 结果
+     */
+    public int insertHardwareFireDevice(HardwareFireDevice fireDevice);
+
+    /**
+     * 修改灭火设备
+     *
+     * @param fireDevice 灭火设备
+     * @return 结果
+     */
+    public int updateHardwareFireDevice(HardwareFireDevice fireDevice);
+
+    /**
+     * 删除灭火设备
+     *
+     * @param id 灭火设备主键
+     * @return 结果
+     */
+    public int deleteHardwareFireDeviceById(Long id);
+
+    /**
+     * 批量删除灭火设备
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteHardwareFireDeviceByIds(Long[] ids);
+}

+ 145 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/service/impl/FireDeviceLogServiceImpl.java

@@ -0,0 +1,145 @@
+package com.zd.alg.firedevice.service.impl;
+
+
+import com.zd.alg.firedevice.mapper.FireDeviceLogMapper;
+import com.zd.alg.firedevice.mapper.FireDeviceMapper;
+import com.zd.alg.firedevice.service.IFireDeviceLogService;
+import com.zd.alg.firedevice.utils.FireDeviceStatusTask;
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDeviceLog;
+import com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO;
+import com.zd.common.core.redis.RedisService;
+import com.zd.common.core.utils.SaveUtil;
+import com.zd.common.core.utils.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 灭火设备日志 Service业务层处理
+ *
+ * @author xxf
+ * @date 2022-11-24
+ */
+@Service
+public class FireDeviceLogServiceImpl implements IFireDeviceLogService {
+
+    @Autowired
+    private FireDeviceLogMapper fireDeviceLogMapper;
+
+    @Autowired
+    private FireDeviceMapper fireDeviceMapper;
+
+    @Autowired
+    private RedisService redisService;
+
+    /**
+     * 查询实验室灭火设备日志
+     *
+     * @param fireDeviceLog 灭火设备日志
+     * @return 灭火设备日志
+     */
+    @Override
+    public List<HardwareFireDeviceLog> selectFireDeviceLogList(HardwareFireDeviceLog fireDeviceLog) {
+        return fireDeviceLogMapper.selectLabFireDeviceLogList(fireDeviceLog);
+    }
+
+    /****
+     *根据id查询
+     * @param id
+     * @return
+     */
+    @Override
+    public HardwareFireDeviceLog selectFireDeviceLogById(Long id) {
+        return fireDeviceLogMapper.selectLabFireDeviceLogById(id);
+    }
+
+    /**
+     * 新增灭火设备日志
+     *
+     * @param fireDeviceLog 灭火设备日志
+     * @return 结果
+     */
+    @Override
+    public int insertFireDeviceLog(HardwareFireDeviceLog fireDeviceLog) {
+        //设置其他公共字段
+        SaveUtil.setCommonAttr(fireDeviceLog);
+        return fireDeviceLogMapper.insertLabFireDeviceLog(fireDeviceLog);
+    }
+
+    /**
+     * 修改灭火设备日志
+     *
+     * @param fireDeviceLog 灭火设备日志
+     * @return 结果
+     */
+    @Override
+    public int updateFireDeviceLog(HardwareFireDeviceLog fireDeviceLog) {
+        return fireDeviceLogMapper.updateLabFireDeviceLog(fireDeviceLog);
+    }
+
+    /**
+     * 删除灭火设备日志
+     *
+     * @param id 灭火设备日志主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFireDeviceLogById(Long id) {
+        return fireDeviceLogMapper.deleteLabFireDeviceLogById(id);
+    }
+
+    /**
+     * 批量删除灭火设备日志
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    @Override
+    public int deleteFireDeviceLogByIds(Long[] ids) {
+        return fireDeviceLogMapper.deleteLabFireDeviceLogByIds(ids);
+    }
+
+    /***
+     * 自动灭火日志添加
+     * @param code 继电器编号
+     * @return
+     */
+    @Override
+    public String insertFireAutomatic(String code){
+        String str=null;
+        /*SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Date date = new Date(System.currentTimeMillis());
+        System.out.println(sdf.format(date));*/
+
+        // redis取值,当天日志是否添加
+        String isExist = redisService.getCacheObject(FireDeviceStatusTask.TOPIC_OUTFIRE_ISEXIST);
+        if(StringUtils.isEmpty(isExist)){
+            str="当天首次自动灭火日志已添加";
+        }else{
+            //根据继电器编码查询灭火设备信息
+            HardwareFireDeviceVO vo = new HardwareFireDeviceVO();
+            vo.setDeviceCode(code);
+            List<HardwareFireDeviceVO> list = fireDeviceMapper.selectHardwareFireDeviceList(vo);
+            if(list.size()>0){
+                //自动灭火日志添加
+                HardwareFireDeviceLog fireDeviceLog = new HardwareFireDeviceLog();
+                fireDeviceLog.setFireDeviceId(list.get(0).getId());
+                fireDeviceLog.setFlgTime(new Date());
+                List<HardwareFireDeviceLog> loglist = fireDeviceLogMapper.selectLabFireDeviceLogList(fireDeviceLog);
+                if(loglist.size()==0){
+                    fireDeviceLog.setRunType(1);
+                    fireDeviceLog.setCreateTime(new Date());
+                    fireDeviceLogMapper.insertLabFireDeviceLog(fireDeviceLog);
+                    str="当天首次自动灭火日志添加";
+                }else{
+                    str="当天自动灭火日志无需重复添加";
+                }
+            }
+        }
+
+        return str;
+    }
+}

+ 150 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/service/impl/FireDeviceServiceImpl.java

@@ -0,0 +1,150 @@
+package com.zd.alg.firedevice.service.impl;
+
+
+import com.zd.alg.firedevice.mapper.FireDeviceMapper;
+import com.zd.alg.firedevice.service.IFireDeviceService;
+import com.zd.alg.firedevice.utils.FireDeviceStatusTask;
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDevice;
+import com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO;
+import com.zd.common.core.exception.ServiceException;
+import com.zd.common.core.redis.RedisService;
+import com.zd.common.core.security.TokenService;
+import com.zd.common.core.utils.SaveUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 灭火设备Service业务层处理
+ *
+ * @author xxf
+ * @date 2022-11-24
+ */
+@Service
+public class FireDeviceServiceImpl implements IFireDeviceService {
+
+    @Autowired
+    private FireDeviceMapper hardwareFireDeviceMapper;
+
+    @Autowired
+    private RedisService redisService;
+
+    /**
+     * 查询实验室灭火设备
+     *
+     * @param fireDeviceVO 灭火设备
+     * @return 灭火设备
+     */
+    @Override
+    public List<HardwareFireDeviceVO> selectHardwareFireDeviceList(HardwareFireDeviceVO fireDeviceVO) {
+        return hardwareFireDeviceMapper.selectHardwareFireDeviceList(fireDeviceVO);
+    }
+
+    /****
+     *根据id查询
+     * @param id
+     * @return
+     */
+    @Override
+    public HardwareFireDeviceVO selectHardwareFireDeviceById(Long id) {
+        return hardwareFireDeviceMapper.selectHardwareFireDeviceById(id);
+    }
+
+    /**
+     * 新增灭火设备
+     *
+     * @param fireDevice 灭火设备
+     * @return 结果
+     */
+    @Override
+    public int insertHardwareFireDevice(HardwareFireDevice fireDevice) {
+        HardwareFireDeviceVO vo = new HardwareFireDeviceVO();
+        vo.setDeviceCode(fireDevice.getDeviceCode());
+        vo.setSubjectId(fireDevice.getSubjectId());
+        List<HardwareFireDeviceVO> list = hardwareFireDeviceMapper.selectHardwareFireDeviceList(vo);
+        if (list.size() > 0) {
+            throw new ServiceException("采集器编号已经存在!");
+        }
+
+        vo=new HardwareFireDeviceVO();
+        vo.setRelayCode(fireDevice.getRelayCode());
+        vo.setSubjectId(fireDevice.getSubjectId());
+        list = hardwareFireDeviceMapper.selectHardwareFireDeviceList(vo);
+        if (list.size() > 0) {
+            throw new ServiceException("继电器编号已经存在!");
+        }
+
+        //设置其他公共字段
+        SaveUtil.setCommonAttr(fireDevice);
+        int flg = hardwareFireDeviceMapper.insertHardwareFireDevice(fireDevice);
+        //刷新redis缓存
+        setupRedis();
+        return flg;
+    }
+
+    /**
+     * 修改灭火设备
+     *
+     * @param fireDevice 灭火设备
+     * @return 结果
+     */
+    @Override
+    public int updateHardwareFireDevice(HardwareFireDevice fireDevice) {
+        HardwareFireDeviceVO vo = new HardwareFireDeviceVO();
+        vo.setDeviceCode(fireDevice.getDeviceCode());
+        vo.setSubjectId(fireDevice.getSubjectId());
+        List<HardwareFireDeviceVO> list = hardwareFireDeviceMapper.selectHardwareFireDeviceList(vo);
+        if (list.size() > 0 && !list.get(0).getId().equals(fireDevice.getId())) {
+            throw new ServiceException("采集器编号已经存在!");
+        }
+
+        vo=new HardwareFireDeviceVO();
+        vo.setRelayCode(fireDevice.getRelayCode());
+        vo.setSubjectId(fireDevice.getSubjectId());
+        list = hardwareFireDeviceMapper.selectHardwareFireDeviceList(vo);
+        if (list.size() > 0 && !list.get(0).getId().equals(fireDevice.getId())) {
+            throw new ServiceException("继电器编号已经存在!");
+        }
+
+        int flg =hardwareFireDeviceMapper.updateHardwareFireDevice(fireDevice);
+        //刷新redis缓存
+        setupRedis();
+        return flg;
+    }
+
+    /**
+     * 删除灭火设备
+     *
+     * @param id 灭火设备主键
+     * @return 结果
+     */
+    @Override
+    public int deleteHardwareFireDeviceById(Long id) {
+        int flg = hardwareFireDeviceMapper.deleteHardwareFireDeviceById(id);
+        //刷新redis缓存
+        setupRedis();
+        return flg;
+    }
+
+    /**
+     * 批量删除灭火设备
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    @Override
+    public int deleteHardwareFireDeviceByIds(Long[] ids) {
+        return hardwareFireDeviceMapper.deleteHardwareFireDeviceByIds(ids);
+    }
+
+    /***
+     * 查询所有灭火设备,更新到redis
+     */
+    private void setupRedis(){
+        HardwareFireDeviceVO fireDeviceVO = new HardwareFireDeviceVO();
+        List<HardwareFireDeviceVO> list = hardwareFireDeviceMapper.selectHardwareFireDeviceList(fireDeviceVO);
+        redisService.setCacheObject(FireDeviceStatusTask.REDIS_TASK_FIRE_DEVICE_LIST,list,1L, TimeUnit.MINUTES);
+    }
+}

+ 78 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/utils/FireDeviceStatusTask.java

@@ -0,0 +1,78 @@
+package com.zd.alg.firedevice.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.zd.alg.firedevice.service.IFireDeviceService;
+import com.zd.alg.mqtt.MqttSend;
+import com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO;
+import com.zd.common.core.redis.RedisService;
+import com.zd.model.constant.MqttConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author: xxf 定时更新灭火器状态
+ * @Date: 2022/11/25/14:58
+ * @Description:
+ */
+@Component
+public class FireDeviceStatusTask {
+
+    private static final Logger logger = LoggerFactory.getLogger(FireDeviceStatusTask.class);
+
+    /**
+     * redis键值(灭火设备集合)
+     */
+    public static final String REDIS_TASK_FIRE_DEVICE_LIST = "rdeisTaskFireDeviceList";
+
+
+    /**
+     * redis键值 灭火设备最后响应时间
+     */
+    public static final String TOPIC_FD_RESPOND_TIME = "topicFdRespondTime";
+
+    /**
+     * redis键值 灭火设备日志是否添加
+     */
+    public static final String TOPIC_OUTFIRE_ISEXIST = "topicOutfireIsExist";
+
+    @Autowired
+    private IFireDeviceService hardwareFireDeviceService;
+    @Autowired
+    private MqttSend mqttSend;
+    @Autowired
+    private RedisService redisService;
+
+
+    /**
+     * 定时更新灭火装置状态
+     *
+     */
+    //@Scheduled(cron = "0/20 * * * * ?")
+    public void getFireDeviceStatus() {
+        //redis取值
+        List<HardwareFireDeviceVO> list = JSON.parseArray(redisService.getCacheObject(REDIS_TASK_FIRE_DEVICE_LIST) + "", HardwareFireDeviceVO.class);
+        if (list == null) {
+            list = hardwareFireDeviceService.selectHardwareFireDeviceList(new HardwareFireDeviceVO());
+            //redis存值,时效1分钟
+            redisService.setCacheObject(REDIS_TASK_FIRE_DEVICE_LIST, list, 1L, TimeUnit.MINUTES);
+        }
+
+        if (list != null) {
+            for (HardwareFireDeviceVO vo : list) {
+                //根据主机地址-位获取主机状态指令
+                String activeCode = FireLaborUtil.getFireActiveOrder(vo.getDeviceUrl());
+                //向mqtt发送状态信息
+                mqttSend.send(MqttConstants.TOPIC_FIRE_DEVICE + vo.getDeviceCode(), activeCode);
+                logger.info("集合数量:" + list.size() + ",mqtt消息推送, 灭火装置状态请求,实验室id:" + vo.getSubjectId() + ",设备编号:" + vo.getDeviceCode());
+            }
+        } else {
+            logger.info("====暂未查询到灭火主机信息====");
+        }
+    }
+}

+ 210 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/firedevice/utils/FireLaborUtil.java

@@ -0,0 +1,210 @@
+package com.zd.alg.firedevice.utils;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * @time2022-10-28
+ * @author 董高升
+ * @descprition 该类用于通过传参获取动态指令,进行状态查询,当收到状态火警的时候给传感器信号
+ */
+public class FireLaborUtil {
+    //功能码
+    private static final  String FUNCTION_CODE="03";
+    //起始地址高字节
+    private static final  String START_HIGN_CODE="00";
+    //起始地址低字节
+    private static final  String END_HIGN_CODE="00";
+    //36个寄存器查询地址
+    private static final  String All_REGISTER="00 24";
+
+
+    public static final Map<String, String> statusMap = new HashMap<String, String>();
+    static {
+        statusMap.put("00","无事件");
+        statusMap.put("01","火警");
+        statusMap.put("02","故障");
+        statusMap.put("03","动作");
+        statusMap.put("05","启动");
+    }
+
+    /**
+     * 静态map,用于存储 寄存器状态说明
+     *
+     */
+    public static final Map<Integer, String> myMap_0 = new HashMap<Integer, String>();
+    static {
+        myMap_0.put(1, "01 02");
+        myMap_0.put(2, "03 04");
+        myMap_0.put(3, "05 06");
+        myMap_0.put(4, "07 08");
+        myMap_0.put(5, "09 10");
+        myMap_0.put(6, "11 12");
+        myMap_0.put(7, "13 14");
+        myMap_0.put(8, "15 16");
+        myMap_0.put(9, "17 18");
+        myMap_0.put(10, "19 20");
+        myMap_0.put(11, "21 22");
+        myMap_0.put(12, "23 24");
+        myMap_0.put(13, "25 26");
+        myMap_0.put(14, "27 28");
+        myMap_0.put(15, "29 30");
+        myMap_0.put(16, "31 32");
+        myMap_0.put(17, "33 34");
+        myMap_0.put(18, "35 36");
+        myMap_0.put(19, "37 38");
+        myMap_0.put(20, "39 40");
+        myMap_0.put(21, "41 42");
+        myMap_0.put(22, "43 44");
+        myMap_0.put(23, "45 46");
+        myMap_0.put(24, "47 48");
+        myMap_0.put(25, "49 50");
+        myMap_0.put(26, "51 52");
+        myMap_0.put(27, "53 54");
+        myMap_0.put(28, "55 56");
+        myMap_0.put(29, "57 58");
+        myMap_0.put(30, "59 60");
+        myMap_0.put(31, "61 62");
+        myMap_0.put(32, "63 64");
+    }
+
+    /**
+     * 主机地址位
+     * @param addressBit
+     * @return
+     * 动态获取主机状态指令
+     * 寄存器地址
+     */
+    public static String getFireActiveOrder(Integer addressBit){
+       String activeCode="";
+       String coverCode=coverCode(addressBit);
+       activeCode=coverCode+" "+FUNCTION_CODE+" "+START_HIGN_CODE+" "+END_HIGN_CODE+" "+All_REGISTER+" ";
+       String disposeCode=activeCode.replace(" ","");
+       String crcCode=getCRC16Result(disposeCode);
+       activeCode+=crcCode;
+       return activeCode;
+    }
+
+
+    public static JSONObject getFireStatus(String returnCodes){
+        boolean fireStatus=false;
+        String msg="";
+        int fireNumber=0;
+        //returnCodes="02 03 48 00 00 00 00 02 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0A 00 00 00 40 3D ";
+        returnCodes=returnCodes.replace(" ","");
+        System.out.println("returnCodes length:"+returnCodes.length());
+        String registerCode=returnCodes.substring(6,returnCodes.length()-20);
+        System.out.println("registerCode:"+registerCode);
+        String mainCode=returnCodes.substring(134,returnCodes.length()-4);
+        System.out.println("mainCode:"+mainCode);
+        List<String> registerCodeList=parseArrayList(registerCode);
+        Set<String> statusSet=statusMap.keySet();
+        if(registerCodeList.contains("01")){
+            fireStatus=true;
+        }
+        for(int i=0;i<registerCodeList.size();i++){
+            String code=registerCodeList.get(i);
+            if(code.equals("01")){
+                fireNumber++;
+            }
+            for(String set:statusSet){
+                if(!registerCodeList.get(i).equals("00") && registerCodeList.get(i).equals(set)){
+                    msg+="NO:"+(i+1)+"号设备"+statusMap.get(set)+" ";
+                }
+            }
+        }
+        List<String> mainCodeList=parseArrayList(mainCode);
+        JSONObject jsonObject=new JSONObject();
+        if(mainCodeList.get(0).equals("05")){
+            jsonObject.put("startSpray","1");
+        }else{
+            jsonObject.put("startSpray","0");
+        }
+        if(mainCodeList.get(1).equals("03")){
+            jsonObject.put("gasSpray","1");
+        }else{
+            jsonObject.put("gasSpray","0");
+        }
+        jsonObject.put("fireNumber",fireNumber);
+        jsonObject.put("fireStatus",fireStatus);
+        jsonObject.put("msg",msg);
+        jsonObject.put("createTime",System.currentTimeMillis());
+        return jsonObject;
+    }
+
+    /**
+     * 主机地址位
+     * @param addressBit
+     * @return
+     */
+    private static String coverCode(Integer addressBit){
+        if(addressBit>=10){
+            return String.valueOf(addressBit);
+        }
+        return String.format("%0"+2+"x", Integer.valueOf(addressBit));
+    }
+
+    /**
+     * 解析数据为数组状态
+     * @return
+     * returnCode返回数据
+     */
+    /**
+     * 存放16进制字符串,字符串2为 2为存
+     * @param hexString
+     * @return
+     */
+    public static List<String> parseArrayList(String hexString){
+        List<String> strings = new ArrayList<>();
+        for (int i = 0; i < hexString.length()/2; i++){
+            int index = i * 2;
+            String var = hexString.substring(index,index+2);
+            strings.add(var);
+        }
+        return strings;
+    }
+
+    /**
+     * CRC16_MODBUS:多项式x16+x15+x2+1(0x8005),初始值0xFFFF,低位在前,高位在后,结果与0x0000异或
+     * 以上计算步骤中的多项式0xA001是0x8005按位颠倒后的结果。
+     * 0x8408是0x1021按位颠倒后的结果。
+     * @param s 需要输入十六进制字符串
+     * @return 结果数据CRC16 modbus格式
+     */
+    public static String getCRC16Result(String s){
+        int CRC = 0x0000ffff;
+        for (int i=0;i<s.length();i=i+2){
+            int CRCL=CRC&0x000000FF;//低八位
+            int CRCH=CRC&0x0000FF00;//高八位
+            String CRCIn = s.substring(i,i+2);
+            int a = Integer.parseInt(CRCIn,16);//待处理数据转16进制
+            CRC=CRCH+CRCL^a;
+            for(int j=0;j<8;j++){
+                if((CRC&0x0001)==0){
+                    CRC=CRC>>1;
+                }else {
+                    CRC>>=1;
+                    CRC=CRC^0xA001;
+                }
+            }
+        }
+        //      交换
+        int CRCL=CRC&0x000000FF;//低八位
+        int CRCH=CRC&0x0000FF00;//高八位
+        CRC=CRCL<<8|CRCH>>8;//最好用按位与,别用加
+        String hexString=Integer.toHexString(CRC).toUpperCase();
+        //给crc加空格格式
+        String regex = "(.{2})";
+        hexString=hexString.replaceAll(regex, "$1 ");
+        return hexString;
+    }
+
+    public static void main(String[] args) {
+        String msg="";
+        System.out.println(getFireActiveOrder(2));
+        JSONObject jsonObject=getFireStatus("0");
+        System.out.println(jsonObject.toJSONString());
+    }
+}

+ 243 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/mqtt/MqttConfig.java

@@ -0,0 +1,243 @@
+package com.zd.alg.mqtt;
+
+import com.alibaba.fastjson.JSONObject;
+import com.zd.alg.firedevice.service.IFireDeviceLogService;
+import com.zd.alg.firedevice.service.IFireDeviceService;
+import com.zd.alg.firedevice.utils.FireDeviceStatusTask;
+import com.zd.alg.firedevice.utils.FireLaborUtil;
+import com.zd.algorithm.api.firedevice.entity.HardwareFireDeviceLog;
+import com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO;
+import com.zd.common.core.redis.RedisService;
+import com.zd.model.constant.MqttConstants;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.integration.annotation.ServiceActivator;
+import org.springframework.integration.channel.DirectChannel;
+import org.springframework.integration.core.MessageProducer;
+import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
+import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
+import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
+import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
+import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.*;
+
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * mqtt配置
+ *
+ * @author dgs
+ */
+@Configuration
+public class MqttConfig {
+    static Logger logger = LoggerFactory.getLogger(MqttConfig.class);
+
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private MqttSend mqttSend;
+
+    @Autowired
+    private IFireDeviceLogService deviceLogService;
+
+    private static final byte[] WILL_DATA;
+
+    private static String WILL_TOPIC = "willTopic";
+
+    static {
+        WILL_DATA = "offline".getBytes();
+    }
+
+    public static final String MQTT_INBOUND_CHANNEL = "mqttInboundChannel";
+
+
+    public static final String MQTT_OUTBOUND_CHANNEL = "mqttInboundChannel";
+
+    @Value("${mqtt.username}")
+    private String username;
+
+    @Value("${mqtt.password}")
+    private String password;
+
+    @Value("${mqtt.url}")
+    private String url;
+
+    @Value("${mqtt.defaultTopic}")
+    private String defaultTopic;
+
+    @Value("${mqtt.producer.clientId}")
+    private String producerClientId;
+
+    @Value("${mqtt.consumer.clientId}")
+    private String consumerClientId;
+
+    @Value("${mqtt.consumer.maxInflight}")
+    private Integer maxInflight;
+
+    private MqttPahoMessageDrivenChannelAdapter adapter;
+
+
+    /**
+     * 连接mqtt配置
+     *
+     * @return
+     */
+    @Bean
+    public MqttConnectOptions mqttConnectOptions() {
+        MqttConnectOptions options = new MqttConnectOptions();
+        // false,服务器会保留客户端的连接记录
+        // true,表示每次连接到服务器都以新的身份连接
+        options.setCleanSession(false);
+        options.setAutomaticReconnect(true);
+        options.setUserName(username);
+        options.setPassword(password.toCharArray());
+        options.setMaxInflight(maxInflight);
+        options.setServerURIs(StringUtils.split(url, ","));
+        //超时时间 单位为秒
+        options.setConnectionTimeout(60);
+        //会话心跳时间 单位: s, 间隔时间:1.5*20秒向客户端发送心跳判断客户端是否在线
+        options.setKeepAliveInterval(60);
+        //设置“遗嘱”消息的话题,若客户端与服务器之间的连接意外中断,服务器将发布客户端的“遗嘱”消息。
+        options.setWill(WILL_TOPIC, WILL_DATA, 2, false);
+        return options;
+    }
+
+
+    /**
+     * MQTT客户端
+     */
+    @Bean
+    public MqttPahoClientFactory mqttClientFactory() {
+        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
+        factory.setConnectionOptions(mqttConnectOptions());
+        return factory;
+    }
+
+    /**
+     * 发送者消息通道
+     */
+    @Bean(name = MQTT_OUTBOUND_CHANNEL)
+    public MessageChannel mqttOutboundChannel() {
+        return new DirectChannel();
+    }
+
+    /**
+     * 发送者消息处理
+     *
+     * @return
+     */
+    @Bean
+    @ServiceActivator(inputChannel = MQTT_OUTBOUND_CHANNEL)
+    public MessageHandler mqttOutbound() {
+        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(
+                producerClientId,
+                mqttClientFactory());
+        messageHandler.setAsync(true);
+        messageHandler.setDefaultTopic(defaultTopic);
+        return messageHandler;
+    }
+
+    /**
+     * 消息订阅
+     *
+     * @return
+     */
+    @Bean
+    public MessageProducer inbound() {
+        // 可同时消费(订阅)多个Topic
+        adapter = new MqttPahoMessageDrivenChannelAdapter(consumerClientId, mqttClientFactory(), StringUtils.split(defaultTopic, ","));
+        adapter.setCompletionTimeout(5000);
+        adapter.setConverter(new DefaultPahoMessageConverter());
+        adapter.setQos(2);
+        // 设置订阅通道
+        adapter.setOutputChannel(mqttInboundChannel());
+        return adapter;
+    }
+
+
+    /**
+     * 消费者消息通道
+     *
+     * @return
+     */
+    @Bean(name = MQTT_INBOUND_CHANNEL)
+    public MessageChannel mqttInboundChannel() {
+        return new DirectChannel();
+    }
+
+    /**
+     * 消费者消息处理
+     * 设备心跳
+     *
+     * @return
+     */
+    @Bean
+    @ServiceActivator(inputChannel = MQTT_INBOUND_CHANNEL)
+    public MessageHandler mqttInbound() {
+
+        return new MessageHandler() {
+            @Override
+            public void handleMessage(Message<?> message) throws MessagingException {
+                MessageHeaders messageHeaders = message.getHeaders();
+                //String receivedTopic = (String) messageHeaders.get(MqttHeaders.RECEIVED_TOPIC);
+                String receivedTopic = (String) messageHeaders.get(MqttHeaders.TOPIC);
+//                logger.info("[通道] - [{}]",receivedTopic);
+//                logger.info("[消息] - [{}]",message.getPayload());
+                String messageStr = message.getPayload().toString();
+//                logger.info("======= receivedTopic:" + receivedTopic + " messageStr:" + messageStr);
+                if (receivedTopic.startsWith(MqttConstants.TOPIC_FIRE_DEVICE_RECEIVE)) {
+                    logger.info("灭火设备消息消费,receivedTopic:" + receivedTopic + " messageStr:" + messageStr);
+                    receivedTopic = receivedTopic.substring(receivedTopic.lastIndexOf("/") + 1, receivedTopic.length());
+                    //根据状态指令获取主机状态
+                    JSONObject jsonObject = FireLaborUtil.getFireStatus(messageStr);
+                    Integer fireNumber = Integer.valueOf(jsonObject.get("fireNumber").toString());
+                    //灭火主机发生预警
+                    if (fireNumber > 0) {
+                        logger.info("灭火设备传感器异常,通知预案,状态:" + jsonObject.toJSONString());
+                        mqttSend.send(MqttConstants.TOPIC_FIRE_DEVICE_WARN,jsonObject.toJSONString());
+                        //自动灭火
+                        if (fireNumber == 2) {
+                            //redis中是否已存在日志已添加标识
+                            String isExist = redisService.getCacheObject(FireDeviceStatusTask.TOPIC_OUTFIRE_ISEXIST);
+                            if(StringUtils.isEmpty(isExist)){
+                                //自动灭火日志添加
+                                String str = deviceLogService.insertFireAutomatic(receivedTopic);
+                                //redis存值,灭火日志已经添加标识
+                                redisService.setCacheObject(FireDeviceStatusTask.TOPIC_OUTFIRE_ISEXIST, str, 60L, TimeUnit.MINUTES);
+                                logger.info("自动灭火日志添加执行结果," + str);
+                            }
+                        }
+                    }
+                    //redis存值 采集器编号:主机状态json
+                    redisService.setCacheObject(receivedTopic, jsonObject, 1L, TimeUnit.MINUTES);
+                    //redis存值 灭火主机响应时间
+                    redisService.setCacheObject(FireDeviceStatusTask.TOPIC_FD_RESPOND_TIME, System.currentTimeMillis(), 1L, TimeUnit.MINUTES);
+                }
+            }
+        };
+    }
+
+    public static String byte2Hex(byte[] bytes) {
+        StringBuilder builder = new StringBuilder();
+        String temp;
+        for (byte aByte : bytes) {
+            temp = Integer.toHexString(aByte & 0xFF);
+            if (temp.length() == 1) {
+                //1得到一位的进行补0操作
+                builder.append("0");
+            }
+            builder.append(temp);
+        }
+        return builder.toString();
+    }
+}

+ 39 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/mqtt/MqttProducerUtils.java

@@ -0,0 +1,39 @@
+package com.zd.alg.mqtt;
+
+import org.springframework.integration.annotation.MessagingGateway;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+/**
+ * 消息发送者
+ *
+ * @author zpp
+ */
+@Component
+@MessagingGateway(defaultRequestChannel = MqttConfig.MQTT_OUTBOUND_CHANNEL)
+public interface MqttProducerUtils {
+
+    /**
+     * 发送消息到默认主题
+     * @param data
+     */
+    void send(String data);
+
+    /**
+     * 发送信息
+     * @param topic
+     * @param qos
+     *        0,只发送一次,消费者会丢消息
+     *        1,消费者没收到消息之前会一直重试,但消费者有可能收到重复的消息
+     *        2,在【1】的基础上去重,消费者只会收到1条消息
+     * @param payload 消息
+     */
+    void send(@Header(MqttHeaders.TOPIC) String topic,
+              @Header(MqttHeaders.QOS) int qos,
+              String payload);
+
+    void send(@Header(MqttHeaders.TOPIC) String topic,
+              @Header(MqttHeaders.QOS) int qos,
+              byte[] payload);
+}

+ 65 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/mqtt/MqttSend.java

@@ -0,0 +1,65 @@
+package com.zd.alg.mqtt;
+
+import com.alibaba.fastjson.JSON;
+import com.zd.alg.mqtt.entiy.MessageBody;
+import com.zd.alg.mqtt.enums.SendMode;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 公用发送类
+ *
+ * @Author: zhoupan
+ * @Date: 2021/10/08/10:42
+ * @Description:
+ */
+@Service
+public class MqttSend {
+
+    @Autowired
+    MqttProducerUtils mqttProducer;
+
+
+    /**
+     * 发送消息:去重模式
+     *
+     * @param topic
+     * @param messageBody
+     */
+    public void send(String topic, MessageBody messageBody) {
+        mqttProducer.send(topic, SendMode.DISTINCT.getCode(), JSON.toJSONString(messageBody));
+    }
+
+    /**
+     * 发送消息
+     *
+     * @param topic
+     * @param messageBody
+     * @param sendMode
+     */
+    public void send(String topic, MessageBody messageBody, SendMode sendMode) {
+        mqttProducer.send(topic, sendMode.getCode(), JSON.toJSONString(messageBody));
+    }
+
+
+    /**
+     * 发送消息:去重模式
+     *
+     * @param topic
+     * @param messageBody
+     */
+    public void send(String topic, String messageBody) {
+        mqttProducer.send(topic, SendMode.ONCE.getCode(), messageBody);
+    }
+
+    /**
+     * 发送消息:去重模式
+     *
+     * @param topic
+     * @param messageBody
+     */
+    public void send(String topic, byte[] messageBody) {
+        mqttProducer.send(topic, SendMode.ONCE.getCode(), messageBody);
+    }
+
+}

+ 95 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/mqtt/entiy/MessageBody.java

@@ -0,0 +1,95 @@
+package com.zd.alg.mqtt.entiy;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 发送请求体
+ * @Author: zhoupan
+ * @Date: 2021/10/08/10:46
+ * @Description:
+ */
+public class MessageBody<T> {
+
+    public static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    T data;
+
+    String msg;
+
+    String sendDate;
+
+    Integer type;
+
+    Long messageId;
+
+    public MessageBody() {
+        //获取当前时间
+        LocalDateTime newTime = LocalDateTime.now();
+        String format = formatter.format(newTime);
+        this.sendDate = format;
+    }
+
+    public MessageBody(String msg) {
+        LocalDateTime newTime = LocalDateTime.now();
+        String format = formatter.format(newTime);
+        this.sendDate = format;
+        this.msg = msg;
+    }
+
+    public MessageBody(String msg, Integer type) {
+        LocalDateTime newTime = LocalDateTime.now();
+        String format = formatter.format(newTime);
+        this.sendDate = format;
+        this.msg = msg;
+        this.type = type;
+    }
+
+    public MessageBody(String msg, Integer type, Long messageId) {
+        LocalDateTime newTime = LocalDateTime.now();
+        String format = formatter.format(newTime);
+        this.sendDate = format;
+        this.msg = msg;
+        this.type = type;
+        this.messageId = messageId;
+    }
+
+    public Integer getType() {
+        return type;
+    }
+
+    public void setType(Integer type) {
+        this.type = type;
+    }
+
+    public String getSendDate() {
+        return sendDate;
+    }
+
+    public void setSendDate(String sendDate) {
+        this.sendDate = sendDate;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public Long getMessageId() {
+        return messageId;
+    }
+
+    public void setMessageId(Long messageId) {
+        this.messageId = messageId;
+    }
+}

+ 26 - 0
zd-modules/zd-algorithm/src/main/java/com/zd/alg/mqtt/enums/SendMode.java

@@ -0,0 +1,26 @@
+package com.zd.alg.mqtt.enums;
+
+/**
+ * 发送模式
+ * @Author: zhoupan
+ * @Date: 2021/10/08/10:56
+ * @Description:
+ */
+public enum SendMode {
+    //只发送一次
+    ONCE(0),
+    //重试
+    RETRY(1),
+    //重试上去重
+    DISTINCT(2),
+    ;
+    private int code;
+
+    SendMode(int code) {
+        this.code = code;
+    }
+
+    public int getCode() {
+        return code;
+    }
+}

+ 108 - 0
zd-modules/zd-algorithm/src/main/resources/mapper/firedevice/FireDeviceLogMapper.xml

@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zd.alg.firedevice.mapper.FireDeviceLogMapper">
+
+    <resultMap type="com.zd.algorithm.api.firedevice.entity.HardwareFireDeviceLog" id="LabFireDeviceLogResult">
+        <result property="id" column="id"/>
+        <result property="deptName" column="dept_name"/>
+        <result property="deptId" column="dept_id"/>
+        <result property="createTime" column="create_time"/>
+        <result property="userId" column="user_id"/>
+        <result property="createBy" column="create_by"/>
+
+        <result property="fireDeviceId" column="fire_device_id"/>
+        <result property="runType" column="run_type"/>
+        <result property="runResult" column="run_result"/>
+    </resultMap>
+
+    <sql id="selectFireDeviceLog">
+        select id,
+               fire_device_id,
+               run_type,
+               run_result,
+               user_id,
+               create_by,
+               dept_id,
+               dept_name,
+               create_time
+        from hardware_fire_device_log
+    </sql>
+
+    <select id="selectLabFireDeviceLogList" parameterType="com.zd.algorithm.api.firedevice.entity.HardwareFireDeviceLog"
+            resultMap="LabFireDeviceLogResult">
+        <include refid="selectFireDeviceLog"/>
+        <where>
+            <if test="fireDeviceId != null ">and fire_device_id = #{fireDeviceId}</if>
+            <if test="runType != null ">and run_type = #{runType}</if>
+            <if test="runResult != null ">and run_result =#{runResult}</if>
+            <if test="userId != null ">and user_id = #{userId}</if>
+            <if test="createBy != null ">and create_by = #{createBy}</if>
+            <if test="deptId != null ">and dept_id = #{deptId}</if>
+            <if test="deptName != null ">and dept_name = #{deptName}</if>
+            <if test="createTime != null ">and create_time = #{createTime}</if>
+            <if test="flgTime != null ">and date_format(create_time,'%Y-%m-%d') = date_format(#{flgTime},'%Y-%m-%d')</if>
+            ${params.dataScope}
+        </where>
+        order by create_time desc
+    </select>
+
+    <select id="selectLabFireDeviceLogById" parameterType="Long" resultMap="LabFireDeviceLogResult">
+        <include refid="selectFireDeviceLog"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertLabFireDeviceLog" parameterType="com.zd.algorithm.api.firedevice.entity.HardwareFireDeviceLog" useGeneratedKeys="true"
+            keyProperty="id">
+        insert into hardware_fire_device_log
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="deptName != null">dept_name,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="fireDeviceId != null">fire_device_id,</if>
+            <if test="runType != null">run_type,</if>
+            <if test="runResult != null">run_result,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="deptName != null">#{deptName},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="fireDeviceId != null">#{fireDeviceId},</if>
+            <if test="runType != null">#{runType},</if>
+            <if test="runResult != null">#{runResult},</if>
+        </trim>
+    </insert>
+
+    <update id="updateLabFireDeviceLog" parameterType="com.zd.algorithm.api.firedevice.entity.HardwareFireDeviceLog">
+        update hardware_fire_device_log
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="deptName != null">dept_name = #{deptName},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="createBy != null">create_by = #{createBy},</if>
+            <if test="fireDeviceId != null">fire_device_id = #{fireDeviceId},</if>
+            <if test="runType != null">run_type = #{runType},</if>
+            <if test="runResult != null">run_result = #{runResult},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteLabFireDeviceLogById" parameterType="Long">
+        delete
+        from hardware_fire_device_log
+        where id = #{id}
+    </delete>
+
+    <delete id="deleteLabFireDeviceLogByIds" parameterType="String">
+        delete from hardware_fire_device_log where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 135 - 0
zd-modules/zd-algorithm/src/main/resources/mapper/firedevice/FireDeviceMapper.xml

@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zd.alg.firedevice.mapper.FireDeviceMapper">
+
+    <resultMap type="com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO" id="LabFireDeviceResult">
+        <result property="id" column="id"/>
+        <result property="deptName" column="dept_name"/>
+        <result property="deptId" column="dept_id"/>
+        <result property="createTime" column="create_time"/>
+        <result property="userId" column="user_id"/>
+        <result property="createBy" column="create_by"/>
+        <result property="updateBy" column="update_by"/>
+        <result property="deviceName" column="device_name"/>
+        <result property="deviceCode" column="device_code"/>
+        <result property="relayCode" column="relay_code"/>
+        <result property="deviceUrl" column="device_url"/>
+        <result property="deviceCountDown" column="device_count_down"/>
+        <result property="deviceStatus" column="device_status"/>
+        <result property="subjectId" column="subject_id"/>
+    </resultMap>
+
+    <sql id="selectFireDeviceVo">
+        select fd.id,
+               fd.device_name,
+               fd.device_code,
+               fd.relay_code,
+               fd.device_url,
+               fd.device_count_down,
+               fd.device_status,
+               fd.subject_id,
+               fd.dept_id,
+               fd.dept_name,
+               fd.user_id,
+               fd.create_by,
+               fd.create_time,
+               ls.name      subjectName,
+               lsl.room,
+               sd.dept_name buildName
+        from hardware_fire_device fd
+                 LEFT JOIN lab_subject ls on fd.subject_id = ls.id
+                 LEFT JOIN lab_subject_layout lsl on lsl.floor_id = ls.layout_id and ls.id = fd.subject_id
+                 LEFT JOIN sys_dept sd on ls.build_id = sd.dept_id and ls.id = fd.subject_id
+    </sql>
+
+    <select id="selectHardwareFireDeviceList" parameterType="com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO"
+            resultMap="LabFireDeviceResult">
+        <include refid="selectFireDeviceVo"/>
+        <where>
+            <if test="searchValue != null  and searchValue != ''">
+                and (fd.device_name like concat('%', #{searchValue}, '%') or
+                ls.`name` like concat('%', #{searchValue}, '%') )
+            </if>
+            <if test="deviceName != null  and deviceName != ''">and fd.device_name like concat('%', #{deviceName}, '%')</if>
+            <if test="deviceCode != null and deviceCode != ''">and fd.device_code = #{deviceCode}</if>
+            <if test="relayCode != null and relayCode != ''">and fd.relay_code = #{relayCode}</if>
+            <if test="deviceUrl != null and deviceUrl != ''">and fd.device_url = #{deviceUrl}</if>
+            <if test="deviceCountDown != null ">and fd.device_count_down =#{deviceCountDown}</if>
+            <if test="deviceStatus != null ">and fd.device_status = #{deviceStatus}</if>
+            ${params.dataScope}
+        </where>
+        order by fd.create_time desc
+    </select>
+
+    <select id="selectHardwareFireDeviceById" parameterType="Long" resultMap="LabFireDeviceResult">
+        <include refid="selectFireDeviceVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertHardwareFireDevice" parameterType="com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO" useGeneratedKeys="true"
+            keyProperty="id">
+        insert into hardware_fire_device
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="deptName != null">dept_name,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="deviceName != null">device_name,</if>
+            <if test="deviceCode != null">device_code,</if>
+            <if test="relayCode != null">relay_code,</if>
+            <if test="deviceUrl != null">device_url,</if>
+            <if test="deviceCountDown != null">device_count_down,</if>
+            <if test="deviceStatus != null">device_status,</if>
+            <if test="subjectId != null">subject_id,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="deptName != null">#{deptName},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="deviceName != null">#{deviceName},</if>
+            <if test="deviceCode != null">#{deviceCode},</if>
+            <if test="relayCode != null">#{relayCode},</if>
+            <if test="deviceUrl != null">#{deviceUrl},</if>
+            <if test="deviceCountDown != null">#{deviceCountDown},</if>
+            <if test="deviceStatus != null">#{deviceStatus},</if>
+            <if test="subjectId != null">#{subjectId},</if>
+        </trim>
+    </insert>
+
+    <update id="updateHardwareFireDevice" parameterType="com.zd.algorithm.api.firedevice.entity.vo.HardwareFireDeviceVO">
+        update hardware_fire_device
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="deptName != null">dept_name = #{deptName},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="createBy != null">create_by = #{createBy},</if>
+            <if test="deviceName != null">device_name = #{deviceName},</if>
+            <if test="deviceCode != null">device_code = #{deviceCode},</if>
+            <if test="relayCode != null">relay_code = #{relayCode},</if>
+            <if test="deviceUrl != null">device_url = #{deviceUrl},</if>
+            <if test="deviceCountDown != null">device_count_down = #{deviceCountDown},</if>
+            <if test="deviceStatus != null">device_status = #{deviceStatus},</if>
+            <if test="subjectId != null">subject_id = #{subjectId},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteHardwareFireDeviceById" parameterType="Long">
+        delete
+        from hardware_fire_device
+        where id = #{id}
+    </delete>
+
+    <delete id="deleteHardwareFireDeviceByIds" parameterType="String">
+        delete from hardware_fire_device where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>