package com.tuoheng.admin.enums; | |||||
import lombok.Getter; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 11:09 | |||||
* @Description: 机场日志告警类型 枚举 | |||||
* @Version: 1.0 | |||||
*/ | |||||
public enum AlarmTypeEnum { | |||||
/** | |||||
* 常规日志 | |||||
*/ | |||||
ALARM_LOG("log", "常规日志"), | |||||
/** | |||||
* 错误日志 | |||||
*/ | |||||
ALARM_ERROR("error", "错误日志"), | |||||
/** | |||||
* 紧急日志 | |||||
*/ | |||||
ALARM_CRITICAL("critical", "紧急日志"), | |||||
; | |||||
AlarmTypeEnum(String type,String desc) { | |||||
this.type = type; | |||||
this.desc = desc; | |||||
} | |||||
/** | |||||
* 日志类型 | |||||
*/ | |||||
@Getter | |||||
private String type; | |||||
/** | |||||
* 描述 | |||||
*/ | |||||
@Getter | |||||
private String desc; | |||||
} |
package com.tuoheng.admin.mapper; | |||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |||||
import com.tuoheng.admin.pojo.entity.Alarm; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 11:31 | |||||
* @Description: 机场告警数据 Mapper | |||||
* @Version: 1.0 | |||||
*/ | |||||
public interface AlarmMapper extends BaseMapper<Alarm> { | |||||
} |
package com.tuoheng.admin.mapper; | |||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |||||
import com.tuoheng.admin.pojo.entity.Bnconnect; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 11:12 | |||||
* @Description: 机场对接业务系统 Mapper | |||||
* @Version: 1.0 | |||||
*/ | |||||
public interface BnconnectMapper extends BaseMapper<Bnconnect> { | |||||
} |
package com.tuoheng.admin.pojo.entity; | |||||
import com.baomidou.mybatisplus.annotation.TableName; | |||||
import com.tuoheng.common.common.BaseEntity; | |||||
import lombok.Data; | |||||
import lombok.EqualsAndHashCode; | |||||
import lombok.experimental.Accessors; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 11:31 | |||||
* @Description: 机场告警数据表 | |||||
* @Version: 1.0 | |||||
*/ | |||||
@Data | |||||
@EqualsAndHashCode(callSuper = true) | |||||
@Accessors(chain = true) | |||||
@TableName("th_alarm") | |||||
public class Alarm extends BaseEntity { | |||||
private static final long serialVersionUID = 1L; | |||||
/** | |||||
* 机场ID | |||||
*/ | |||||
private Integer airportId; | |||||
/** | |||||
* 控制板ID | |||||
*/ | |||||
private String edgeId; | |||||
/** | |||||
* 接收的时间戳 | |||||
*/ | |||||
private String timestamp; | |||||
/** | |||||
* 日志类型(log: 常规日志;error: 错误日志; critical: 紧急日志) | |||||
*/ | |||||
private String type; | |||||
/** | |||||
* 消息主体 | |||||
*/ | |||||
private String data; | |||||
/** | |||||
* 告警消息主体 | |||||
*/ | |||||
private String critical; | |||||
/** | |||||
* 处理结果 1 : 已处理, 0: 未处理 | |||||
*/ | |||||
private Integer result; | |||||
public final static Integer HANDLE_AGO = 1;//已处理 | |||||
public final static Integer HANDLE_NOT = 0;//未处理 | |||||
} |
package com.tuoheng.admin.pojo.entity; | |||||
import com.baomidou.mybatisplus.annotation.TableName; | |||||
import com.tuoheng.common.common.BaseEntity; | |||||
import lombok.Data; | |||||
import lombok.EqualsAndHashCode; | |||||
import lombok.experimental.Accessors; | |||||
/** | |||||
* <p> | |||||
* 机场业务对接表 | |||||
* </p> | |||||
* | |||||
* @author 拓恒 | |||||
* @since 2022-11-03 | |||||
*/ | |||||
@Data | |||||
@EqualsAndHashCode(callSuper = true) | |||||
@Accessors(chain = true) | |||||
@TableName("th_bnconnect") | |||||
public class Bnconnect extends BaseEntity { | |||||
private static final long serialVersionUID = 1L; | |||||
/** | |||||
*代码 | |||||
*/ | |||||
private String code; | |||||
//业务系统名称 | |||||
private String name; | |||||
//业务系统api | |||||
private String apiUrl; | |||||
private String pushUrl; | |||||
private String playUrl; | |||||
} |
package com.tuoheng.admin.pojo.request; | |||||
import com.tuoheng.common.common.BaseQuery; | |||||
import lombok.Data; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 11:12 | |||||
* @Description: 机场对接业务系统 query | |||||
* @Version: 1.0 | |||||
*/ | |||||
@Data | |||||
public class BnconnectQuery extends BaseQuery { | |||||
/** | |||||
* 设备编号 | |||||
*/ | |||||
private String code; | |||||
/** | |||||
* 设备名称 | |||||
*/ | |||||
private String name; | |||||
} |
package com.tuoheng.admin.service.bnconnect; | |||||
import com.tuoheng.admin.pojo.entity.Bnconnect; | |||||
import com.tuoheng.admin.pojo.request.BnconnectQuery; | |||||
import com.tuoheng.common.common.IBaseService; | |||||
import com.tuoheng.common.utils.JsonResult; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 11:12 | |||||
* @Description: 机场对接业务系统 服务类 | |||||
* @Version: 1.0 | |||||
*/ | |||||
public interface IBnconnectService extends IBaseService<Bnconnect> { | |||||
JsonResult getList(BnconnectQuery query); | |||||
Bnconnect selectByCode(String code); | |||||
Bnconnect selectByUrl(String url); | |||||
JsonResult getListAll(); | |||||
} |
package com.tuoheng.admin.service.bnconnect.impl; | |||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||||
import com.baomidou.mybatisplus.core.metadata.IPage; | |||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |||||
import com.tuoheng.admin.mapper.BnconnectMapper; | |||||
import com.tuoheng.admin.pojo.entity.Bnconnect; | |||||
import com.tuoheng.admin.pojo.request.BnconnectQuery; | |||||
import com.tuoheng.admin.service.bnconnect.IBnconnectService; | |||||
import com.tuoheng.common.common.BaseServiceImpl; | |||||
import com.tuoheng.common.utils.JsonResult; | |||||
import com.tuoheng.common.utils.StringUtils; | |||||
import org.springframework.stereotype.Service; | |||||
import javax.annotation.Resource; | |||||
import java.util.List; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 11:12 | |||||
* @Description: 机场对接业务系统 服务实现类 | |||||
* @Version: 1.0 | |||||
*/ | |||||
@Service | |||||
public class BnconnectServiceImpl extends BaseServiceImpl<BnconnectMapper, Bnconnect> implements IBnconnectService { | |||||
@Resource | |||||
private BnconnectMapper bnconnectMapper; | |||||
@Override | |||||
public JsonResult getList(BnconnectQuery bnconnectQuery) { | |||||
QueryWrapper wrapper = new QueryWrapper(); | |||||
wrapper.eq("mark","1"); | |||||
if(StringUtils.isNotEmpty(bnconnectQuery.getCode())) { | |||||
wrapper.like("code", bnconnectQuery.getCode()); | |||||
} | |||||
if(StringUtils.isNotEmpty(bnconnectQuery.getName())) { | |||||
wrapper.like("name", bnconnectQuery.getName()); | |||||
} | |||||
IPage<Bnconnect> page = new Page<>(bnconnectQuery.getPage(), bnconnectQuery.getLimit()); | |||||
return JsonResult.success(bnconnectMapper.selectPage(page,wrapper)); | |||||
} | |||||
@Override | |||||
public Bnconnect selectByCode(String code) { | |||||
QueryWrapper wrapper = new QueryWrapper(); | |||||
wrapper.eq("mark","1"); | |||||
wrapper.eq("code",code); | |||||
List list =bnconnectMapper.selectList(wrapper); | |||||
if (list.size()>0){ | |||||
return (Bnconnect) list.get(0); | |||||
} | |||||
return null; | |||||
} | |||||
@Override | |||||
public Bnconnect selectByUrl(String url) { | |||||
QueryWrapper wrapper = new QueryWrapper(); | |||||
wrapper.eq("mark","1"); | |||||
wrapper.eq("api_url",url); | |||||
List list =bnconnectMapper.selectList(wrapper); | |||||
if (list.size()>0){ | |||||
return (Bnconnect) list.get(0); | |||||
} | |||||
return null; | |||||
} | |||||
@Override | |||||
public JsonResult getListAll() { | |||||
List<Bnconnect> list = list(); | |||||
Bnconnect bnconnect = new Bnconnect(); | |||||
bnconnect.setCode("airport"); | |||||
bnconnect.setName("机场平台"); | |||||
list.add(bnconnect); | |||||
Bnconnect bnconnect1 = new Bnconnect(); | |||||
bnconnect1.setCode("airportTimer"); | |||||
bnconnect1.setName("机场平台定时任务"); | |||||
list.add(bnconnect1); | |||||
return JsonResult.success(list); | |||||
} | |||||
} |
package com.tuoheng.admin.service.mqttService.consumer.topicHandle; | |||||
import org.eclipse.paho.client.mqttv3.MqttMessage; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 10:21 | |||||
* @Description: 机场硬件交互顶级服务接口 | |||||
* @Version: 1.0 | |||||
*/ | |||||
public interface ITopicHandleService { | |||||
/** | |||||
* topic信息,每个topic对应一个处理类 | |||||
* | |||||
* @return | |||||
*/ | |||||
String getTopic(); | |||||
/** | |||||
* 机场topic回调处理 | |||||
* @param message MQTT message | |||||
* @param edgId 设备ID | |||||
*/ | |||||
void topicHandle(MqttMessage message, String edgId); | |||||
} |
package com.tuoheng.admin.service.mqttService.consumer.topicHandle.alarm; | |||||
import cn.hutool.core.util.ObjectUtil; | |||||
import com.alibaba.fastjson.JSONObject; | |||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||||
import com.tuoheng.admin.enums.AlarmTypeEnum; | |||||
import com.tuoheng.admin.enums.MQTTTopicEnum; | |||||
import com.tuoheng.admin.enums.ServiceExceptionEnum; | |||||
import com.tuoheng.admin.mapper.AirportMapper; | |||||
import com.tuoheng.admin.mapper.AlarmMapper; | |||||
import com.tuoheng.admin.pojo.entity.Airport; | |||||
import com.tuoheng.admin.pojo.entity.Alarm; | |||||
import com.tuoheng.admin.pojo.entity.Bnconnect; | |||||
import com.tuoheng.admin.service.bnconnect.IBnconnectService; | |||||
import com.tuoheng.admin.service.mqttpush.IMqttPushService; | |||||
import com.tuoheng.admin.service.mqttService.HttpURLConnectionUtil; | |||||
import com.tuoheng.admin.service.mqttService.consumer.topicHandle.ITopicHandleService; | |||||
import com.tuoheng.admin.utils.SpringUtil; | |||||
import com.tuoheng.common.enums.MarkStatusEnum; | |||||
import com.tuoheng.common.utils.JsonResult; | |||||
import com.tuoheng.common.utils.StringUtils; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.eclipse.paho.client.mqttv3.MqttMessage; | |||||
import org.springframework.stereotype.Service; | |||||
import javax.annotation.Resource; | |||||
import java.util.ArrayList; | |||||
import java.util.HashMap; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 10:28 | |||||
* @Description: 告警记录处理 服务实现类 | |||||
* @Version: 1.0 | |||||
*/ | |||||
@Service | |||||
@Slf4j | |||||
public class AlarmTopicHandleService implements ITopicHandleService { | |||||
@Resource | |||||
private AlarmMapper alarmMapper; | |||||
/** | |||||
* DSP 告警服务URI | |||||
*/ | |||||
private final static String DSP_ALARM_URI = "/alarm/alarmData"; | |||||
/** | |||||
* 机场日志记录topic | |||||
*/ | |||||
private static final String topic = MQTTTopicEnum.TOPIC_POST_WTH.getTopic(); | |||||
@Override | |||||
public String getTopic() { | |||||
return topic; | |||||
} | |||||
/** | |||||
* 告警日志处理 | |||||
* | |||||
* @param message MQTT message | |||||
* @param edgId 设备ID | |||||
*/ | |||||
@Override | |||||
public void topicHandle(MqttMessage message, String edgId) { | |||||
/** | |||||
* 1、记录告警日志 | |||||
* 2、调用DSP接口上报告警数据 | |||||
* 3、发送MQTT消息告警已处理 | |||||
* 4、DSP调用成功更新告警记录为已处理 | |||||
*/ | |||||
JSONObject jsonObject = (JSONObject) JSONObject.parse(message.getPayload()); | |||||
if (ObjectUtil.isEmpty(jsonObject.get("type")) || ObjectUtil.isEmpty(jsonObject.get("critical"))) { | |||||
log.error("告警日志类型或紧急告警内容为空,消息无需处理!"); | |||||
return; | |||||
} | |||||
if (AlarmTypeEnum.ALARM_CRITICAL.getType().equals(jsonObject.get("type").toString())) { | |||||
//获取机场信息 | |||||
AirportMapper airportMapper = SpringUtil.getBean(AirportMapper.class); | |||||
IBnconnectService bnconnectService = SpringUtil.getBean(IBnconnectService.class); | |||||
List<Airport> airports = airportMapper.selectList(new LambdaQueryWrapper<Airport>() | |||||
.eq(Airport::getMark, MarkStatusEnum.VALID.getCode()) | |||||
.eq(Airport::getEdgeId, edgId)); | |||||
Bnconnect bnconnect = bnconnectService.selectByCode("alarmDsp"); | |||||
String critical = jsonObject.get("critical") == null ? "" : jsonObject.get("critical").toString(); | |||||
String data = jsonObject.get("critical") == null ? "" : jsonObject.get("critical").toString(); | |||||
String time = jsonObject.get("timestamp") == null ? "0" : jsonObject.get("timestamp").toString(); | |||||
IMqttPushService mqttService = SpringUtil.getBean(IMqttPushService.class); | |||||
try { | |||||
if (airports.size() > 0 && bnconnect != null) { | |||||
String airportName = airports.get(0).getName(); | |||||
//记录告警日志 | |||||
Alarm alarm = new Alarm(); | |||||
alarm.setAirportId(airports.get(0).getId()); | |||||
alarm.setEdgeId(edgId); | |||||
alarm.setCritical(critical); | |||||
alarm.setData(data); | |||||
alarm.setType(AlarmTypeEnum.ALARM_CRITICAL.getType()); | |||||
alarm.setTimestamp(time); | |||||
alarm.setResult(Alarm.HANDLE_NOT); | |||||
Integer insertResult = alarmMapper.insert(alarm); | |||||
if (insertResult <= 0) { | |||||
log.error("异常告警数据:{},记录入库异常:", time); | |||||
return; | |||||
} | |||||
log.info("异常告警数据:{},记录入库成功!", time); | |||||
//调用DSP,上报异常告警数据 | |||||
HttpURLConnectionUtil httpURLConnectionUtil = new HttpURLConnectionUtil(); | |||||
//dps请求地址 | |||||
String url = bnconnect.getApiUrl() + DSP_ALARM_URI; | |||||
//请求参数 | |||||
List parm = new ArrayList(); | |||||
Map parmMap = new HashMap(); | |||||
parmMap.put("platformCode", "001"); | |||||
Map parmMapTemplate = new HashMap(); | |||||
parmMapTemplate.put("name", airportName); | |||||
parmMapTemplate.put("msg", critical); | |||||
parmMap.put("alarmData", JSONObject.toJSONString(parmMapTemplate)); | |||||
parmMap.put("alarmTemplate", "您好,您所管辖的机场:${name},正在发生告警,告警内容是:${msg},请及时处理!"); | |||||
parm.add(parmMap); | |||||
String jsonparm = JSONObject.toJSONString(parm); | |||||
log.info("请求地址{},请求类型put,请求体{}", url, jsonparm); | |||||
String dspResponse = httpURLConnectionUtil.doPut(url, jsonparm); | |||||
log.info("请求返回值{}", dspResponse); | |||||
if (StringUtils.isEmpty(dspResponse)) { | |||||
log.error("异常告警数据上报调用DSP返回结果为空!"); | |||||
throw new RuntimeException("异常告警数据上报调用DSP返回结果为空!"); | |||||
} else { | |||||
JSONObject dspJSObject = JSONObject.parseObject(dspResponse); | |||||
if (ObjectUtil.isNotEmpty(dspJSObject) && JsonResult.SUCCESS == dspJSObject.getInteger("code")) { | |||||
//发送MQTT消息告警已处理 | |||||
mqttService.alarmSend(edgId, Alarm.HANDLE_AGO, Long.parseLong(time)); | |||||
log.info("告警数据:{},控制面板ID:{},告警处理已回复", time, edgId); | |||||
alarm.setResult(Alarm.HANDLE_AGO); | |||||
//更新告警记录已处理 | |||||
alarmMapper.updateById(alarm); | |||||
} else { | |||||
//请求返回失败 | |||||
log.error("异常告警数据:{},上报调用DSP异常,返回值:{}", time, dspJSObject); | |||||
throw new RuntimeException("异常告警数据上报调用DSP返回结果异常!"); | |||||
} | |||||
} | |||||
} else { | |||||
log.error("告警数据:{},控制板ID:{}告警,未查询到机场信息或dsp信息", time, edgId); | |||||
throw new RuntimeException("未查询到机场信息或dsp信息!"); | |||||
} | |||||
}catch (Exception e){ | |||||
log.error("告警数据:{},处理异常,通知MQTT消息未处理",time,e); | |||||
//发送MQTT消息告警未处理 | |||||
mqttService.alarmSend(edgId, Alarm.HANDLE_NOT, Long.parseLong(time)); | |||||
} | |||||
} | |||||
} | |||||
} |
package com.tuoheng.admin.service.mqttpush; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 11:22 | |||||
* @Description: MQTT 消息请求服务类 | |||||
* @Version: 1.0 | |||||
*/ | |||||
public interface IMqttPushService { | |||||
/** | |||||
* 告警成功反馈 | |||||
*/ | |||||
void alarmSend(String edgId,int command,long time); | |||||
} |
package com.tuoheng.admin.service.mqttpush.impl; | |||||
import com.alibaba.fastjson.JSONObject; | |||||
import com.tuoheng.admin.enums.AlarmTypeEnum; | |||||
import com.tuoheng.admin.service.mqttpush.IMqttPushService; | |||||
import com.tuoheng.admin.service.mqttService.send.MqttProviderConfig; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.stereotype.Service; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 11:22 | |||||
* @Description: MQTT 消息请求服务实现类 | |||||
* @Version: 1.0 | |||||
*/ | |||||
@Service | |||||
@Slf4j | |||||
public class MqttPushServiceImpl implements IMqttPushService { | |||||
@Autowired | |||||
private MqttProviderConfig client; | |||||
@Override | |||||
public void alarmSend(String edgId, int command,long time) { | |||||
JSONObject message = new JSONObject(); | |||||
message.put("DeviceID",edgId); | |||||
message.put("logID",time); | |||||
message.put("type", AlarmTypeEnum.ALARM_CRITICAL.getType()); | |||||
message.put("Result",1); | |||||
log.info("告警数据:{},控制面板ID:{},告警处理已回复",time,edgId); | |||||
client.publish(2,false,"/v1/"+edgId+"/log",message.toJSONString()); | |||||
} | |||||
} |
package com.tuoheng.common.enums; | |||||
import lombok.Getter; | |||||
/** | |||||
* @Author: 吴彬 | |||||
* @CreateTime: 2023-06-12 17:22 | |||||
* @Description: 逻辑删除状态 | |||||
* @Version: 1.0 | |||||
*/ | |||||
public enum MarkStatusEnum { | |||||
VALID(1,"有效"), | |||||
INVALID(0,"失效"); | |||||
MarkStatusEnum(int code, String description){ | |||||
this.code = code; | |||||
this.description = description; | |||||
} | |||||
@Getter | |||||
private int code; | |||||
@Getter | |||||
private String description; | |||||
} |