diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java index 57ab7277e..52e8e1cc4 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java @@ -79,19 +79,6 @@ public class TDengineService { return getTdengineDbName() + "." + tableName; } - private String tdengineSubTableName(String stableName, Long deviceId) { - return stableName + "_" + deviceId; - } - - private void addTbnameForStableInsert(String childTableName, - StringBuilder columnBuilder, - StringBuilder valueBuilder, - List params) { - columnBuilder.append("tbname"); - valueBuilder.append("?"); - params.add(childTableName); - } - // @DS("tdengine") // public void testConnection() { // String testSQL = "SELECT SERVER_STATUS()"; @@ -285,6 +272,7 @@ public class TDengineService { String tableName = "d_" + id; StringBuilder sqlBuilder = new StringBuilder(); List params = new ArrayList<>(); + sqlBuilder.append("SELECT ts, query_data FROM ").append(tdengineTable(tableName)).append(" WHERE 1=1"); if (StartTime != null) { @@ -1416,7 +1404,7 @@ public class TDengineService { // 2. 必须以字母开头 if (!Character.isLetter(tableName.charAt(0))) { throw exception(DEVICE_MODEL_MUST_LETTER, - tableName); + tableName); } // 3. 只能包含字母、数字、下划线 @@ -1523,7 +1511,7 @@ public class TDengineService { */ @DS("tdengine") public List> newSelectBatchPage(Long deviceId, String startTime, String endTime, - Integer page, Integer pageSize) { + Integer page, Integer pageSize) { if (deviceId == null || page == null || pageSize == null) { return Collections.emptyList(); } @@ -2047,9 +2035,7 @@ public class TDengineService { } // 表名 - 使用固定表名或按设备分表 - String stableName = "iot_device_operation_record"; - String tableName = tdengineTable(stableName); - String childTableName = tdengineSubTableName(stableName, record.getDeviceId()); + String tableName = tdengineTable("iot_device_operation_record"); // 或者按设备分表: tdengineTable("operation_record_" + record.getDeviceId()); // 构建 SQL @@ -2058,12 +2044,11 @@ public class TDengineService { List params = new ArrayList<>(); // 1. 必须字段: 时间戳 (TDengine 要求) - addTbnameForStableInsert(childTableName, columnBuilder, valueBuilder, params); - columnBuilder.append(", ts"); - valueBuilder.append(", ?"); + columnBuilder.append("ts"); + valueBuilder.append("?"); // 使用当前时间作为 ts,或者使用 record 中的时间 // if (record.getCreateTime() != null) { - // 将 LocalDateTime 转换为 Timestamp + // 将 LocalDateTime 转换为 Timestamp // Timestamp tsTimestamp = Timestamp.valueOf(record.getCreateTime()); params.add(new Timestamp(System.currentTimeMillis())); // } else { @@ -2377,23 +2362,20 @@ public class TDengineService { */ @DS("tdengine") public boolean insertDeviceWarningRecord(DeviceWarinningRecordDO deviceWarningRecordDO) { - if (deviceWarningRecordDO == null || deviceWarningRecordDO.getDeviceId() == null) { + if (deviceWarningRecordDO == null) { log.warn("告警记录参数为空"); return false; } - String stableName = "iot_device_warning_record"; - String tableName = tdengineTable(stableName); - String childTableName = tdengineSubTableName(stableName, deviceWarningRecordDO.getDeviceId()); + String tableName = tdengineTable("iot_device_warning_record"); StringBuilder columnBuilder = new StringBuilder(); StringBuilder valueBuilder = new StringBuilder(); List params = new ArrayList<>(); // 1. 必须字段: 时间戳 - addTbnameForStableInsert(childTableName, columnBuilder, valueBuilder, params); - columnBuilder.append(", ts"); - valueBuilder.append(", ?"); + columnBuilder.append("ts"); + valueBuilder.append("?"); params.add(new Timestamp(System.currentTimeMillis())); // 2. 设备信息 @@ -2685,10 +2667,9 @@ public class TDengineService { return false; } try { - String stableName = "iot_device_capacity_record"; - String sql = "INSERT INTO " + tdengineTable(stableName) - + " (tbname, ts, capacity_value, device_id) VALUES (?, NOW, ?, ?)"; - jdbcTemplate.update(sql, tdengineSubTableName(stableName, deviceId), capacityValue, deviceId); + String sql = "INSERT INTO iot_device_capacity_record (ts, capacity_value, device_id) VALUES (NOW, " + + capacityValue + ", " + deviceId + ")"; + jdbcTemplate.execute(sql); return true; } catch (Exception e) { log.error("insertDeviceCapacityRecord failed, deviceId={}, capacityValue={}", deviceId, capacityValue, e); diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImpl.java index 209b799df..c8f3344fb 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/energydevice/EnergyDeviceServiceImpl.java @@ -836,11 +836,7 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService { try { LocalDateTime start = LocalDateTime.parse(reqVO.getStartTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); LocalDateTime end = LocalDateTime.parse(reqVO.getEndTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - Map> deviceRulesMap = buildDeviceRulesMap(devices); - Set sourceDeviceIds = collectRuleDeviceIds(deviceRulesMap); - Map pointInfoMap = batchGetPointInfoFromLocalDB(new ArrayList<>(collectPointIds(deviceRulesMap))); - - if (sourceDeviceIds.isEmpty()) { + if (buildDeviceRulesMap(devices).isEmpty()) { chart.setXAxis(Collections.emptyList()); chart.setData(Collections.emptyList()); return chart; @@ -848,9 +844,9 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService { boolean sameDay = start.toLocalDate().equals(end.toLocalDate()) && !start.equals(end); if (sameDay) { - return buildHourTrendChart(chart, deviceRulesMap, sourceDeviceIds, pointInfoMap, start, end); + return buildHourTrendChart(chart, devices, start, end); } - return buildDayTrendChart(chart, deviceRulesMap, sourceDeviceIds, pointInfoMap, start.toLocalDate(), end.toLocalDate()); + return buildDayTrendChart(chart, devices, start, end); } catch (Exception e) { log.warn("构建能源总览趋势数据失败, req={}", reqVO, e); chart.setXAxis(Collections.emptyList()); @@ -860,23 +856,21 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService { } private EnergyOverviewRespVO.TrendChart buildHourTrendChart(EnergyOverviewRespVO.TrendChart chart, - Map> deviceRulesMap, - Set sourceDeviceIds, - Map pointInfoMap, + List devices, LocalDateTime start, LocalDateTime end) { - DateTimeFormatter hourKeyFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH"); DateTimeFormatter displayFormatter = DateTimeFormatter.ofPattern("HH:00"); - List> allRows = tDengineService.newQueryLastDataByHourBatch(sourceDeviceIds, start, end); - Map> hourCacheMap = buildTimeCacheByHour(allRows, pointInfoMap, deviceRulesMap); - List xAxis = new ArrayList<>(); List data = new ArrayList<>(); - LocalDateTime cursor = start.withMinute(0).withSecond(0); - LocalDateTime limit = end.withMinute(0).withSecond(0); + LocalDateTime cursor = start.withMinute(0).withSecond(0).withNano(0); + LocalDateTime limit = end.withMinute(0).withSecond(0).withNano(0); while (!cursor.isAfter(limit)) { - String hourKey = cursor.format(hourKeyFormatter); - double total = sumGroupedEnergy(deviceRulesMap, hourCacheMap.getOrDefault(hourKey, Collections.emptyMap())); + LocalDateTime intervalStart = cursor.isBefore(start) ? start : cursor; + LocalDateTime intervalEnd = cursor.plusHours(1); + if (intervalEnd.isAfter(end)) { + intervalEnd = end; + } + double total = intervalStart.isAfter(intervalEnd) ? 0D : queryTrendConsumption(devices, intervalStart, intervalEnd); xAxis.add(cursor.format(displayFormatter)); data.add(formatDouble(total)); cursor = cursor.plusHours(1); @@ -887,22 +881,25 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService { } private EnergyOverviewRespVO.TrendChart buildDayTrendChart(EnergyOverviewRespVO.TrendChart chart, - Map> deviceRulesMap, - Set sourceDeviceIds, - Map pointInfoMap, - LocalDate startDate, - LocalDate endDate) { - int days = (int) (endDate.toEpochDay() - startDate.toEpochDay()) + 1; - List> allRows = tDengineService.queryLastDataByDayBatch(sourceDeviceIds, startDate, days); - Map> dayCacheMap = buildTimeCacheByDay(allRows, pointInfoMap, deviceRulesMap); - + List devices, + LocalDateTime start, + LocalDateTime end) { + LocalDate startDate = start.toLocalDate(); + LocalDate endDate = end.toLocalDate(); List xAxis = new ArrayList<>(); List data = new ArrayList<>(); LocalDate cursor = startDate; while (!cursor.isAfter(endDate)) { - String dayKey = cursor.toString(); - double total = sumGroupedEnergy(deviceRulesMap, dayCacheMap.getOrDefault(dayKey, Collections.emptyMap())); - xAxis.add(dayKey); + LocalDateTime intervalStart = cursor.atStartOfDay(); + if (intervalStart.isBefore(start)) { + intervalStart = start; + } + LocalDateTime intervalEnd = cursor.plusDays(1).atStartOfDay(); + if (intervalEnd.isAfter(end)) { + intervalEnd = end; + } + double total = intervalStart.isAfter(intervalEnd) ? 0D : queryTrendConsumption(devices, intervalStart, intervalEnd); + xAxis.add(cursor.toString()); data.add(formatDouble(total)); cursor = cursor.plusDays(1); } @@ -911,6 +908,19 @@ public class EnergyDeviceServiceImpl implements EnergyDeviceService { return chart; } + private double queryTrendConsumption(List devices, LocalDateTime start, LocalDateTime end) { + if (devices == null || devices.isEmpty()) { + return 0D; + } + EnergyDeviceConsumptionReqVO req = new EnergyDeviceConsumptionReqVO(); + req.setIds(devices.stream().map(item -> String.valueOf(item.getId())).collect(Collectors.joining(","))); + req.setStartTime(start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + req.setEndTime(end.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + return queryDataRecords(req).stream() + .mapToDouble(item -> parseEnergyValue(item.getEnergyConsumption())) + .sum(); + } + private Map> buildTimeCacheByHour(List> allRows, Map pointInfoMap, Map> deviceRulesMap) {