fix:优化能耗管理-能源报表接口

main
HuangHuiKang 1 week ago
parent 5a27d83074
commit d8c5f86c59

@ -0,0 +1,14 @@
package cn.iocoder.yudao.framework.common.pojo;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class DeviceEdgeData {
private Long deviceId;
private LocalDateTime firstTs;
private String firstData;
private LocalDateTime lastTs;
private String lastData;
}

@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.infra.service.job.JobService; import cn.iocoder.yudao.module.infra.service.job.JobService;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
@ -37,7 +36,6 @@ import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
@Tag(name = "管理后台 - 物联设备") @Tag(name = "管理后台 - 物联设备")
@RestController @RestController

@ -22,7 +22,6 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -32,11 +31,6 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@Component @Component
@Slf4j @Slf4j

@ -9,7 +9,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import javax.validation.constraints.*;
import javax.validation.*; import javax.validation.*;
import javax.servlet.http.*; import javax.servlet.http.*;
import java.util.*; import java.util.*;

@ -1,10 +1,10 @@
package cn.iocoder.yudao.module.iot.service.device; package cn.iocoder.yudao.module.iot.service.device;
import cn.iocoder.yudao.framework.common.pojo.DeviceEdgeData;
import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.dynamic.datasource.annotation.DS;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.taosdata.jdbc.utils.BlobUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.Hex;
@ -15,11 +15,11 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.Blob;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*; import java.util.*;
@Service @Service
@ -387,4 +387,145 @@ public class TDengineService {
return Collections.singletonList(createEmptyResult(id)); return Collections.singletonList(createEmptyResult(id));
} }
} }
/**
* TDengine
*
*
* 1. TDengine d_{deviceId}
* 2.
* 3. latest
*
* @param deviceId ID
* @param startTime null
* @param endTime null
* @param latest true false
* @return timestamp / deviceId / queryData
*/
@DS("tdengine")
public Map<String, Object> getDeviceEdgeData(
Long deviceId,
String startTime,
String endTime,
boolean latest) {
// TDengine 子表名d_设备ID
String tableName = "d_" + deviceId;
// 构建 SQL
StringBuilder sql = new StringBuilder();
sql.append("SELECT ts, query_data ")
.append("FROM besure.").append(tableName)
.append(" WHERE 1=1 ");
// 起始时间条件
if (startTime != null) {
sql.append(" AND ts >= '").append(startTime).append("' ");
}
// 结束时间条件
if (endTime != null) {
sql.append(" AND ts <= '").append(endTime).append("' ");
}
// 根据 latest 决定排序方式
// latest = true -> 按时间倒序,取最新一条
// latest = false -> 按时间正序,取最早一条
sql.append(" ORDER BY ts ")
.append(latest ? "DESC" : "ASC")
.append(" LIMIT 1");
try {
return jdbcTemplate.query(sql.toString(), rs -> {
// 没有数据直接返回 null
if (!rs.next()) {
return null;
}
Map<String, Object> result = new HashMap<>();
result.put("timestamp", rs.getTimestamp("ts"));
result.put("deviceId", deviceId);
// 读取 query_data二进制字段
byte[] blob = rs.getBytes("query_data");
if (blob != null) {
// 转为字符串
String json = new String(blob, StandardCharsets.UTF_8).trim();
// 去除 TDengine 中可能存在的外层双引号
if (json.startsWith("\"") && json.endsWith("\"")) {
json = json.substring(1, json.length() - 1);
}
// 如果是十六进制字符串,先解码
if (isHexString(json)) {
json = hexToString(json);
}
// 统一约定queryData 始终返回 String由上层决定是否解析 JSON
result.put("queryData", json);
} else {
// 没有数据时返回空数组字符串
result.put("queryData", "[]");
}
return result;
});
} catch (Exception e) {
log.error("TDengine 查询失败deviceId={} td表不存在", deviceId);
return null;
}
}
/**
*
* @param deviceIds ID
* @param startTime , yyyy-MM-dd HH:mm:ss
* @param endTime , yyyy-MM-dd HH:mm:ss
* @return Map<deviceId, DeviceEdgeData>
*/
@DS("tdengine")
public Map<Long, DeviceEdgeData> queryDeviceFirstAndLast(Set<Long> deviceIds, String startTime, String endTime) {
if (deviceIds == null || deviceIds.isEmpty()) {
return Collections.emptyMap();
}
Map<Long, DeviceEdgeData> result = new HashMap<>();
for (Long deviceId : deviceIds) {
try {
// 查询首条数据
List<Map<String, Object>> firstList = getstDeviceDataOrderByTimeDesc(deviceId, startTime, endTime, 1);
Map<String, Object> firstData = firstList.isEmpty() ? null : firstList.get(0);
// 查询末条数据
List<Map<String, Object>> lastList = getstDeviceDataOrderByTimeDesc(deviceId, startTime, endTime, 1);
Map<String, Object> lastData = lastList.isEmpty() ? null : lastList.get(0);
DeviceEdgeData edgeData = new DeviceEdgeData();
edgeData.setDeviceId(deviceId);
if (firstData != null) {
edgeData.setFirstTs(((Timestamp) firstData.get("timestamp")).toLocalDateTime());
edgeData.setFirstData(JSON.toJSONString(firstData.get("queryData")));
}
if (lastData != null) {
edgeData.setLastTs(((Timestamp) lastData.get("timestamp")).toLocalDateTime());
edgeData.setLastData(JSON.toJSONString(lastData.get("queryData")));
}
result.put(deviceId, edgeData);
} catch (Exception e) {
log.error("查询设备首末数据失败, deviceId={}", deviceId, e);
}
}
return result;
}
} }

