|
@@ -2,18 +2,14 @@ package com.usky.cdi.service.impl;
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+import com.alibaba.nacos.shaded.com.google.gson.Gson;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
|
-import com.usky.cdi.domain.CdiDefenseProject;
|
|
|
|
|
-import com.usky.cdi.domain.CdiDeliveryLog;
|
|
|
|
|
-import com.usky.cdi.domain.DmpDevice;
|
|
|
|
|
-import com.usky.cdi.domain.DmpProduct;
|
|
|
|
|
-import com.usky.cdi.mapper.CdiDefenseProjectMapper;
|
|
|
|
|
-import com.usky.cdi.mapper.CdiDeliveryLogMapper;
|
|
|
|
|
-import com.usky.cdi.mapper.DmpDeviceMapper;
|
|
|
|
|
-import com.usky.cdi.mapper.DmpProductMapper;
|
|
|
|
|
|
|
+import com.usky.cdi.domain.*;
|
|
|
|
|
+import com.usky.cdi.mapper.*;
|
|
|
import com.usky.cdi.service.enums.MqttTopics;
|
|
import com.usky.cdi.service.enums.MqttTopics;
|
|
|
import com.usky.cdi.service.mqtt.MqttConnectionTool;
|
|
import com.usky.cdi.service.mqtt.MqttConnectionTool;
|
|
|
|
|
+import com.usky.cdi.service.util.AirDefenseSimulator;
|
|
|
import com.usky.cdi.service.util.DeviceDataQuery;
|
|
import com.usky.cdi.service.util.DeviceDataQuery;
|
|
|
import com.usky.cdi.service.util.SnowflakeIdGenerator;
|
|
import com.usky.cdi.service.util.SnowflakeIdGenerator;
|
|
|
import com.usky.cdi.service.vo.IotDataTransferVO;
|
|
import com.usky.cdi.service.vo.IotDataTransferVO;
|
|
@@ -37,6 +33,7 @@ import java.time.ZoneId;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
+import java.util.concurrent.ThreadLocalRandom;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -92,6 +89,9 @@ public class IotDataTransferService {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private CdiDeliveryLogMapper cdiDeliveryLogMapper;
|
|
private CdiDeliveryLogMapper cdiDeliveryLogMapper;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private BaseBuildUnitMapper baseBuildUnitMapper;
|
|
|
|
|
+
|
|
|
@PostConstruct
|
|
@PostConstruct
|
|
|
public void init() {
|
|
public void init() {
|
|
|
this.idGenerator = new SnowflakeIdGenerator(workerId, dataCenterId);
|
|
this.idGenerator = new SnowflakeIdGenerator(workerId, dataCenterId);
|
|
@@ -160,6 +160,9 @@ public class IotDataTransferService {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 为每条数据的监测时间添加毫秒级微差
|
|
|
|
|
+ dataEndTime = addTimeOffset(dataEndTime);
|
|
|
|
|
+
|
|
|
Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
|
Integer value = deviceDataItem.getInteger("leach_status");
|
|
Integer value = deviceDataItem.getInteger("leach_status");
|
|
|
if (value == null) {
|
|
if (value == null) {
|
|
@@ -177,6 +180,7 @@ public class IotDataTransferService {
|
|
|
vo.setDataEndTime(dataEndTime);
|
|
vo.setDataEndTime(dataEndTime);
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
|
|
+ log.info("【水浸数据】开始推送,设备:{},数据:{}", deviceId, JSON.toJSONString(vo));
|
|
|
sendMqttMessage(MqttTopics.IotInfo.WATER_LEAK.getTopic(), vo, MqttTopics.IotInfo.WATER_LEAK.getDesc(), transferVO.getUsername());
|
|
sendMqttMessage(MqttTopics.IotInfo.WATER_LEAK.getTopic(), vo, MqttTopics.IotInfo.WATER_LEAK.getDesc(), transferVO.getUsername());
|
|
|
result.put("successCount", result.get("successCount") + 1);
|
|
result.put("successCount", result.get("successCount") + 1);
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
@@ -248,6 +252,9 @@ public class IotDataTransferService {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 为每条数据的监测时间添加毫秒级微差
|
|
|
|
|
+ dataEndTime = addTimeOffset(dataEndTime);
|
|
|
|
|
+
|
|
|
// 检查业务字段是否为空,为空则计入失败(修复:原逻辑静默跳过并误计为成功)
|
|
// 检查业务字段是否为空,为空则计入失败(修复:原逻辑静默跳过并误计为成功)
|
|
|
boolean fieldMissing = false;
|
|
boolean fieldMissing = false;
|
|
|
switch (deviceType) {
|
|
switch (deviceType) {
|
|
@@ -387,6 +394,88 @@ public class IotDataTransferService {
|
|
|
return cdiDefenseProject.getTenantId();
|
|
return cdiDefenseProject.getTenantId();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 发送人员统计情况(703)-掩蔽人数
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return 推送结果,包含成功数和失败数
|
|
|
|
|
+ **/
|
|
|
|
|
+ public Map<String, Integer> sendPersonCount(IotDataTransferVO transferVO) {
|
|
|
|
|
+ Map<String, Integer> result = new HashMap<>();
|
|
|
|
|
+ result.put("successCount", 0);
|
|
|
|
|
+ result.put("failureCount", 0);
|
|
|
|
|
+
|
|
|
|
|
+ if (!validateMqttGateway(transferVO.getUsername())) {
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
|
|
+
|
|
|
|
|
+ // 模拟人员统计
|
|
|
|
|
+ log.info("开始执行【人员统计】数据推送,工程ID:{}", transferVO.getEngineeringId());
|
|
|
|
|
+ try {
|
|
|
|
|
+ LambdaQueryWrapper<BaseBuildUnit> buildUnitQuery = new LambdaQueryWrapper<>();
|
|
|
|
|
+ buildUnitQuery.eq(BaseBuildUnit::getTenantId, transferVO.getTenantId());
|
|
|
|
|
+ List<BaseBuildUnit> buildUnitList = baseBuildUnitMapper.selectList(buildUnitQuery);
|
|
|
|
|
+
|
|
|
|
|
+ // 修复3:单元为空,打印日志+标记失败,不静默返回
|
|
|
|
|
+ if (buildUnitList.isEmpty()) {
|
|
|
|
|
+ log.warn("【人员统计】未查询到建筑单元,租户ID:{},推送终止", transferVO.getTenantId());
|
|
|
|
|
+ result.put("failureCount", 1);
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.info("【人员统计】获取到建筑单元数量:{}", buildUnitList.size());
|
|
|
|
|
+ for (BaseBuildUnit buildUnit : buildUnitList) {
|
|
|
|
|
+ int peopleCount = AirDefenseSimulator.calculatePeopleCount(now);
|
|
|
|
|
+ HeadcountVO headcountVO = new HeadcountVO();
|
|
|
|
|
+ headcountVO.setDataPacketID(generateDataPacketID());
|
|
|
|
|
+ headcountVO.setEngineeringID(transferVO.getEngineeringId());
|
|
|
|
|
+ headcountVO.setSensorValue(peopleCount);
|
|
|
|
|
+ // headcountVO.setSensorID(buildUnit.getId());
|
|
|
|
|
+
|
|
|
|
|
+ // 为每条数据的监测时间添加毫秒级微差
|
|
|
|
|
+ LocalDateTime dataEndTime = addTimeOffset(now);
|
|
|
|
|
+
|
|
|
|
|
+ headcountVO.setDataEndTime(dataEndTime);
|
|
|
|
|
+ headcountVO.setPublishTime(getCurrentTime());
|
|
|
|
|
+ headcountVO.setUnitName(buildUnit.getUnitName());
|
|
|
|
|
+ headcountVO.setFloor(buildUnit.getFloor());
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ log.info("【人员统计】开始推送,单元:{},数据:{}", buildUnit.getUnitName(), JSON.toJSONString(headcountVO));
|
|
|
|
|
+ sendMqttMessage(
|
|
|
|
|
+ MqttTopics.IotInfo.PERSON.getTopic(),
|
|
|
|
|
+ headcountVO,
|
|
|
|
|
+ MqttTopics.IotInfo.PERSON.getDesc(),
|
|
|
|
|
+ transferVO.getUsername()
|
|
|
|
|
+ );
|
|
|
|
|
+ // 添加2S延时
|
|
|
|
|
+ Thread.sleep(2000);
|
|
|
|
|
+ result.put("successCount", result.get("successCount") + 1);
|
|
|
|
|
+ log.info("【人员统计】推送成功,单元:{},人数:{}", buildUnit.getUnitName(), peopleCount);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("【人员统计】数据推送失败,单元:{},异常:{}", buildUnit.getUnitName(), e.getMessage());
|
|
|
|
|
+ result.put("failureCount", result.get("failureCount") + 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 修复4:统计推送完成,打印汇总日志
|
|
|
|
|
+ log.info("【人员统计】推送完成,成功:{},失败:{}", result.get("successCount"), result.get("failureCount"));
|
|
|
|
|
+ // 可选:和闯入一样保存汇总日志(推荐加上)
|
|
|
|
|
+ long endTime = System.currentTimeMillis();
|
|
|
|
|
+ saveLog(transferVO, now, startTime, endTime, buildUnitList.size(),
|
|
|
|
|
+ result.get("successCount"), result.get("failureCount"), 0,
|
|
|
|
|
+ result.get("successCount") > 0 ? 1 : 0, SecurityUtils.getUsername());
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ // 修复5:全局异常兜底,绝不丢失
|
|
|
|
|
+ log.error("【人员统计】推送发生全局异常", e);
|
|
|
|
|
+ result.put("failureCount", result.getOrDefault("failureCount", 0) + 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 发送人员闯入情况(703)
|
|
* 发送人员闯入情况(703)
|
|
|
*
|
|
*
|
|
@@ -403,7 +492,6 @@ public class IotDataTransferService {
|
|
|
|
|
|
|
|
LocalDateTime now = LocalDateTime.now();
|
|
LocalDateTime now = LocalDateTime.now();
|
|
|
long startTime = System.currentTimeMillis();
|
|
long startTime = System.currentTimeMillis();
|
|
|
-
|
|
|
|
|
try {
|
|
try {
|
|
|
List<JSONObject> deviceData = deviceDataQuery.getDeviceData(transferVO);
|
|
List<JSONObject> deviceData = deviceDataQuery.getDeviceData(transferVO);
|
|
|
Integer deviceType = transferVO.getDeviceType();
|
|
Integer deviceType = transferVO.getDeviceType();
|
|
@@ -434,6 +522,9 @@ public class IotDataTransferService {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 处理数据时间
|
|
|
|
|
+ dataEndTime = addTimeOffset(dataEndTime);
|
|
|
|
|
+
|
|
|
Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
|
|
|
|
|
|
PersonPresenceVO vo = new PersonPresenceVO();
|
|
PersonPresenceVO vo = new PersonPresenceVO();
|
|
@@ -445,6 +536,7 @@ public class IotDataTransferService {
|
|
|
vo.setSensorValue(0); // 固定值(根据业务需求)
|
|
vo.setSensorValue(0); // 固定值(根据业务需求)
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
|
|
+ log.info("【人员闯入】开始推送,设备ID:{},数据:{}", deviceId, JSON.toJSONString(vo));
|
|
|
sendMqttMessage(
|
|
sendMqttMessage(
|
|
|
MqttTopics.IotInfo.PERSON_PRESENCE.getTopic(),
|
|
MqttTopics.IotInfo.PERSON_PRESENCE.getTopic(),
|
|
|
vo,
|
|
vo,
|
|
@@ -533,6 +625,7 @@ public class IotDataTransferService {
|
|
|
result.put("failureCount", result.get("failureCount") + 1);
|
|
result.put("failureCount", result.get("failureCount") + 1);
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
+ dataEndTime = addTimeOffset(dataEndTime);
|
|
|
|
|
|
|
|
Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
|
|
|
|
|
@@ -560,6 +653,7 @@ public class IotDataTransferService {
|
|
|
vo.setTotalPower(totalPower);
|
|
vo.setTotalPower(totalPower);
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
|
|
+ log.info("【人防用电负荷情况】开始推送,设备ID:{},数据:{}", deviceId, JSON.toJSONString(vo));
|
|
|
sendMqttMessage(
|
|
sendMqttMessage(
|
|
|
MqttTopics.IotInfo.ELECTRICITY_LOAD.getTopic(),
|
|
MqttTopics.IotInfo.ELECTRICITY_LOAD.getTopic(),
|
|
|
vo,
|
|
vo,
|
|
@@ -625,6 +719,8 @@ public class IotDataTransferService {
|
|
|
tempVO.setSensorValue(value);
|
|
tempVO.setSensorValue(value);
|
|
|
tempVO.setDataEndTime(dataEndTime);
|
|
tempVO.setDataEndTime(dataEndTime);
|
|
|
System.out.println("监测时间:" + dataEndTime);
|
|
System.out.println("监测时间:" + dataEndTime);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("【温度】开始推送,设备ID:{},数据:{}", deviceId, JSON.toJSONString(tempVO));
|
|
|
sendMqttMessage(MqttTopics.IotInfo.TEMP.getTopic(), tempVO, MqttTopics.IotInfo.TEMP.getDesc(), username);
|
|
sendMqttMessage(MqttTopics.IotInfo.TEMP.getTopic(), tempVO, MqttTopics.IotInfo.TEMP.getDesc(), username);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -650,6 +746,8 @@ public class IotDataTransferService {
|
|
|
humidityVO.setPublishTime(getCurrentTime());
|
|
humidityVO.setPublishTime(getCurrentTime());
|
|
|
humidityVO.setSensorValue(value);
|
|
humidityVO.setSensorValue(value);
|
|
|
humidityVO.setDataEndTime(dataEndTime);
|
|
humidityVO.setDataEndTime(dataEndTime);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("【湿度】开始推送,设备ID:{},数据:{}", deviceId, JSON.toJSONString(humidityVO));
|
|
|
sendMqttMessage(MqttTopics.IotInfo.HUMIDITY.getTopic(), humidityVO, MqttTopics.IotInfo.HUMIDITY.getDesc(), username);
|
|
sendMqttMessage(MqttTopics.IotInfo.HUMIDITY.getTopic(), humidityVO, MqttTopics.IotInfo.HUMIDITY.getDesc(), username);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -675,6 +773,8 @@ public class IotDataTransferService {
|
|
|
oxygenVO.setPublishTime(getCurrentTime());
|
|
oxygenVO.setPublishTime(getCurrentTime());
|
|
|
oxygenVO.setSensorValue(value);
|
|
oxygenVO.setSensorValue(value);
|
|
|
oxygenVO.setDataEndTime(dataEndTime);
|
|
oxygenVO.setDataEndTime(dataEndTime);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("【氧气浓度】开始推送,设备ID:{},数据:{}", deviceId, JSON.toJSONString(oxygenVO));
|
|
|
sendMqttMessage(MqttTopics.IotInfo.OXYGEN.getTopic(), oxygenVO, MqttTopics.IotInfo.OXYGEN.getDesc(), username);
|
|
sendMqttMessage(MqttTopics.IotInfo.OXYGEN.getTopic(), oxygenVO, MqttTopics.IotInfo.OXYGEN.getDesc(), username);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -700,6 +800,8 @@ public class IotDataTransferService {
|
|
|
coVO.setPublishTime(getCurrentTime());
|
|
coVO.setPublishTime(getCurrentTime());
|
|
|
coVO.setSensorValue(value);
|
|
coVO.setSensorValue(value);
|
|
|
coVO.setDataEndTime(dataEndTime);
|
|
coVO.setDataEndTime(dataEndTime);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("【一氧化碳浓度】开始推送,设备ID:{},数据:{}", deviceId, JSON.toJSONString(coVO));
|
|
|
sendMqttMessage(MqttTopics.IotInfo.CO.getTopic(), coVO, MqttTopics.IotInfo.CO.getDesc(), username);
|
|
sendMqttMessage(MqttTopics.IotInfo.CO.getTopic(), coVO, MqttTopics.IotInfo.CO.getDesc(), username);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -723,8 +825,14 @@ public class IotDataTransferService {
|
|
|
co2VO.setSensorID(deviceId);
|
|
co2VO.setSensorID(deviceId);
|
|
|
co2VO.setEngineeringID(engineeringID);
|
|
co2VO.setEngineeringID(engineeringID);
|
|
|
co2VO.setPublishTime(getCurrentTime());
|
|
co2VO.setPublishTime(getCurrentTime());
|
|
|
- co2VO.setSensorValue(value);
|
|
|
|
|
|
|
+ // 将value除以10000并保留三位小数
|
|
|
|
|
+ Float processedValue = new java.math.BigDecimal(value / 10000f)
|
|
|
|
|
+ .setScale(3, java.math.RoundingMode.HALF_UP)
|
|
|
|
|
+ .floatValue();
|
|
|
|
|
+ co2VO.setSensorValue(processedValue);
|
|
|
co2VO.setDataEndTime(dataEndTime);
|
|
co2VO.setDataEndTime(dataEndTime);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("【二氧化碳浓度】开始推送,设备ID:{},数据:{}", deviceId, JSON.toJSONString(co2VO));
|
|
|
sendMqttMessage(MqttTopics.IotInfo.CO2.getTopic(), co2VO, MqttTopics.IotInfo.CO2.getDesc(), username);
|
|
sendMqttMessage(MqttTopics.IotInfo.CO2.getTopic(), co2VO, MqttTopics.IotInfo.CO2.getDesc(), username);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -912,6 +1020,7 @@ public class IotDataTransferService {
|
|
|
result.put("failureCount", result.get("failureCount") + 1);
|
|
result.put("failureCount", result.get("failureCount") + 1);
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
+ dataEndTime = addTimeOffset(dataEndTime);
|
|
|
|
|
|
|
|
Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
|
Integer value = deviceDataItem.getInteger("wy");
|
|
Integer value = deviceDataItem.getInteger("wy");
|
|
@@ -930,6 +1039,7 @@ public class IotDataTransferService {
|
|
|
vo.setSensorValue(value == 0 ? 0 : 1);
|
|
vo.setSensorValue(value == 0 ? 0 : 1);
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
|
|
+ log.info("【位移数据】开始推送,设备ID:{},数据:{}", deviceId, JSON.toJSONString(vo));
|
|
|
sendMqttMessage(MqttTopics.IotInfo.DEVIATION.getTopic(), vo, MqttTopics.IotInfo.DEVIATION.getDesc(), transferVO.getUsername());
|
|
sendMqttMessage(MqttTopics.IotInfo.DEVIATION.getTopic(), vo, MqttTopics.IotInfo.DEVIATION.getDesc(), transferVO.getUsername());
|
|
|
result.put("successCount", result.get("successCount") + 1);
|
|
result.put("successCount", result.get("successCount") + 1);
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
@@ -981,7 +1091,7 @@ public class IotDataTransferService {
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
|
|
|
|
|
- log.info("开始推送集水井水位数据,设备类型:{},设备数量:{},获取到的数据条数:{}",
|
|
|
|
|
|
|
+ log.info("开始推送【集水井水位】数据,设备类型:{},设备数量:{},获取到的数据条数:{}",
|
|
|
deviceType, totalDevices, deviceData.size());
|
|
deviceType, totalDevices, deviceData.size());
|
|
|
|
|
|
|
|
if (deviceData.isEmpty()) {
|
|
if (deviceData.isEmpty()) {
|
|
@@ -997,6 +1107,7 @@ public class IotDataTransferService {
|
|
|
result.put("failureCount", result.get("failureCount") + 1);
|
|
result.put("failureCount", result.get("failureCount") + 1);
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
+ dataEndTime = addTimeOffset(dataEndTime);
|
|
|
|
|
|
|
|
Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
|
Double value = deviceDataItem.getDouble("sensorValue");
|
|
Double value = deviceDataItem.getDouble("sensorValue");
|
|
@@ -1015,6 +1126,7 @@ public class IotDataTransferService {
|
|
|
vo.setSensorValue(value);
|
|
vo.setSensorValue(value);
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
|
|
+ log.info("【水位数据】开始推送,设备ID:{},数据:{}", deviceId, JSON.toJSONString(vo));
|
|
|
sendMqttMessage(MqttTopics.IotInfo.SEWAGE_LEVEL.getTopic(), vo, MqttTopics.IotInfo.SEWAGE_LEVEL.getDesc(), transferVO.getUsername());
|
|
sendMqttMessage(MqttTopics.IotInfo.SEWAGE_LEVEL.getTopic(), vo, MqttTopics.IotInfo.SEWAGE_LEVEL.getDesc(), transferVO.getUsername());
|
|
|
result.put("successCount", result.get("successCount") + 1);
|
|
result.put("successCount", result.get("successCount") + 1);
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
@@ -1042,6 +1154,92 @@ public class IotDataTransferService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 发送发电机蓄电池监测数据(720)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return 推送结果,包含成功数和失败数
|
|
|
|
|
+ **/
|
|
|
|
|
+ public Map<String, Integer> sendGeneratorMonitoring(IotDataTransferVO transferVO) {
|
|
|
|
|
+ Map<String, Integer> result = new HashMap<>();
|
|
|
|
|
+ result.put("successCount", 0);
|
|
|
|
|
+ result.put("failureCount", 0);
|
|
|
|
|
+
|
|
|
|
|
+ if (!validateMqttGateway(transferVO.getUsername())) {
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
|
|
+ long endTime;
|
|
|
|
|
+
|
|
|
|
|
+ List<JSONObject> deviceData = deviceDataQuery.getDeviceData(transferVO);
|
|
|
|
|
+ Integer deviceType = transferVO.getDeviceType();
|
|
|
|
|
+ Integer totalDevices = transferVO.getDevices().size();
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+
|
|
|
|
|
+ log.info("开始推送【战时柴油发电机每日启动时长】数据,设备类型:{},设备数量:{},获取到的数据条数:{}",
|
|
|
|
|
+ deviceType, totalDevices, deviceData.size());
|
|
|
|
|
+
|
|
|
|
|
+ if (deviceData.isEmpty()) {
|
|
|
|
|
+ log.warn("没有获取到战时柴油发电机每日启动时长数据!设备类型:{}", deviceType);
|
|
|
|
|
+ result.put("failureCount", totalDevices);
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Long engineeringId = transferVO.getEngineeringId();
|
|
|
|
|
+ for (JSONObject deviceDataItem : deviceData) {
|
|
|
|
|
+ LocalDateTime dataEndTime = parseDataTime(deviceDataItem);
|
|
|
|
|
+ if (dataEndTime == null) {
|
|
|
|
|
+ result.put("failureCount", result.get("failureCount") + 1);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ dataEndTime = addTimeOffset(dataEndTime);
|
|
|
|
|
+
|
|
|
|
|
+ Integer deviceId = deviceDataItem.getIntValue("device_id");
|
|
|
|
|
+ Integer startDuration = deviceDataItem.get("startDuration") == null ? 0 : deviceDataItem.getIntValue("startDuration");
|
|
|
|
|
+
|
|
|
|
|
+ GeneratorMonitoringVO vo = new GeneratorMonitoringVO();
|
|
|
|
|
+ vo.setDataPacketID(generateDataPacketID());
|
|
|
|
|
+ vo.setSensorID(deviceId);
|
|
|
|
|
+ vo.setEngineeringID(engineeringId);
|
|
|
|
|
+ vo.setPublishTime(getCurrentTime());
|
|
|
|
|
+ vo.setDataEndTime(dataEndTime);
|
|
|
|
|
+ vo.setSensorDate(dataEndTime.toLocalDate());
|
|
|
|
|
+ vo.setStartDuration(startDuration);
|
|
|
|
|
+ if (deviceDataItem.containsKey("batteryVoltage")) {
|
|
|
|
|
+ vo.setBatteryVoltage(deviceDataItem.getDouble("batteryVoltage"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ log.info("【战时柴油发电机每日启动时长】开始推送,设备ID:{},数据:{}", deviceId, JSON.toJSONString(vo));
|
|
|
|
|
+ sendMqttMessage(MqttTopics.IotInfo.ALTERNATOR_STARTUP_TIME.getTopic(), vo, MqttTopics.IotInfo.ALTERNATOR_STARTUP_TIME.getDesc(), transferVO.getUsername());
|
|
|
|
|
+ result.put("successCount", result.get("successCount") + 1);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("设备{}的战时柴油发电机每日启动时长数据推送失败:{}", deviceId, e.getMessage());
|
|
|
|
|
+ result.put("failureCount", result.get("failureCount") + 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.info("战时柴油发电机每日启动时长数据推送完成,设备类型:{},成功:{},失败:{}",
|
|
|
|
|
+ deviceType, result.get("successCount"), result.get("failureCount"));
|
|
|
|
|
+
|
|
|
|
|
+ endTime = System.currentTimeMillis();
|
|
|
|
|
+ saveLog(transferVO, now, startTime, endTime, totalDevices,
|
|
|
|
|
+ result.get("successCount"), result.get("failureCount"),
|
|
|
|
|
+ totalDevices - result.get("successCount") - result.get("failureCount"), 1, SecurityUtils.getUsername());
|
|
|
|
|
+ return result;
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("战时柴油发电机每日启动时长数据推送发生异常", e);
|
|
|
|
|
+ result.put("failureCount", transferVO.getDevices().size());
|
|
|
|
|
+ endTime = System.currentTimeMillis();
|
|
|
|
|
+ saveLog(transferVO, now, startTime, endTime, totalDevices,
|
|
|
|
|
+ result.get("successCount"), result.get("failureCount"),
|
|
|
|
|
+ totalDevices - result.get("successCount") - result.get("failureCount"), 0, SecurityUtils.getUsername());
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 同步设备数据
|
|
* 同步设备数据
|
|
|
* @param tenantId 租户ID
|
|
* @param tenantId 租户ID
|
|
@@ -1083,6 +1281,7 @@ public class IotDataTransferService {
|
|
|
transferVO.setDevices(devices);
|
|
transferVO.setDevices(devices);
|
|
|
transferVO.setEngineeringId(engineeringId);
|
|
transferVO.setEngineeringId(engineeringId);
|
|
|
transferVO.setUsername(username); // 保存当前任务的用户名
|
|
transferVO.setUsername(username); // 保存当前任务的用户名
|
|
|
|
|
+ transferVO.setTenantId(tenantId);
|
|
|
transferList.add(transferVO);
|
|
transferList.add(transferVO);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -1128,8 +1327,13 @@ public class IotDataTransferService {
|
|
|
result = sendWaterLeak(transferVO);
|
|
result = sendWaterLeak(transferVO);
|
|
|
break;
|
|
break;
|
|
|
case 703:
|
|
case 703:
|
|
|
|
|
+ if (transferVO.getEngineeringId() == 3101100024L) {
|
|
|
|
|
+ result = sendPersonCount(transferVO);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
result = sendPersonPresence(transferVO);
|
|
result = sendPersonPresence(transferVO);
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case 705:
|
|
|
case 704:
|
|
case 704:
|
|
|
if (tenantId == 1205) {
|
|
if (tenantId == 1205) {
|
|
|
// 设置默认值,避免空指针
|
|
// 设置默认值,避免空指针
|
|
@@ -1151,6 +1355,12 @@ public class IotDataTransferService {
|
|
|
case 716:
|
|
case 716:
|
|
|
result = sendWaterLevel(transferVO);
|
|
result = sendWaterLevel(transferVO);
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case 719:
|
|
|
|
|
+ result = sendPersonCount(transferVO);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 720:
|
|
|
|
|
+ result = sendGeneratorMonitoring(transferVO);
|
|
|
|
|
+ break;
|
|
|
default:
|
|
default:
|
|
|
log.debug("不支持的设备类型:{}", deviceType);
|
|
log.debug("不支持的设备类型:{}", deviceType);
|
|
|
continue;
|
|
continue;
|
|
@@ -1268,7 +1478,10 @@ public class IotDataTransferService {
|
|
|
} else if (raw instanceof Number) {
|
|
} else if (raw instanceof Number) {
|
|
|
dataTime = ((Number) raw).longValue();
|
|
dataTime = ((Number) raw).longValue();
|
|
|
} else if (raw instanceof String) {
|
|
} else if (raw instanceof String) {
|
|
|
- try { dataTime = Long.parseLong((String) raw); } catch (Exception ignored) {}
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ dataTime = Long.parseLong((String) raw);
|
|
|
|
|
+ } catch (Exception ignored) {
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
if (dataTime == null) return null;
|
|
if (dataTime == null) return null;
|
|
|
return LocalDateTime.ofInstant(Instant.ofEpochMilli(dataTime), ZoneId.systemDefault());
|
|
return LocalDateTime.ofInstant(Instant.ofEpochMilli(dataTime), ZoneId.systemDefault());
|
|
@@ -1305,8 +1518,7 @@ public class IotDataTransferService {
|
|
|
* 序列化楼层平面图VO(将 floorFile byte[] 转为 Base64 字符串)
|
|
* 序列化楼层平面图VO(将 floorFile byte[] 转为 Base64 字符串)
|
|
|
*/
|
|
*/
|
|
|
private String serializeFloorPlaneVO(com.usky.cdi.service.vo.info.FloorPlaneVO vo) {
|
|
private String serializeFloorPlaneVO(com.usky.cdi.service.vo.info.FloorPlaneVO vo) {
|
|
|
- com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
|
|
|
|
|
-
|
|
|
|
|
|
|
+ Map<String, Object> jsonObject = new HashMap<>();
|
|
|
jsonObject.put("dataPacketID", vo.getDataPacketID());
|
|
jsonObject.put("dataPacketID", vo.getDataPacketID());
|
|
|
jsonObject.put("engineeringID", vo.getEngineeringID());
|
|
jsonObject.put("engineeringID", vo.getEngineeringID());
|
|
|
jsonObject.put("floor", vo.getFloor());
|
|
jsonObject.put("floor", vo.getFloor());
|
|
@@ -1316,23 +1528,50 @@ public class IotDataTransferService {
|
|
|
jsonObject.put("filePixWidth", vo.getFilePixWidth());
|
|
jsonObject.put("filePixWidth", vo.getFilePixWidth());
|
|
|
jsonObject.put("filePixHeight", vo.getFilePixHeight());
|
|
jsonObject.put("filePixHeight", vo.getFilePixHeight());
|
|
|
jsonObject.put("publishTime", vo.getPublishTime());
|
|
jsonObject.put("publishTime", vo.getPublishTime());
|
|
|
-
|
|
|
|
|
- // 关键:将 byte[] 转为 Base64 字符串
|
|
|
|
|
- if (vo.getFloorFile() != null) {
|
|
|
|
|
- String base64File = java.util.Base64.getEncoder().encodeToString(vo.getFloorFile());
|
|
|
|
|
- jsonObject.put("floorFile", base64File);
|
|
|
|
|
- log.info("平面图文件转换Base64成功,FileID: {}, 原始大小: {} bytes, Base64长度: {}",
|
|
|
|
|
- vo.getFloorFileID(), vo.getFloorFile().length, base64File.length());
|
|
|
|
|
- } else {
|
|
|
|
|
- jsonObject.put("floorFile", "");
|
|
|
|
|
- log.warn("平面图文件为空,FileID: {}", vo.getFloorFileID());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return jsonObject.toJSONString();
|
|
|
|
|
|
|
+ jsonObject.put("floorFile", vo.getFloorFile());
|
|
|
|
|
+ Gson gson = new Gson();
|
|
|
|
|
+ return gson.toJson(jsonObject);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void allData(Long engineeringId, String username, String password) {
|
|
public void allData(Long engineeringId, String username, String password) {
|
|
|
Integer tenantId = 0;
|
|
Integer tenantId = 0;
|
|
|
synchronizeDeviceData(tenantId, engineeringId, username, password);
|
|
synchronizeDeviceData(tenantId, engineeringId, username, password);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 为监测时间添加随机偏移(用于模拟真实采集场景)
|
|
|
|
|
+ * @param originalTime 原始监测时间
|
|
|
|
|
+ * @return 偏移后的时间
|
|
|
|
|
+ */
|
|
|
|
|
+ private LocalDateTime addTimeOffset(LocalDateTime originalTime) {
|
|
|
|
|
+ if (originalTime == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取当前时间作为上限
|
|
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
+
|
|
|
|
|
+ // 如果原始时间已经是未来时间,先修正为当前时间
|
|
|
|
|
+ if (originalTime.isAfter(now)) {
|
|
|
|
|
+ log.warn("检测到未来时间的监测数据,已修正为当前时间:{}", originalTime);
|
|
|
|
|
+ originalTime = now;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 随机秒偏移:0、1、2 秒(向前偏移,使用减法)
|
|
|
|
|
+ int secondsOffset = ThreadLocalRandom.current().nextInt(0, 3);
|
|
|
|
|
+ // 随机毫秒偏移:0 ~ 999 毫秒(向前偏移,使用减法)
|
|
|
|
|
+ int millisOffset = ThreadLocalRandom.current().nextInt(0, 1000);
|
|
|
|
|
+
|
|
|
|
|
+ LocalDateTime offsetTime = originalTime.minusSeconds(secondsOffset)
|
|
|
|
|
+ .minusNanos(millisOffset * 1_000_000L);
|
|
|
|
|
+
|
|
|
|
|
+ // 最终校验:确保不会晚于当前时间
|
|
|
|
|
+ if (offsetTime.isAfter(now)) {
|
|
|
|
|
+ log.warn("偏移后时间仍然晚于当前时间,已修正:原始={}, 偏移后={}, 当前={}",
|
|
|
|
|
+ originalTime, offsetTime, now);
|
|
|
|
|
+ return now;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return offsetTime;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|