|
|
@@ -2,34 +2,56 @@ package com.xunmei.host.protection.service.impl;
|
|
|
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
import com.xunmei.common.core.domain.iot.domain.*;
|
|
|
+import com.xunmei.common.core.domain.mediator.domain.IotAlarmData;
|
|
|
+import com.xunmei.common.core.domain.mediator.domain.IotAlarmSystemField;
|
|
|
+import com.xunmei.common.core.enums.iot.DeviceTypeEnum;
|
|
|
import com.xunmei.common.core.util.BeanHelper;
|
|
|
import com.xunmei.common.core.utils.IDHelper;
|
|
|
import com.xunmei.common.core.utils.JacksonUtils;
|
|
|
+import com.xunmei.common.redis.utils.RedisUtils;
|
|
|
+import com.xunmei.host.alarm.mapper.IotAlarmDataMapper;
|
|
|
+import com.xunmei.host.alarm.mapper.IotAlarmSystemFieldMapper;
|
|
|
+import com.xunmei.host.enums.AlarmDataTypeEnum;
|
|
|
+import com.xunmei.host.enums.IotInputSensorTypeEnum;
|
|
|
+import com.xunmei.host.enums.IotInputStatusEnum;
|
|
|
+import com.xunmei.host.iot.mapper.IotDeviceStatusLogMapper;
|
|
|
+import com.xunmei.host.iot.mapper.IotDeviceStatusMapper;
|
|
|
import com.xunmei.host.iot.service.IIotDeviceInfoService;
|
|
|
+import com.xunmei.host.protection.mapper.IotAlarmDefenceAreaMapper;
|
|
|
import com.xunmei.host.protection.mapper.ProtectionLogMapper;
|
|
|
import com.xunmei.host.protection.service.*;
|
|
|
+import com.xunmei.host.protection.vo.AlarmHostSensorVO;
|
|
|
+import com.xunmei.host.protection.vo.IotPropertiesRes;
|
|
|
import com.xunmei.host.websocket.constant.WebSocketConstants;
|
|
|
import com.xunmei.host.websocket.dto.WebsocketExecuteReq;
|
|
|
import com.xunmei.host.websocket.dto.WebsocketResult;
|
|
|
+import com.xunmei.host.websocket.enums.DeviceCacheEnum;
|
|
|
import com.xunmei.host.websocket.enums.ProductEnums;
|
|
|
import com.xunmei.host.websocket.service.RouterService;
|
|
|
import com.xunmei.host.websocket.utils.IotServerUtils;
|
|
|
import com.xunmei.host.websocket.utils.WebSocketUtils;
|
|
|
import com.xunmei.system.api.domain.iot.IotDeviceInfo;
|
|
|
+import com.xunmei.system.api.domain.iot.IotDeviceStatus;
|
|
|
+import com.xunmei.system.api.domain.iot.IotDeviceStatusLog;
|
|
|
import com.xunmei.system.api.enums.AlarmHostSensorStatus;
|
|
|
import com.xunmei.system.api.enums.ProtectionStatus;
|
|
|
import com.xunmei.system.api.util.LogUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
import java.io.Serializable;
|
|
|
+import java.time.Duration;
|
|
|
import java.time.LocalDateTime;
|
|
|
-import java.util.List;
|
|
|
-import java.util.StringJoiner;
|
|
|
+import java.util.*;
|
|
|
|
|
|
@Service
|
|
|
public class IotAlarmHostServiceImpl implements IIotAlarmHostService, RouterService {
|
|
|
@@ -53,6 +75,17 @@ public class IotAlarmHostServiceImpl implements IIotAlarmHostService, RouterServ
|
|
|
@Resource
|
|
|
ProtectionLogMapper protectionLogMapper;
|
|
|
|
|
|
+ @Resource
|
|
|
+ private IotAlarmDefenceAreaMapper iotAlarmDefenceAreaMapper;
|
|
|
+ @Resource
|
|
|
+ private IotDeviceStatusMapper iotDeviceStatusMapper;
|
|
|
+ @Autowired
|
|
|
+ private IotDeviceStatusLogMapper iotDeviceStatusLogMapper;
|
|
|
+ @Autowired
|
|
|
+ private IotAlarmSystemFieldMapper alarmSystemFieldMapper;
|
|
|
+ @Autowired
|
|
|
+ private IotAlarmDataMapper iotAlarmDataMapper;
|
|
|
+
|
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public void changeSubSystemStatus(WebsocketExecuteReq req) {
|
|
|
@@ -302,7 +335,8 @@ public class IotAlarmHostServiceImpl implements IIotAlarmHostService, RouterServ
|
|
|
public Object execute(WebsocketExecuteReq req) {
|
|
|
try {
|
|
|
if (WebSocketConstants.SENSOR_STATUS.equals(req.getEvent())) {
|
|
|
- changeAlarmHostSensorStatus(req);
|
|
|
+ //changeAlarmHostSensorStatus(req);
|
|
|
+ changeAlarmHostInputStatus(req);
|
|
|
} else if (WebSocketConstants.SUB_SYSTEM_STATUS.equals(req.getEvent())) {
|
|
|
changeSubSystemStatus(req);
|
|
|
}
|
|
|
@@ -312,4 +346,276 @@ public class IotAlarmHostServiceImpl implements IIotAlarmHostService, RouterServ
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void changeAlarmHostInputStatus(WebsocketExecuteReq req) {
|
|
|
+ try {
|
|
|
+ LogUtils.STATUS_INFO_STATUS_SENSOR.info("【报警主机传感器状态事件】【token:{}】【msgId:{}】【接收参数:{}】", req.getServerInfo().getIotCode(), req.getId(), JSON.toJSONString(req));
|
|
|
+ if (req.getData() != null) {
|
|
|
+ String productName = req.getProductName();
|
|
|
+ String deviceName = req.getDeviceName();
|
|
|
+ AlarmHostSensorVO resParam = JSONObject.parseObject(req.getData().toString(),AlarmHostSensorVO.class);
|
|
|
+ String index = resParam.getIndex();
|
|
|
+ if(resParam == null){
|
|
|
+ LogUtils.STATUS_INFO_STATUS_SENSOR.error("报警主机传感器状态事件:产品名称={},设备名称={},设备状态为空", productName,deviceName);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(index)){
|
|
|
+ LogUtils.STATUS_INFO_STATUS_SENSOR.error("报警主机传感器状态事件:产品名称={},设备名称={},index为空", productName,deviceName);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(resParam.getStatus().equals(IotInputStatusEnum.ACTIVITY.getState())){
|
|
|
+ LogUtils.STATUS_INFO_STATUS_SENSOR.debug("报警主机传感器状态事件:产品名称={},设备名称={},index={},活动状态丢弃", productName,deviceName,index);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ this.saveInputStatus(req.getServerInfo().getIotCode(),productName, deviceName, resParam);
|
|
|
+ }catch (Exception e){
|
|
|
+ LogUtils.STATUS_INFO_STATUS_SENSOR.info("报警主机传感器状态事件: 处理出现异常{}",e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ LogUtils.STATUS_INFO_STATUS_SENSOR.error("处理报警主机传感器状态事件出错", e);
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public void saveInputStatus(String token,String productName,String deviceName,AlarmHostSensorVO vo) throws Exception {
|
|
|
+ String subsystemId = vo.getSubsystemId();
|
|
|
+ String moduleAddress = vo.getModuleAddress();
|
|
|
+ String index = vo.getIndex();
|
|
|
+ String val = vo.getStatus();
|
|
|
+
|
|
|
+
|
|
|
+ String limitOne = "limit 1";
|
|
|
+ //todo:
|
|
|
+ final IotAlarmDefenceArea input = this.selectByTypeAndCode(token, DeviceTypeEnum.ALARM_HOST_INPUT.getCode(), productName, deviceName,moduleAddress,index);
|
|
|
+ if (input == null) {
|
|
|
+ LogUtils.STATUS_INFO_STATUS_SENSOR.error("接收报警主机传感器状态事件:未查询到报警主机传感器信息,token:{},alarmHostId:{},zoneId:{},inputIndex:{}",token,deviceName,subsystemId,index);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String vipProductName = IotInputSensorTypeEnum.formatterSystemField(input.getSensorType());
|
|
|
+ Long vipDeviceCode = input.getId();
|
|
|
+
|
|
|
+ QueryWrapper<IotAlarmSystemField> fieldWrapper = new QueryWrapper<>();
|
|
|
+ fieldWrapper.eq("product_type",vipProductName);
|
|
|
+ fieldWrapper.eq("enable",1);
|
|
|
+ List<IotAlarmSystemField> fieldList = alarmSystemFieldMapper.selectList(fieldWrapper);
|
|
|
+ IotPropertiesRes resParam = new IotPropertiesRes();
|
|
|
+ resParam.setPropertyName("status");
|
|
|
+ resParam.setPropertyValue(val);
|
|
|
+
|
|
|
+ JSONArray arr = this.dealStatusData(resParam, fieldList);
|
|
|
+ if(arr == null || arr.isEmpty()){
|
|
|
+ LogUtils.STATUS_INFO_STATUS_SENSOR.debug("接收报警主机传感器状态事件: 匹配表iotAlarmSystemField属性失败,productName={},deviceName={}", vipProductName, vipDeviceCode);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Date now = new Date();
|
|
|
+ Long id= IDHelper.id();
|
|
|
+ String arrInfo = JSON.toJSONString(arr);
|
|
|
+ String displayName = input.getDefenceAreaName();
|
|
|
+ //入库状态app附表
|
|
|
+ QueryWrapper<IotDeviceStatus> wrapper = new QueryWrapper<>();
|
|
|
+ wrapper.eq("device_product", vipProductName);
|
|
|
+ wrapper.eq("device_id", vipDeviceCode);
|
|
|
+ wrapper.last(limitOne);
|
|
|
+ IotDeviceStatus status = iotDeviceStatusMapper.selectOne(wrapper);
|
|
|
+ if (status == null) {
|
|
|
+ status = new IotDeviceStatus();
|
|
|
+ status.setId(id);
|
|
|
+ status.setDeviceProduct(vipProductName);
|
|
|
+ status.setDeviceId(vipDeviceCode);
|
|
|
+ //todo:
|
|
|
+ status.setUniqueCode(token + "_" + vipDeviceCode);
|
|
|
+ //status.setUniqueCode();
|
|
|
+ status.setDeviceCode(input.getAlarmHostCode());
|
|
|
+ status.setDeviceName(displayName);
|
|
|
+ status.setInfo(arrInfo);
|
|
|
+ status.setCreateTime(now);
|
|
|
+ status.setUpdateTime(now);
|
|
|
+ status.setOrgId(input.getOrgId());
|
|
|
+ iotDeviceStatusMapper.insert(status);
|
|
|
+ } else {
|
|
|
+ status.setInfo(arrInfo);
|
|
|
+ status.setDeviceName(displayName);
|
|
|
+ status.setUpdateTime(now);
|
|
|
+ iotDeviceStatusMapper.updateById(status);
|
|
|
+ }
|
|
|
+ IotDeviceStatusLog log = new IotDeviceStatusLog();
|
|
|
+ BeanUtils.copyProperties(status,log);
|
|
|
+ log.setDeviceStatusId(id);
|
|
|
+ iotDeviceStatusLogMapper.insert(log);
|
|
|
+
|
|
|
+ boolean isAlarm = false;
|
|
|
+ if(val.equals(IotInputStatusEnum.ALARM.getState())){
|
|
|
+ isAlarm = true;
|
|
|
+ }
|
|
|
+ String infos = status.getInfo();
|
|
|
+ Map<String, String> dataMap = dealInfos(infos);
|
|
|
+ IotAlarmSystemField field = fieldList.get(0);
|
|
|
+ String sensorValue = dataMap.get(field.getName());
|
|
|
+ if (StringUtils.isBlank(sensorValue)) {
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ IotAlarmData alarmData =this.builderAlarm(sensorValue,field,status);
|
|
|
+
|
|
|
+ QueryWrapper<IotAlarmData> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.lambda().eq(IotAlarmData::getDeviceId, vipDeviceCode).isNull(IotAlarmData::getEndTime);
|
|
|
+ List<IotAlarmData> alarms = iotAlarmDataMapper.selectList(queryWrapper);
|
|
|
+ if (isAlarm && alarms.size() == 0) {
|
|
|
+ iotAlarmDataMapper.insert(alarmData);
|
|
|
+ if (ObjectUtil.notEqual(status.getState(), 1)) {
|
|
|
+ status.setState(1);
|
|
|
+ status.setStateUpdateTime(LocalDateTime.now());
|
|
|
+ status.setStateStartTime(LocalDateTime.now());
|
|
|
+ iotDeviceStatusMapper.updateById(status);
|
|
|
+ }
|
|
|
+ List<IotAlarmData> dataList = Lists.newArrayList();
|
|
|
+ dataList.add(alarmData);
|
|
|
+ }else{
|
|
|
+ // 本次上传的设备状态数据 没有生成告警
|
|
|
+ if (!isAlarm) {
|
|
|
+ //报警恢复
|
|
|
+ if (alarms.size() != 0) {
|
|
|
+ // 温湿度一个设备 存在同时2条告警的情况
|
|
|
+ if (alarms.size() > 1) {
|
|
|
+ for (IotAlarmData oldAlarm : alarms) {
|
|
|
+ oldAlarm.setEndTime(LocalDateTime.now());
|
|
|
+ iotAlarmDataMapper.updateById(oldAlarm);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ IotAlarmData iotAlarmData = alarms.get(0);
|
|
|
+ iotAlarmData.setEndTime(LocalDateTime.now());
|
|
|
+ iotAlarmDataMapper.updateById(iotAlarmData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ObjectUtil.notEqual(status.getState(), 0)) {
|
|
|
+ status.setStateUpdateTime(LocalDateTime.now());
|
|
|
+ status.setStateStartTime(LocalDateTime.now());
|
|
|
+ status.setState(0);
|
|
|
+ iotDeviceStatusMapper.updateById(status);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ //告警持续无操作
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //分析状态数据
|
|
|
+ private JSONArray dealStatusData(IotPropertiesRes datum, List<IotAlarmSystemField> fieldList) {
|
|
|
+ JSONArray array = new JSONArray();
|
|
|
+ JSONObject object = new JSONObject();
|
|
|
+ String val = datum.getPropertyValue();
|
|
|
+ if(StringUtils.isBlank(val)){
|
|
|
+ return array;
|
|
|
+ }
|
|
|
+
|
|
|
+ IotAlarmSystemField bean = null;
|
|
|
+ for(IotAlarmSystemField field:fieldList){
|
|
|
+ if(datum.getPropertyName().equals(field.getPropertyName())){
|
|
|
+ bean = field;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (bean == null) {
|
|
|
+ return array;
|
|
|
+ }
|
|
|
+
|
|
|
+ String name = bean.getName();
|
|
|
+ object.put("name", name);
|
|
|
+ object.put("val", val);
|
|
|
+
|
|
|
+ if (ObjectUtil.isNotEmpty(bean.getUnit())) {
|
|
|
+ //说明存在单位,那么把val拼接上单位set到原来的属性值中去
|
|
|
+ object.put("unit", bean.getUnit());
|
|
|
+ object.put("res", val + bean.getUnit());
|
|
|
+ } else {
|
|
|
+ object.put("unit", bean.getSpecs());
|
|
|
+ final Map extraMap = JSON.parseObject(bean.getSpecs(), Map.class);
|
|
|
+ for (Object o : extraMap.keySet()) {
|
|
|
+ if (String.valueOf(o).equals(val)) {
|
|
|
+ object.put("res", (String) extraMap.get(o));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ array.add(object);
|
|
|
+ return array;
|
|
|
+ }
|
|
|
+
|
|
|
+ //转换infos数据
|
|
|
+ private Map<String, String> dealInfos(String infos) {
|
|
|
+ JSONArray objects = JSONArray.parseArray(infos);
|
|
|
+ Map<String, String> map = new HashMap<>();
|
|
|
+ for (Object object : objects) {
|
|
|
+ JSONObject data = (JSONObject) object;
|
|
|
+ map.put(data.getString("name"), data.getString("val"));
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ //分析组装alarmData数据
|
|
|
+ private IotAlarmData builderAlarm(String sensorValue, IotAlarmSystemField field, IotDeviceStatus iotDeviceStatus) {
|
|
|
+ String deviceName = iotDeviceStatus.getDeviceName();
|
|
|
+ String productName = field.getSourceTypeDes();
|
|
|
+
|
|
|
+ IotAlarmData iotAlarmData = new IotAlarmData();
|
|
|
+ iotAlarmData.setId(IDHelper.id());
|
|
|
+ iotAlarmData.setAlarmValue(sensorValue + (field.getUnit() == null ? "" : field.getUnit()));
|
|
|
+ iotAlarmData.setTime(LocalDateTime.now());
|
|
|
+ iotAlarmData.setDeviceName(deviceName);
|
|
|
+ iotAlarmData.setRuleId(-1L);//规则id
|
|
|
+ iotAlarmData.setSourceType(field.getSourceType());
|
|
|
+ iotAlarmData.setSourceTypeDes(field.getSourceTypeDes() + "告警");
|
|
|
+ iotAlarmData.setFieldCode(field.getSysFieldCode());
|
|
|
+ iotAlarmData.setOperator(field.getOperators());//规则操作符
|
|
|
+ iotAlarmData.setValue(sensorValue);//规则值
|
|
|
+ iotAlarmData.setValueText(IotInputStatusEnum.ALARM.getName());//规则值描述
|
|
|
+ iotAlarmData.setContent(deviceName + "触发" + productName + "告警");
|
|
|
+ iotAlarmData.setOrgId(iotDeviceStatus.getOrgId());
|
|
|
+
|
|
|
+ iotAlarmData.setDataType(AlarmDataTypeEnum.HOST_ALARM.getValue());//报警主机类传感器
|
|
|
+ iotAlarmData.setSmsType(false);
|
|
|
+ //todo:
|
|
|
+ iotAlarmData.setDeviceId(String.valueOf(iotDeviceStatus.getDeviceId()));
|
|
|
+ //iotAlarmData.setDeviceId(iotDeviceStatus.getUniqueCode());
|
|
|
+
|
|
|
+ iotAlarmData.setCreateTime(new Date());
|
|
|
+ iotAlarmData.setUpdateTime(new Date());
|
|
|
+ iotAlarmData.setCreateBy("system");
|
|
|
+ iotAlarmData.setUpdateBy("system");
|
|
|
+ return iotAlarmData;
|
|
|
+ }
|
|
|
+
|
|
|
+ private IotAlarmDefenceArea selectByTypeAndCode(String token, String deviceType, String product, String deviceCode,String moduleAddress,String index) {
|
|
|
+ /**
|
|
|
+ * RedisUtils,加入缓存机制
|
|
|
+ */
|
|
|
+ String key = DeviceCacheEnum.IOT_BASE_DEVICE_INFO.getCode() + token + "_" + deviceType + "_" + product + "_" + deviceCode + "_" + moduleAddress + "_" + index;
|
|
|
+ IotAlarmDefenceArea info = RedisUtils.getCacheObject(key);
|
|
|
+ if (info == null) {
|
|
|
+ QueryWrapper<IotAlarmDefenceArea> qw = new QueryWrapper();
|
|
|
+ qw.lambda()
|
|
|
+ .eq(IotAlarmDefenceArea::getIotToken, token)
|
|
|
+ .eq(IotAlarmDefenceArea::getAlarmHostCode, deviceCode)
|
|
|
+ .eq(IotAlarmDefenceArea::getModuleAddress, moduleAddress)
|
|
|
+ .eq(IotAlarmDefenceArea::getDefenceAreaIndex, index)
|
|
|
+ .last("limit 1");
|
|
|
+ IotAlarmDefenceArea one = iotAlarmDefenceAreaMapper.selectOne(qw);
|
|
|
+ if (one != null) {
|
|
|
+ //更新缓存
|
|
|
+ RedisUtils.setCacheObject(key, info, Duration.ofMillis(1000 * 60 * 60));
|
|
|
+ return one;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return info;
|
|
|
+ }
|
|
|
+
|
|
|
}
|