@ -1,8 +1,6 @@
package cn.iocoder.yudao.module.iot.service.devicemodelattribute; package cn.iocoder.yudao.module.iot.service.devicemodelattribute;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.module.iot.dal.dataobject.deviceattributetype.DeviceAttributeTypeDO; import cn.iocoder.yudao.module.iot.dal.dataobject.deviceattributetype.DeviceAttributeTypeDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodel.DeviceModelDO;
import cn.iocoder.yudao.module.iot.dal.mysql.deviceattributetype.DeviceAttributeTypeMapper; import cn.iocoder.yudao.module.iot.dal.mysql.deviceattributetype.DeviceAttributeTypeMapper;
import cn.iocoder.yudao.module.iot.service.device.TDengineService; import cn.iocoder.yudao.module.iot.service.device.TDengineService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@ -16,7 +14,6 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.sql.Wrapper;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -24,7 +21,6 @@ import java.util.stream.Collectors;
import cn.iocoder.yudao.module.iot.controller.admin.devicemodelattribute.vo.*; import cn.iocoder.yudao.module.iot.controller.admin.devicemodelattribute.vo.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodelattribute.DeviceModelAttributeDO; import cn.iocoder.yudao.module.iot.dal.dataobject.devicemodelattribute.DeviceModelAttributeDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.iot.dal.mysql.devicemodelattribute.DeviceModelAttributeMapper; import cn.iocoder.yudao.module.iot.dal.mysql.devicemodelattribute.DeviceModelAttributeMapper;

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.iot.service.recipedeviceattribute; package cn.iocoder.yudao.module.iot.service.recipedeviceattribute;
import cn.iocoder.yudao.module.iot.dal.dataobject.deviceattributetype.DeviceAttributeTypeDO;
import cn.iocoder.yudao.module.iot.service.device.TDengineService; import cn.iocoder.yudao.module.iot.service.device.TDengineService;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
@ -13,14 +12,11 @@ import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import cn.iocoder.yudao.module.iot.controller.admin.recipedeviceattribute.vo.*; import cn.iocoder.yudao.module.iot.controller.admin.recipedeviceattribute.vo.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.recipedeviceattribute.RecipeDeviceAttributeDO; import cn.iocoder.yudao.module.iot.dal.dataobject.recipedeviceattribute.RecipeDeviceAttributeDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.iot.dal.mysql.recipedeviceattribute.RecipeDeviceAttributeMapper; import cn.iocoder.yudao.module.iot.dal.mysql.recipedeviceattribute.RecipeDeviceAttributeMapper;

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.mes.controller.admin.energydevice.vo;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Map;
@Data
public class TimePointCache {
private LocalDateTime timestamp;
private String queryData;
private Map<Long, JSONObject> pointIndex;
}

@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.mes.controller.admin.taskmanagement.scheduled.co
import cn.iocoder.yudao.module.iot.controller.admin.device.enums.TaskTypeEnum; import cn.iocoder.yudao.module.iot.controller.admin.device.enums.TaskTypeEnum;
import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.core.Task; import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.core.Task;
import cn.iocoder.yudao.module.iot.service.device.TDengineService;
import cn.iocoder.yudao.module.mes.dal.dataobject.deviceledger.DeviceLedgerDO; import cn.iocoder.yudao.module.mes.dal.dataobject.deviceledger.DeviceLedgerDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.dvsubject.DvSubjectDO; import cn.iocoder.yudao.module.mes.dal.dataobject.dvsubject.DvSubjectDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.subjectplan.SubjectPlanDO; import cn.iocoder.yudao.module.mes.dal.dataobject.subjectplan.SubjectPlanDO;

Loading…
Cancel
Save