作者 钟来

修改bug

@@ -40,6 +40,11 @@ @@ -40,6 +40,11 @@
40 <groupId>com.zhonglai.luhui</groupId> 40 <groupId>com.zhonglai.luhui</groupId>
41 <artifactId>lh-mqtt-service</artifactId> 41 <artifactId>lh-mqtt-service</artifactId>
42 </dependency> 42 </dependency>
  43 + <!-- 定时-->
  44 + <dependency>
  45 + <groupId>com.zhonglai.luhui</groupId>
  46 + <artifactId>lh-quartz</artifactId>
  47 + </dependency>
43 <!-- 文档 --> 48 <!-- 文档 -->
44 <dependency > 49 <dependency >
45 <groupId>io.springfox</groupId> 50 <groupId>io.springfox</groupId>
@@ -82,6 +87,20 @@ @@ -82,6 +87,20 @@
82 <groupId>org.aspectj</groupId> 87 <groupId>org.aspectj</groupId>
83 <artifactId>aspectjrt</artifactId> 88 <artifactId>aspectjrt</artifactId>
84 </dependency> 89 </dependency>
  90 +
  91 + <dependency>
  92 + <groupId>cn.hutool</groupId>
  93 + <artifactId>hutool-all</artifactId>
  94 + </dependency>
  95 + <dependency>
  96 + <groupId>com.jcraft</groupId>
  97 + <artifactId>jsch</artifactId>
  98 + </dependency>
  99 +
  100 + <dependency>
  101 + <groupId>com.sun.mail</groupId>
  102 + <artifactId>javax.mail</artifactId>
  103 + </dependency>
85 </dependencies> 104 </dependencies>
86 105
87 <build> 106 <build>
@@ -10,8 +10,10 @@ import org.springframework.context.annotation.ComponentScan; @@ -10,8 +10,10 @@ import org.springframework.context.annotation.ComponentScan;
10 "com.ruoyi.system", 10 "com.ruoyi.system",
11 "com.ruoyi.framework", 11 "com.ruoyi.framework",
12 "com.ruoyi.generator", 12 "com.ruoyi.generator",
  13 + "com.ruoyi.quartz",
13 "com.zhonglai.luhui.admin.config", 14 "com.zhonglai.luhui.admin.config",
14 "com.zhonglai.luhui.admin.service", 15 "com.zhonglai.luhui.admin.service",
  16 + "com.zhonglai.luhui.admin.task",
15 "com.zhonglai.luhui.admin.controller", 17 "com.zhonglai.luhui.admin.controller",
16 "com.zhonglai.luhui.mqtt.comm.service.redis", 18 "com.zhonglai.luhui.mqtt.comm.service.redis",
17 "com.zhonglai.luhui.mqtt.service.db.mode" 19 "com.zhonglai.luhui.mqtt.service.db.mode"
1 package com.zhonglai.luhui.admin.controller.iot; 1 package com.zhonglai.luhui.admin.controller.iot;
2 2
  3 +import cn.hutool.core.bean.BeanUtil;
  4 +import com.alibaba.fastjson.JSONObject;
3 import com.ruoyi.common.annotation.Log; 5 import com.ruoyi.common.annotation.Log;
4 import com.ruoyi.common.core.controller.BaseController; 6 import com.ruoyi.common.core.controller.BaseController;
5 import com.ruoyi.common.core.domain.AjaxResult; 7 import com.ruoyi.common.core.domain.AjaxResult;
6 import com.ruoyi.common.core.page.TableDataInfo; 8 import com.ruoyi.common.core.page.TableDataInfo;
7 import com.ruoyi.common.enums.BusinessType; 9 import com.ruoyi.common.enums.BusinessType;
  10 +import com.ruoyi.common.utils.StringUtils;
8 import com.ruoyi.common.utils.poi.ExcelUtil; 11 import com.ruoyi.common.utils.poi.ExcelUtil;
9 import com.ruoyi.system.domain.IotAlert; 12 import com.ruoyi.system.domain.IotAlert;
10 import com.ruoyi.system.service.IIotAlertService; 13 import com.ruoyi.system.service.IIotAlertService;
  14 +import com.zhonglai.luhui.admin.dto.AlarmActionConfig;
  15 +import com.zhonglai.luhui.admin.dto.AlarmTriggersConfig;
