|
|
|
|
@ -1,16 +1,21 @@
|
|
|
|
|
package cn.iocoder.yudao.module.iot.service.device;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
|
|
import cn.iocoder.yudao.framework.common.enums.DeviceConnectionStatusEnum;
|
|
|
|
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|
|
|
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
|
|
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
|
|
|
|
import cn.iocoder.yudao.module.cus.dal.dataobject.management.ManagementDO;
|
|
|
|
|
import cn.iocoder.yudao.module.cus.dal.mysql.management.ManagementMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.device.dto.DeviceLatestRuleDTO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.device.enums.DeviceStatusEnum;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.scheduler.TaskSchedulerManager;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.utils.CronExpressionUtils;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.device.utils.DataTypeParseUtil;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.devicecontactmodel.vo.DeviceContactModelPageReqVO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.controller.admin.devicewarinningrecord.vo.DeviceWarinningRecordPageReqVO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceAttributeDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.deviceattributetype.DeviceAttributeTypeDO;
|
|
|
|
|
@ -20,7 +25,9 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodelattribute.DeviceMod
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodelrules.DeviceModelRulesDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.deviceoperationrecord.DeviceOperationRecordDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.devicepointrules.DevicePointRulesDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.devicewarinningrecord.DeviceWarinningRecordDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.gateway.GatewayDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.dataobject.orgnode.OrgNodeDO;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceAttributeMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.deviceattributetype.DeviceAttributeTypeMapper;
|
|
|
|
|
@ -31,6 +38,8 @@ import cn.iocoder.yudao.module.iot.dal.mysql.devicemodelrules.DeviceModelRulesMa
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.deviceoperationrecord.DeviceOperationRecordMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.devicepointrules.DevicePointRulesMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.gateway.GatewayMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.mysql.orgnode.OrgNodeMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceMapper;
|
|
|
|
|
import cn.iocoder.yudao.module.iot.framework.mqtt.consumer.IMqttservice;
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
@ -43,6 +52,7 @@ import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
|
|
import org.springframework.context.annotation.Lazy;
|
|
|
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
@ -85,6 +95,9 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
@Resource
|
|
|
|
|
private DeviceContactModelMapper deviceContactModelMapper;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private IotDeviceMapper iotDeviceMapper;
|
|
|
|
|
|
|
|
|
|
// @Resource
|
|
|
|
|
// private MqttDataRecordMapper mqttDataRecordMapper;
|
|
|
|
|
@Resource
|
|
|
|
|
@ -118,6 +131,12 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
@Resource
|
|
|
|
|
private GatewayMapper gatewayMapper;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
@Lazy
|
|
|
|
|
private OrgNodeMapper orgNodeMapper;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private ManagementMapper cusManagementMapper;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@ -139,6 +158,9 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
throw exception(DEVICE_CODE_ALREADY_EXISTS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (StrUtil.isNotBlank(createReqVO.getDeviceCode())) {
|
|
|
|
|
tdengineService.validateTableName(createReqVO.getDeviceCode());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeviceModelDO deviceModelDO = deviceModelMapper.selectById(createReqVO.getDeviceModelId());
|
|
|
|
|
|
|
|
|
|
@ -192,6 +214,13 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
List<DevicePointRulesDO> devicePointRulesDOList = new ArrayList<>();
|
|
|
|
|
DeviceModelDO deviceModelDO = deviceModelMapper.selectById(deviceModelId);
|
|
|
|
|
if(deviceModelDO == null){
|
|
|
|
|
DevicePointRulesDO devicePointRulesDO = new DevicePointRulesDO();
|
|
|
|
|
devicePointRulesDO.setIdentifier("RUNNING");
|
|
|
|
|
devicePointRulesDO.setFieldName("运行");
|
|
|
|
|
devicePointRulesDO.setDefaultValue("运行");
|
|
|
|
|
devicePointRulesDO.setDeviceId(deviceId);
|
|
|
|
|
devicePointRulesDOList.add(devicePointRulesDO);
|
|
|
|
|
devicePointRulesMapper.insert(devicePointRulesDO);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
List<DeviceModelRulesDO> deviceModelRulesDOList = deviceModelRulesMapper.selectList(Wrappers.<DeviceModelRulesDO>lambdaQuery()
|
|
|
|
|
@ -235,7 +264,7 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
// 校验存在
|
|
|
|
|
validateDeviceExists(id);
|
|
|
|
|
//是否有引用
|
|
|
|
|
validateReference(id);
|
|
|
|
|
// validateReference(id);
|
|
|
|
|
// // 删除
|
|
|
|
|
// deviceMapper.deleteById(id);
|
|
|
|
|
// 删除子表
|
|
|
|
|
@ -269,19 +298,49 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
@Override
|
|
|
|
|
public DeviceRespVO getDevice(Long id) {
|
|
|
|
|
DeviceDO deviceDO = deviceMapper.selectById(id);
|
|
|
|
|
if (deviceDO == null) {
|
|
|
|
|
return null; // 或者 throw exception(DEVICE_NOT_EXISTS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeviceRespVO deviceRespVO = BeanUtils.toBean(deviceDO, DeviceRespVO.class);
|
|
|
|
|
List<DevicePointRulesDO> devicePointRulesDOList = devicePointRulesMapper.selectList(Wrappers.<DevicePointRulesDO>lambdaQuery()
|
|
|
|
|
.eq(DevicePointRulesDO::getDeviceId, id));
|
|
|
|
|
//
|
|
|
|
|
// //设置点位规则
|
|
|
|
|
// if (!devicePointRulesDOList.isEmpty()){
|
|
|
|
|
//
|
|
|
|
|
// deviceRespVO.setPointRulesVOList(devicePointRulesDOList);
|
|
|
|
|
// }
|
|
|
|
|
Map<Long, LocalDateTime> latestTsMap = tdengineService.newSelectLatestTsBatch(Collections.singletonList(id));
|
|
|
|
|
|
|
|
|
|
return deviceRespVO;
|
|
|
|
|
|
|
|
|
|
List<DevicePointRulesDO> devicePointRulesDOList = devicePointRulesMapper.selectList(
|
|
|
|
|
Wrappers.<DevicePointRulesDO>lambdaQuery()
|
|
|
|
|
.eq(DevicePointRulesDO::getDeviceId, id)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 如需返回点位规则再打开
|
|
|
|
|
// if (CollUtil.isNotEmpty(devicePointRulesDOList)) {
|
|
|
|
|
// deviceRespVO.setPointRulesVOList(devicePointRulesDOList);
|
|
|
|
|
// }
|
|
|
|
|
//设置采集时间
|
|
|
|
|
if(latestTsMap.get(id) != null){
|
|
|
|
|
deviceRespVO.setCollectionTime(latestTsMap.get(id));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 补客户名称
|
|
|
|
|
if (deviceDO.getCustomerId() != null) {
|
|
|
|
|
ManagementDO customer = cusManagementMapper.selectById(deviceDO.getCustomerId());
|
|
|
|
|
if (customer != null) {
|
|
|
|
|
deviceRespVO.setCustomerName(customer.getCustomerName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 补组织名称(可能为空,表示直挂客户)
|
|
|
|
|
if (deviceDO.getOrgNodeId() != null && deviceDO.getOrgNodeId() > 0) {
|
|
|
|
|
OrgNodeDO orgNode = orgNodeMapper.selectById(deviceDO.getOrgNodeId());
|
|
|
|
|
if (orgNode != null) {
|
|
|
|
|
deviceRespVO.setOrgNodeName(orgNode.getName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return deviceRespVO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public DeviceDO getDeviceByName(String name) {
|
|
|
|
|
return deviceMapper.selectByName(name);
|
|
|
|
|
@ -1133,7 +1192,7 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public DeviceOperationStatusRespVO getDeviceOperationalStatus() {
|
|
|
|
|
public DeviceOperationStatusRespVO getDeviceOperationalStatus(LocalDateTime startTime, LocalDateTime endTime) {
|
|
|
|
|
|
|
|
|
|
DeviceOperationStatusRespVO result = new DeviceOperationStatusRespVO();
|
|
|
|
|
|
|
|
|
|
@ -1185,6 +1244,11 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
// 计算故障率
|
|
|
|
|
calculateFaultRate(result);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// PageResult<DeviceWarinningRecordDO> deviceWarinningRecordDOPageResult = tdengineService.selectRunngingRecordPage(reqVO).getList();
|
|
|
|
|
Long warnningRecordcount = iotDeviceMapper.countWarningRecordByTime(startTime, endTime);
|
|
|
|
|
|
|
|
|
|
result.setWarningRecordCount(warnningRecordcount);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1478,7 +1542,6 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
if (StringUtils.isBlank(deviceDO.getTopic())) {
|
|
|
|
|
throw exception(DEVICE_MQTT_TOPIC_EXIST);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO 待优化
|
|
|
|
|
if (!"MQTT".equals(deviceDO.getProtocol())) {
|
|
|
|
|
throw exception(DEVICE_MQTT_TOPIC_EXIST);
|
|
|
|
|
@ -1501,6 +1564,67 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
return deviceMapper.selectOne(Wrappers.<DeviceDO>lambdaQuery().eq(DeviceDO::getTopic,topic));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<DeviceRespVO> deviceList(DevicePageReqVO pageReqVO) {
|
|
|
|
|
|
|
|
|
|
// 查询设备集合
|
|
|
|
|
List<DeviceDO> deviceDOS = deviceMapper.selectList(Wrappers.<DeviceDO>lambdaQuery()
|
|
|
|
|
.eq(DeviceDO::getCustomerId, pageReqVO.getCustomerId()));
|
|
|
|
|
|
|
|
|
|
List<Long> deviceIds = deviceDOS.stream()
|
|
|
|
|
.map(DeviceDO::getId)
|
|
|
|
|
.filter(Objects::nonNull)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
// 查询规则
|
|
|
|
|
List<String> ruleCodes = Arrays.stream(DeviceStatusEnum.values())
|
|
|
|
|
.map(DeviceStatusEnum::getCode)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
List<DeviceOperationRecordDO> operationRecords =
|
|
|
|
|
tdengineService.selectLatestByDeviceAndRuleMinimal(deviceIds, ruleCodes);
|
|
|
|
|
|
|
|
|
|
// 按 deviceId 分组,取最新一条
|
|
|
|
|
Map<Long, DeviceOperationRecordDO> latestRecordMap = operationRecords.stream()
|
|
|
|
|
.collect(Collectors.toMap(
|
|
|
|
|
DeviceOperationRecordDO::getDeviceId,
|
|
|
|
|
r -> r,
|
|
|
|
|
(r1, r2) -> r1.getCreateTime().isAfter(r2.getCreateTime()) ? r1 : r2
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
List<DeviceRespVO> deviceRespVOList = BeanUtils.toBean(deviceDOS, DeviceRespVO.class);
|
|
|
|
|
|
|
|
|
|
for (DeviceRespVO deviceRespVO : deviceRespVOList) {
|
|
|
|
|
Long deviceId = deviceRespVO.getId();
|
|
|
|
|
DeviceOperationRecordDO record = latestRecordMap.get(deviceId);
|
|
|
|
|
if (record != null) {
|
|
|
|
|
DeviceStatusEnum statusEnum = DeviceStatusEnum.getByCode(record.getRule());
|
|
|
|
|
deviceRespVO.setOperatingStatus(statusEnum != null
|
|
|
|
|
? statusEnum.getName()
|
|
|
|
|
: DeviceStatusEnum.OFFLINE.getName());
|
|
|
|
|
} else {
|
|
|
|
|
deviceRespVO.setOperatingStatus(DeviceStatusEnum.OFFLINE.getName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 按 status 过滤(pageReqVO.status 传状态 code)
|
|
|
|
|
if (StrUtil.isNotBlank(pageReqVO.getStatus())) {
|
|
|
|
|
DeviceStatusEnum queryStatus = DeviceStatusEnum.getByCode(pageReqVO.getStatus());
|
|
|
|
|
if (queryStatus != null) {
|
|
|
|
|
String targetStatusName = queryStatus.getName();
|
|
|
|
|
deviceRespVOList = deviceRespVOList.stream()
|
|
|
|
|
.filter(item -> Objects.equals(item.getOperatingStatus(), targetStatusName))
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
} else {
|
|
|
|
|
// 传入非法状态时返回空
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return deviceRespVOList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void executeEnableUpdate(DeviceDO deviceDO, Boolean enabled) {
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
@ -1596,4 +1720,262 @@ public class DeviceServiceImpl implements DeviceService {
|
|
|
|
|
return deviceMapper.deviceLedgerList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public DeviceRunStatusStatsRespVO getDeviceRunStatusStats(Long customerId, Long orgNodeId) {
|
|
|
|
|
// 1) 先确定设备范围(MySQL)
|
|
|
|
|
List<Long> deviceIds;
|
|
|
|
|
|
|
|
|
|
if (orgNodeId != null) {
|
|
|
|
|
// 当前组织及子组织
|
|
|
|
|
List<OrgNodeDO> all = orgNodeMapper.selectListByCustomerByNodeId(orgNodeId);
|
|
|
|
|
if (CollUtil.isEmpty(all)) {
|
|
|
|
|
return emptyStats();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<Long, List<Long>> childrenMap = new HashMap<>();
|
|
|
|
|
for (OrgNodeDO n : all) {
|
|
|
|
|
childrenMap.computeIfAbsent(n.getParentId(), k -> new ArrayList<>()).add(n.getId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Set<Long> subtreeIds = new HashSet<>();
|
|
|
|
|
Deque<Long> queue = new ArrayDeque<>();
|
|
|
|
|
queue.add(orgNodeId);
|
|
|
|
|
while (!queue.isEmpty()) {
|
|
|
|
|
Long cur = queue.poll();
|
|
|
|
|
if (!subtreeIds.add(cur)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
List<Long> children = childrenMap.get(cur);
|
|
|
|
|
if (CollUtil.isNotEmpty(children)) {
|
|
|
|
|
queue.addAll(children);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<DeviceDO> devices = deviceMapper.selectByOrgNodeIds(new ArrayList<>(subtreeIds));
|
|
|
|
|
deviceIds = devices.stream().map(DeviceDO::getId).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
} else if (customerId != null) {
|
|
|
|
|
List<DeviceDO> devices = deviceMapper.selectByCustomerId(customerId);
|
|
|
|
|
deviceIds = devices.stream().map(DeviceDO::getId).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
deviceIds = deviceMapper.getAllDeviceIds();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (CollUtil.isEmpty(deviceIds)) {
|
|
|
|
|
return emptyStats();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2) tdengine 查每个设备最新一条 rule
|
|
|
|
|
List<DeviceLatestRuleDTO> latestRules = iotDeviceMapper.selectLatestRuleByDeviceIds(deviceIds);
|
|
|
|
|
|
|
|
|
|
// 3) 聚合统计
|
|
|
|
|
Map<Long, String> latestRuleMap = latestRules.stream()
|
|
|
|
|
.collect(Collectors.toMap(DeviceLatestRuleDTO::getDeviceId, DeviceLatestRuleDTO::getRule, (a, b) -> a));
|
|
|
|
|
|
|
|
|
|
DeviceRunStatusStatsRespVO resp = new DeviceRunStatusStatsRespVO();
|
|
|
|
|
resp.setTotalDeviceCount((long) deviceIds.size());
|
|
|
|
|
resp.setOfflineCount(0L);
|
|
|
|
|
resp.setRunningCount(0L);
|
|
|
|
|
resp.setStandbyCount(0L);
|
|
|
|
|
resp.setFaultStandbyCount(0L);
|
|
|
|
|
resp.setAlarmRunningCount(0L);
|
|
|
|
|
|
|
|
|
|
for (Long deviceId : deviceIds) {
|
|
|
|
|
String rule = latestRuleMap.get(deviceId);
|
|
|
|
|
if (rule == null) {
|
|
|
|
|
// 没有记录按离线
|
|
|
|
|
resp.setOfflineCount(resp.getOfflineCount() + 1);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeviceStatusEnum status = DeviceStatusEnum.getByCode(rule);
|
|
|
|
|
if (status == null) {
|
|
|
|
|
resp.setOfflineCount(resp.getOfflineCount() + 1);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
|
case OFFLINE:
|
|
|
|
|
resp.setOfflineCount(resp.getOfflineCount() + 1);
|
|
|
|
|
break;
|
|
|
|
|
case RUNNING:
|
|
|
|
|
resp.setRunningCount(resp.getRunningCount() + 1);
|
|
|
|
|
break;
|
|
|
|
|
case STANDBY:
|
|
|
|
|
resp.setStandbyCount(resp.getStandbyCount() + 1);
|
|
|
|
|
break;
|
|
|
|
|
case FAULT_STANDBY:
|
|
|
|
|
resp.setFaultStandbyCount(resp.getFaultStandbyCount() + 1);
|
|
|
|
|
break;
|
|
|
|
|
case ALARM_RUNNING:
|
|
|
|
|
resp.setAlarmRunningCount(resp.getAlarmRunningCount() + 1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
resp.setOfflineCount(resp.getOfflineCount() + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return resp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private DeviceRunStatusStatsRespVO emptyStats() {
|
|
|
|
|
DeviceRunStatusStatsRespVO resp = new DeviceRunStatusStatsRespVO();
|
|
|
|
|
resp.setTotalDeviceCount(0L);
|
|
|
|
|
resp.setOfflineCount(0L);
|
|
|
|
|
resp.setRunningCount(0L);
|
|
|
|
|
resp.setStandbyCount(0L);
|
|
|
|
|
resp.setFaultStandbyCount(0L);
|
|
|
|
|
resp.setAlarmRunningCount(0L);
|
|
|
|
|
return resp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public DeviceRunStatusStatsRespVO getRunStatusStatsByCustomer(Long customerId) {
|
|
|
|
|
List<DeviceDO> devices = deviceMapper.selectByCustomerId(customerId);
|
|
|
|
|
if (CollUtil.isEmpty(devices)) {
|
|
|
|
|
return emptyStats();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<Long> deviceIds = devices.stream().map(DeviceDO::getId).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
List<DeviceLatestRuleDTO> latestRules = iotDeviceMapper.selectLatestRuleByDeviceIds(deviceIds);
|
|
|
|
|
Map<Long, String> latestRuleMap = latestRules.stream()
|
|
|
|
|
.collect(Collectors.toMap(DeviceLatestRuleDTO::getDeviceId, DeviceLatestRuleDTO::getRule, (a, b) -> a));
|
|
|
|
|
|
|
|
|
|
DeviceRunStatusStatsRespVO resp = new DeviceRunStatusStatsRespVO();
|
|
|
|
|
resp.setTotalDeviceCount((long) deviceIds.size());
|
|
|
|
|
resp.setOfflineCount(0L);
|
|
|
|
|
resp.setRunningCount(0L);
|
|
|
|
|
resp.setStandbyCount(0L);
|
|
|
|
|
resp.setFaultStandbyCount(0L);
|
|
|
|
|
resp.setAlarmRunningCount(0L);
|
|
|
|
|
|
|
|
|
|
for (Long deviceId : deviceIds) {
|
|
|
|
|
String rule = latestRuleMap.get(deviceId);
|
|
|
|
|
DeviceStatusEnum status = DeviceStatusEnum.getByCode(rule);
|
|
|
|
|
if (status == null) {
|
|
|
|
|
resp.setOfflineCount(resp.getOfflineCount() + 1);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
switch (status) {
|
|
|
|
|
case OFFLINE:
|
|
|
|
|
resp.setOfflineCount(resp.getOfflineCount() + 1); break;
|
|
|
|
|
case RUNNING:
|
|
|
|
|
resp.setRunningCount(resp.getRunningCount() + 1); break;
|
|
|
|
|
case STANDBY:
|
|
|
|
|
resp.setStandbyCount(resp.getStandbyCount() + 1); break;
|
|
|
|
|
case FAULT_STANDBY:
|
|
|
|
|
resp.setFaultStandbyCount(resp.getFaultStandbyCount() + 1); break;
|
|
|
|
|
case ALARM_RUNNING:
|
|
|
|
|
resp.setAlarmRunningCount(resp.getAlarmRunningCount() + 1); break;
|
|
|
|
|
default:
|
|
|
|
|
resp.setOfflineCount(resp.getOfflineCount() + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return resp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<CustomerDeviceStatusStatsRespVO> getStatusCountByCustomer() {
|
|
|
|
|
// 1) 查所有客户
|
|
|
|
|
List<ManagementDO> customers = cusManagementMapper.selectList();
|
|
|
|
|
if (CollUtil.isEmpty(customers)) {
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<Long, String> customerNameMap = customers.stream()
|
|
|
|
|
.collect(Collectors.toMap(ManagementDO::getId, ManagementDO::getCustomerName, (a, b) -> a));
|
|
|
|
|
|
|
|
|
|
// 2) 查所有设备(含 customerId)
|
|
|
|
|
List<DeviceDO> devices = deviceMapper.selectList();
|
|
|
|
|
if (CollUtil.isEmpty(devices)) {
|
|
|
|
|
// 没设备时,每个客户返回 0
|
|
|
|
|
return customers.stream()
|
|
|
|
|
.map(this::buildEmptyCustomerStats)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<Long> deviceIds = devices.stream().map(DeviceDO::getId).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
// 3) 查 tdengine 每设备最新 rule
|
|
|
|
|
List<DeviceLatestRuleDTO> latestRules = iotDeviceMapper.selectLatestRuleByDeviceIds(deviceIds);
|
|
|
|
|
Map<Long, String> latestRuleMap = latestRules.stream()
|
|
|
|
|
.collect(Collectors.toMap(DeviceLatestRuleDTO::getDeviceId, DeviceLatestRuleDTO::getRule, (a, b) -> a));
|
|
|
|
|
|
|
|
|
|
// 4) 初始化每个客户统计对象
|
|
|
|
|
Map<Long, CustomerDeviceStatusStatsRespVO> statsMap = new LinkedHashMap<>();
|
|
|
|
|
for (ManagementDO c : customers) {
|
|
|
|
|
statsMap.put(c.getId(), buildEmptyCustomerStats(c));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5) 按设备归属客户累加
|
|
|
|
|
for (DeviceDO d : devices) {
|
|
|
|
|
Long customerId = d.getCustomerId();
|
|
|
|
|
if (customerId == null) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 防止设备 customerId 在 customers 中不存在(脏数据兜底)
|
|
|
|
|
CustomerDeviceStatusStatsRespVO stats = statsMap.computeIfAbsent(customerId, k -> {
|
|
|
|
|
ManagementDO fallback = new ManagementDO();
|
|
|
|
|
fallback.setId(k);
|
|
|
|
|
fallback.setCustomerName(customerNameMap.get(k));
|
|
|
|
|
return buildEmptyCustomerStats(fallback);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
stats.setTotalDeviceCount(stats.getTotalDeviceCount() + 1);
|
|
|
|
|
|
|
|
|
|
String rule = latestRuleMap.get(d.getId());
|
|
|
|
|
DeviceStatusEnum status = DeviceStatusEnum.getByCode(rule);
|
|
|
|
|
if (status == null) {
|
|
|
|
|
stats.setOfflineCount(stats.getOfflineCount() + 1);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
|
case OFFLINE:
|
|
|
|
|
stats.setOfflineCount(stats.getOfflineCount() + 1);
|
|
|
|
|
break;
|
|
|
|
|
case RUNNING:
|
|
|
|
|
stats.setRunningCount(stats.getRunningCount() + 1);
|
|
|
|
|
break;
|
|
|
|
|
case STANDBY:
|
|
|
|
|
stats.setStandbyCount(stats.getStandbyCount() + 1);
|
|
|
|
|
break;
|
|
|
|
|
case FAULT_STANDBY:
|
|
|
|
|
stats.setFaultStandbyCount(stats.getFaultStandbyCount() + 1);
|
|
|
|
|
break;
|
|
|
|
|
case ALARM_RUNNING:
|
|
|
|
|
stats.setAlarmRunningCount(stats.getAlarmRunningCount() + 1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
stats.setOfflineCount(stats.getOfflineCount() + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new ArrayList<>(statsMap.values());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CustomerDeviceStatusStatsRespVO buildEmptyCustomerStats(ManagementDO customer) {
|
|
|
|
|
CustomerDeviceStatusStatsRespVO vo = new CustomerDeviceStatusStatsRespVO();
|
|
|
|
|
vo.setCustomerId(customer.getId());
|
|
|
|
|
vo.setCustomerName(customer.getCustomerName());
|
|
|
|
|
|
|
|
|
|
vo.setLongitude(customer.getLongitude());
|
|
|
|
|
vo.setLatitude(customer.getLatitude());
|
|
|
|
|
|
|
|
|
|
vo.setTotalDeviceCount(0L);
|
|
|
|
|
vo.setOfflineCount(0L);
|
|
|
|
|
vo.setRunningCount(0L);
|
|
|
|
|
vo.setStandbyCount(0L);
|
|
|
|
|
vo.setFaultStandbyCount(0L);
|
|
|
|
|
vo.setAlarmRunningCount(0L);
|
|
|
|
|
return vo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|