Переглянути джерело

Merge remote-tracking branch 'origin/V0.1.1' into V0.1.1

jingyuanchao 1 рік тому
батько
коміт
17a6ae92b4

+ 54 - 0
soc-modules/soc-modules-host/src/main/java/com/xunmei/host/enums/IotInputSensorTypeEnum.java

@@ -0,0 +1,54 @@
+package com.xunmei.host.enums;
+
+public enum IotInputSensorTypeEnum {
+    Humidity("湿度","Humidity"),
+    Temperature("温度","Temperature"),
+    Smoke("烟感","Smoke"),
+    Infrared("红外","Infrared"),
+    Soaking("水浸","Soaking"),
+    DoorSensor("门磁","DoorSensor"),
+    Other("其他","Other"),
+    Displacement("位移","Displacement"),
+    Broken("破碎","Broken"),
+    Shock("震动","Shock"),
+    Tamper("防拆","Tamper"),
+    Intrusion("入侵","Intrusion"),
+    IMDualIdentification("红外微波双鉴","IMDualIdentification"),
+    Microwave("微波","Microwave"),
+    EmergencyButton("紧急按钮","EmergencyButton");
+
+    private String name;
+
+    private String code;
+
+    IotInputSensorTypeEnum(String name, String code) {
+        this.name = name;
+        this.code = code;
+    }
+
+    public static String formatterSystemField(String code) {
+        for (IotInputSensorTypeEnum bean : IotInputSensorTypeEnum.values()) {
+            if (bean.getCode().equals(code)) {
+                return "AlarmHostInput_" + bean.getCode();
+            }
+        }
+
+        return null;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+}

+ 39 - 0
soc-modules/soc-modules-host/src/main/java/com/xunmei/host/enums/IotInputStatusEnum.java

@@ -0,0 +1,39 @@
+package com.xunmei.host.enums;
+
+/**
+ * iot服务传感器报警状态
+ */
+public enum IotInputStatusEnum {
+
+    ALARM("报警","alarm"),
+    BYPASS("旁路","bypass"),
+    BYPASS_ALARM("旁路报警","bypassAlarm"),
+    NORMAL("正常","normal"),
+    ACTIVITY("活动","activity"),
+    UNKNOWN("未知","unknow"),
+    ;
+    private String name;
+
+    private String state;
+
+    IotInputStatusEnum(String name, String state) {
+        this.name = name;
+        this.state = state;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+}

+ 309 - 3
soc-modules/soc-modules-host/src/main/java/com/xunmei/host/protection/service/impl/IotAlarmHostServiceImpl.java

@@ -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;
+    }
+
 }

+ 14 - 0
soc-modules/soc-modules-host/src/main/java/com/xunmei/host/protection/vo/AlarmHostSensorVO.java

@@ -0,0 +1,14 @@
+package com.xunmei.host.protection.vo;
+
+import lombok.Data;
+
+@Data
+public class AlarmHostSensorVO {
+    private String index;
+    private String subsystemId;
+    private String moduleAddress;
+    private String status;
+
+    private String displayName;
+    private String sensorType;
+}

+ 9 - 0
soc-modules/soc-modules-host/src/main/java/com/xunmei/host/protection/vo/IotPropertiesRes.java

@@ -0,0 +1,9 @@
+package com.xunmei.host.protection.vo;
+
+import lombok.Data;
+
+@Data
+public class IotPropertiesRes {
+    private String propertyName;
+    private String propertyValue;
+}