11 import io.swagger.annotations.Api; 16 import io.swagger.annotations.Api;
12 import io.swagger.annotations.ApiImplicitParam; 17 import io.swagger.annotations.ApiImplicitParam;
13 import io.swagger.annotations.ApiImplicitParams; 18 import io.swagger.annotations.ApiImplicitParams;
@@ -18,6 +23,7 @@ import org.springframework.web.bind.annotation.*; @@ -18,6 +23,7 @@ import org.springframework.web.bind.annotation.*;
18 23
19 import javax.servlet.http.HttpServletResponse; 24 import javax.servlet.http.HttpServletResponse;
20 import java.util.List; 25 import java.util.List;
  26 +import java.util.Optional;
21 27
22 /** 28 /**
23 * 设备告警Controller 29 * 设备告警Controller
@@ -80,6 +86,14 @@ public class IotAlertController extends BaseController @@ -80,6 +86,14 @@ public class IotAlertController extends BaseController
80 @PostMapping 86 @PostMapping
81 public AjaxResult add(@RequestBody IotAlert alert) 87 public AjaxResult add(@RequestBody IotAlert alert)
82 { 88 {
  89 + if (checkTriggers(alert))
  90 + {
  91 + return AjaxResult.error("触发器参数必填");
  92 + }
  93 + if (checkActions(alert))
  94 + {
  95 + return AjaxResult.error("执行动作参数必填");
  96 + }
83 return toAjax(alertService.insertAlert(alert)); 97 return toAjax(alertService.insertAlert(alert));
84 } 98 }
85 99
@@ -92,6 +106,14 @@ public class IotAlertController extends BaseController @@ -92,6 +106,14 @@ public class IotAlertController extends BaseController
92 @PutMapping 106 @PutMapping
93 public AjaxResult edit(@RequestBody IotAlert alert) 107 public AjaxResult edit(@RequestBody IotAlert alert)
94 { 108 {
  109 + if (checkTriggers(alert))
  110 + {
  111 + return AjaxResult.error("触发器参数必填");
  112 + }
  113 + if (checkActions(alert))
  114 + {
  115 + return AjaxResult.error("执行动作参数必填");
  116 + }
95 return toAjax(alertService.updateAlert(alert)); 117 return toAjax(alertService.updateAlert(alert));
96 } 118 }
97 119
@@ -106,4 +128,34 @@ public class IotAlertController extends BaseController @@ -106,4 +128,34 @@ public class IotAlertController extends BaseController
106 { 128 {
107 return toAjax(alertService.deleteAlertByAlertIds(alertIds)); 129 return toAjax(alertService.deleteAlertByAlertIds(alertIds));
108 } 130 }
  131 +
  132 + /**
  133 + * 检验触发器
  134 + * @return
  135 + */
  136 + private boolean checkTriggers(IotAlert alert)
  137 + {
  138 + String triggers = Optional.ofNullable(alert).orElse(new IotAlert()).getTriggers();
  139 + if(StringUtils.isNotEmpty(triggers))
  140 + {
  141 + AlarmTriggersConfig alarmTriggersConfig = JSONObject.parseObject(triggers, AlarmTriggersConfig.class);
  142 + return BeanUtil.hasNullField(alarmTriggersConfig,"cron");
  143 + }
  144 + return false;
  145 + }
  146 +
  147 + /**
  148 + * 检验执行动作
  149 + * @return
  150 + */
  151 + private boolean checkActions(IotAlert alert)
  152 + {
  153 + String actions = Optional.ofNullable(alert).orElse(new IotAlert()).getActions();
  154 + if(StringUtils.isNotEmpty(actions))
  155 + {
  156 + AlarmActionConfig alarmActionConfig = JSONObject.parseObject(actions, AlarmActionConfig.class);
  157 + return BeanUtil.hasNullField(alarmActionConfig);
  158 + }
  159 + return false;
  160 + }
109 } 161 }
@@ -69,39 +69,4 @@ public class IotAlertLogController extends BaseController @@ -69,39 +69,4 @@ public class IotAlertLogController extends BaseController
69 return AjaxResult.success(alertLogService.selectAlertLogByAlertLogId(alertLogId)); 69 return AjaxResult.success(alertLogService.selectAlertLogByAlertLogId(alertLogId));
70 } 70 }
71 71
72 - /**  
73 - * 新增设备告警  
74 - */  
75 - @ApiOperation("新增设备告警")  
76 - @PreAuthorize("@ss.hasPermi('iot:alert:add')")  
77 - @Log(title = "设备告警", businessType = BusinessType.INSERT)  
78 - @PostMapping  
79 - public AjaxResult add(@RequestBody IotAlertLog alertLog)  
80 - {  
81 - return toAjax(alertLogService.insertAlertLog(alertLog));  
82 - }  
83 -  
84 - /**  
85 - * 修改设备告警  
86 - */  
87 - @ApiOperation("修改设备告警")  
88 - @PreAuthorize("@ss.hasPermi('iot:alert:edit')")  
89 - @Log(title = "设备告警", businessType = BusinessType.UPDATE)  
90 - @PutMapping  
91 - public AjaxResult edit(@RequestBody IotAlertLog alertLog)  
92 - {  
93 - return toAjax(alertLogService.updateAlertLog(alertLog));  
94 - }  
95 -  
96 - /**  
97 - * 删除设备告警  
98 - */  
99 - @ApiOperation("删除设备告警")  
100 - @PreAuthorize("@ss.hasPermi('iot:alert:remove')")  
101 - @Log(title = "设备告警", businessType = BusinessType.DELETE)  
102 - @DeleteMapping("/{alertLogIds}")  
103 - public AjaxResult remove(@PathVariable Long[] alertLogIds)  
104 - {  
105 - return toAjax(alertLogService.deleteAlertLogByAlertLogIds(alertLogIds));  
106 - }  
107 } 72 }
  1 +package com.zhonglai.luhui.admin.dto;
  2 +
  3 +import com.ruoyi.system.domain.IotThingsModel;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +
  7 +@ApiModel("告警执行动作配置参数")
  8 +public class AlarmActionConfig {
  9 + @ApiModelProperty("条件类型(1属性,2功能)")
  10 + private String conditionType;
  11 + @ApiModelProperty("条件模型(对应物模型表)")
  12 + private IotThingsModel iotThingsModel;
  13 + @ApiModelProperty("值")
  14 + private Object value;
  15 +
  16 + public String getConditionType() {
  17 + return conditionType;
  18 + }
  19 +
  20 + public void setConditionType(String conditionType) {
  21 + this.conditionType = conditionType;
  22 + }
  23 +
  24 + public IotThingsModel getIotThingsModel() {
  25 + return iotThingsModel;
  26 + }
  27 +
  28 + public void setIotThingsModel(IotThingsModel iotThingsModel) {
  29 + this.iotThingsModel = iotThingsModel;
  30 + }
  31 +
  32 + public Object getValue() {
  33 + return value;
  34 + }
  35 +
  36 + public void setValue(Object value) {
  37 + this.value = value;
  38 + }
  39 +}
  1 +package com.zhonglai.luhui.admin.dto;
  2 +
  3 +import com.ruoyi.system.domain.IotThingsModel;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +
  7 +@ApiModel("告警触发器配置参数")
  8 +public class AlarmTriggersConfig {
  9 + @ApiModelProperty("触发器类型(1设备触发,2定时触发)")
  10 + private Integer type;
  11 + @ApiModelProperty("条件类型(1属性,2功能,3事件,4设备上线,5设备下线)")
  12 + private String conditionType;
  13 + @ApiModelProperty("条件模型(对应物模型表)")
  14 + private IotThingsModel iotThingsModel;
  15 + @ApiModelProperty("条件逻辑符号(1等于(=),2不等于(!=),3大于(>),4小于(<),5大于等于(>=),6小于等于(<=),7包含(contain),8不包含(not contain))")
  16 + private String conditionLogic;
  17 + @ApiModelProperty("值")
  18 + private Object value;
  19 + @ApiModelProperty("定时器配置")
  20 + private String cron;
  21 +
  22 + public Integer getType() {
  23 + return type;
  24 + }
  25 +
  26 + public void setType(Integer type) {
  27 + this.type = type;
  28 + }
  29 +
  30 + public String getConditionType() {
  31 + return conditionType;
  32 + }
  33 +
  34 + public void setConditionType(String conditionType) {
  35 + this.conditionType = conditionType;
  36 + }
  37 +
  38 +
  39 + public String getConditionLogic() {
  40 + return conditionLogic;
  41 + }
  42 +
  43 + public void setConditionLogic(String conditionLogic) {
  44 + this.conditionLogic = conditionLogic;
  45 + }
  46 +
  47 + public IotThingsModel getIotThingsModel() {
  48 + return iotThingsModel;
  49 + }
  50 +
  51 + public void setIotThingsModel(IotThingsModel iotThingsModel) {
  52 + this.iotThingsModel = iotThingsModel;
  53 + }
  54 +
  55 + public Object getValue() {
  56 + return value;
  57 + }
  58 +
  59 + public void setValue(Object value) {
  60 + this.value = value;
  61 + }
  62 +
  63 + public String getCron() {
  64 + return cron;
  65 + }
  66 +
  67 + public void setCron(String cron) {
  68 + this.cron = cron;
  69 + }
  70 +}
  1 +package com.zhonglai.luhui.admin.task;
  2 +
  3 +import org.springframework.stereotype.Component;
  4 +
  5 +/**
  6 + * 告警定时器
  7 + */
  8 +@Component("alarmTask")
  9 +public class AlarmTask {
  10 +
  11 +}
  1 +package com.zhonglai.luhui.admin.task;
  2 +
  3 +import com.ruoyi.common.utils.DateUtils;
  4 +import com.ruoyi.system.domain.IotDevice;
  5 +import com.ruoyi.system.service.PublicService;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +import org.springframework.stereotype.Component;
  10 +
  11 +import java.util.ArrayList;
  12 +import java.util.List;
  13 +import java.util.Map;
  14 +import java.util.Optional;
  15 +
  16 +@Component("deviceTask")
  17 +public class DeviceTask {
  18 + protected final Logger logger = LoggerFactory.getLogger(this.getClass());
  19 +
  20 + @Autowired
  21 + private PublicService publicService;
  22 + /**
  23 + * 终端在线状态检测
  24 + */
  25 + public void terminalOnline()
  26 + {
  27 + int time = DateUtils.getNowTimeMilly()-6*60;
  28 + List<Map<String,Object>> list = publicService.getObjectListBySQL("SELECT id FROM `iot_terminal` a LEFT JOIN `iot_device` b ON a.`device_id`=b.`client_id` WHERE "+time+"-a.`data_update_time`>=b.`device_life` AND online=3");
  29 +
  30 + StringBuffer stringBuffer = new StringBuffer();
  31 + Optional.ofNullable(list).orElse(new ArrayList<>()).forEach(stringObjectMap -> {
  32 + if(stringBuffer.length() != 0)
  33 + {
  34 + stringBuffer.append(",");
  35 +
  36 + }
  37 + stringBuffer.append("'"+stringObjectMap.get("id")+"'");
  38 + });
  39 + int i = 0;
  40 + if(stringBuffer.length() != 0)
  41 + {
  42 + i = publicService.updateBySql("UPDATE `iot_terminal` SET online=4 WHERE id IN("+ stringBuffer +")");
  43 + }
  44 + logger.info("更新离线终端设备{}条",i);
  45 + }
  46 +
  47 + /**
  48 + * 网关在线状态检测
  49 + */
  50 + public void deviceOnline()
  51 + {
  52 + int time = DateUtils.getNowTimeMilly();
  53 + List<Map<String,Object>> list = publicService.getObjectListBySQL("SELECT client_id FROM `iot_device` WHERE "+time+"-data_update_time>=device_life AND status=3");
  54 +
  55 + StringBuffer stringBuffer = new StringBuffer();
  56 + Optional.ofNullable(list).orElse(new ArrayList<>()).forEach(stringObjectMap -> {
  57 + if(stringBuffer.length() != 0)
  58 + {
  59 + stringBuffer.append(",");
  60 +
  61 + }
  62 + stringBuffer.append("'"+stringObjectMap.get("client_id")+"'");
  63 + });
  64 + int i = 0;
  65 + if(stringBuffer.length() != 0)
  66 + {
  67 + i = publicService.updateBySql("UPDATE `iot_device` SET `status`=4 WHERE client_id IN("+ stringBuffer +")");
  68 + }
  69 + logger.info("更新离线网关设备{}条",i);
  70 + }
  71 +}
  1 +package com.zhonglai.luhui.admin.task;
  2 +
  3 +import cn.hutool.core.util.CharsetUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.hutool.extra.ssh.ChannelType;
  6 +import cn.hutool.extra.ssh.JschUtil;
  7 +import com.jcraft.jsch.ChannelExec;
  8 +import com.jcraft.jsch.JSchException;
  9 +import com.zhonglai.luhui.mqtt.comm.util.StringUtils;
  10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
  12 +import org.springframework.stereotype.Component;
  13 +
  14 +import java.io.*;
  15 +
  16 +/**
  17 + * 日志定时器
  18 + */
  19 +@Component("logTask")
  20 +public class LogTask {
  21 +
  22 + /**
  23 + * mq设备服务日志采集
  24 + */
  25 + public void mqDeviceServiceLogGather()
  26 + {
  27 + String cmd = "tail -f /root/hivemq-ce-2021.2/log/hivemq.log";
  28 + com.jcraft.jsch.Session session = JschUtil.createSession("175.24.61.68",22,"root","Luhui586");
  29 + try {
  30 + session.connect();
  31 + ChannelExec channel = (ChannelExec)JschUtil.createChannel(session, ChannelType.EXEC);
  32 + channel.setCommand(StrUtil.bytes(cmd, CharsetUtil.CHARSET_UTF_8));
  33 + channel.connect();
  34 + InputStream inputStream = channel.getInputStream();
  35 +
  36 + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
  37 + StringBuffer stringBuffer = new StringBuffer();
  38 + String lineOne = null;
  39 + String imei = null;
  40 + boolean islog = false;
  41 + while ((lineOne=bufferedReader.readLine())!=null)
  42 + {
  43 +
  44 + if(lineOne.indexOf("》》【")>=0)
  45 + {
  46 + islog = true;
  47 + imei = lineOne.substring(lineOne.indexOf("|<")+2,lineOne.indexOf(">|"));
  48 + }
  49 + if(islog)
  50 + {
  51 + stringBuffer.append(lineOne);
  52 + }
  53 + if(lineOne.indexOf("】《《")>=0)
  54 + {
  55 +
  56 + System.out.println(imei);
  57 + System.out.println(stringBuffer.toString());
  58 + islog=false;
  59 + imei = null;
  60 + stringBuffer = new StringBuffer();
  61 + }
  62 +
  63 + }
  64 + } catch (JSchException | IOException e) {
  65 + throw new RuntimeException(e);
  66 + }finally {
  67 + JschUtil.close(session);
  68 + }
  69 +
  70 + }
  71 +}
  1 +package com.zhonglai.luhui.admin.task;
  2 +
  3 +import cn.hutool.core.util.CharsetUtil;
  4 +import cn.hutool.core.util.ReUtil;
  5 +import cn.hutool.extra.mail.MailUtil;
  6 +import cn.hutool.extra.ssh.JschUtil;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +import java.util.regex.Pattern;
  10 +
  11 +/**
  12 + * 服务监听定时器
  13 + */
  14 +@Component("serviceListenTask")
  15 +public class ServiceListenTask {
  16 +
  17 + /**
  18 + * 检测hivemq服务是否正常运行
  19 + */
  20 + public void mqDeviceServiceRunListen()
  21 + {
  22 + String cmd = "ps -ef|grep hivemq.jar";
  23 + com.jcraft.jsch.Session session = JschUtil.createSession("175.24.61.68",22,"root","Luhui586");
  24 + try {
  25 + String cmdbarck = JschUtil.exec(session,cmd,CharsetUtil.CHARSET_UTF_8);
  26 + String[] cmdbarcks = cmdbarck.split("\n");
  27 + boolean isrun = false;
  28 + if(null != cmdbarcks && cmdbarcks.length !=0)
  29 + {
  30 + for(String cs:cmdbarcks)
  31 + {
  32 + if(ReUtil.isMatch(getRunJar("hivemq.jar"), cs))
  33 + {
  34 + isrun = true;
  35 + }
  36 + }
  37 +
  38 + }
  39 +
  40 + if(!isrun)
  41 + {
  42 + String barckStr = JschUtil.exec(session,"systemctl restart hivemq.service", CharsetUtil.CHARSET_UTF_8);
  43 + MailUtil.send("harck24@qq.com","hivemq服务器异常提醒","hivemq服务器异常,以发送重启指令,指令返回结果:"+barckStr,false);
  44 + }
  45 + } catch (Exception e) {
  46 + throw new RuntimeException(e);
  47 + }finally {
  48 + JschUtil.close(session);
  49 + }
  50 + }
  51 +
  52 + /**
  53 + * 匹配执行java程序
  54 + */
  55 + public static Pattern getRunJar(String jarServiceName)
  56 + {
  57 + return Pattern.compile(".*java.* -jar .*"+jarServiceName);
  58 + }
  59 +}
  1 +# 邮件服务器的SMTP地址,可选,默认为smtp.<发件人邮箱后缀>可以自定义
  2 +host = smtp.qq.com
  3 +# 邮件服务器的SMTP端口,可选,默认25 465
  4 +port = 587
  5 +# 发件人邮箱地址
  6 +from = 409188680@qq.com
  7 +# 用户名,默认为发件人邮箱前缀
  8 +user = 409188680
  9 +# 密码(注意,某些邮箱需要为SMTP服务单独设置授权码 比如QQ邮箱)
  10 +pass = yczuddwwztcbcabe
  11 +#使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展
  12 +starttlsEnable = true
  13 +# 需要设置为false 否则QQ邮箱测试邮件发送报错
  14 +sslEnable = false