[fix]:code review

This commit is contained in:
alwayssuper 2025-01-24 15:56:01 +08:00
parent 4f962bd1f7
commit 03d4f60e80
10 changed files with 138 additions and 13 deletions

View File

@ -19,6 +19,9 @@ public class SelectVisualDO {
*/ */
private String tableName; private String tableName;
private String deviceKey;
/** /**
* 属性 * 属性
*/ */

View File

@ -33,6 +33,10 @@ public class TdTableDO {
*/ */
private String tableName; private String tableName;
private String productKey;
private String deviceKey;
/** /**
* COLUMN 字段 * COLUMN 字段
*/ */

View File

@ -68,6 +68,15 @@ public interface IotDeviceLogDataMapper {
/** /**
* 查询设备日志表是否存在 * 查询设备日志表是否存在
* *
* @return 不存在返回null
*/ */
Object checkDeviceLogTableExists(); Object checkDeviceLogSTableExists();
/**
* 检查设备日志子表是否存在
*
* @param deviceKey 设备标识
* @return 不存在返回null
*/
Object checkDeviceLogTableExists(@Param("deviceKey") String deviceKey);
} }

View File

@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.iot.dal.tdengine;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField; import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField;
import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS; import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
@ -10,6 +13,7 @@ import org.apache.ibatis.annotations.Param;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Mapper @Mapper
@ -74,4 +78,43 @@ public interface IotDevicePropertyDataMapper {
void alterProductPropertySTableDropField(@Param("productKey") String productKey, void alterProductPropertySTableDropField(@Param("productKey") String productKey,
@Param("field") TDengineTableField field); @Param("field") TDengineTableField field);
//TODO:先参考一下老逻辑后续改进
/**
* 插入数据 - 指定列插入数据
*
* @param table 数据
* productKey 产品 key
* deviceKey 设备 key
* columns
*/
void insertDevicePropertyData(TdTableDO table);
//TODO:先参考一下老逻辑后续改进
/**
* 查看超级表 - 获取超级表的结构信息
* SQLDESCRIBE [db_name.]stb_name;
*
* @param superTable 超级表信息
* productKey 产品 key
*/
List<Map<String, Object>> describeSuperTable(TdTableDO superTable);
/**
* 获取历史数据列表
*
* @param selectVisualDO 查询条件
* @return 历史数据列表
*/
@TenantIgnore
List<Map<String, Object>> selectHistoryDataList(SelectVisualDO selectVisualDO);
/**
* 获取历史数据条数
*
* @param selectVisualDO 查询条件
* @return 数据条数
*/
@TenantIgnore
Long selectHistoryCount(SelectVisualDO selectVisualDO);
} }

View File

@ -30,8 +30,10 @@ public class DeviceConsumer {
@Async @Async
public void onMessage(ThingModelMessage message) { public void onMessage(ThingModelMessage message) {
log.info("[onMessage][消息内容({})]", message); log.info("[onMessage][消息内容({})]", message);
//TODO:数据插入这块整体写的比较混乱整体借鉴了浩浩哥之前写的逻辑目前是通过模拟设备科插入数据了但之前的逻辑有大量弃用的部分后续看看怎么完善
// 设备数据记录 // 设备数据记录
// deviceDataService.saveDeviceDataTest(message); deviceDataService.saveDeviceDataTest(message);
// 设备日志记录 // 设备日志记录
iotDeviceLogDataService.saveDeviceLog(message); iotDeviceLogDataService.saveDeviceLog(message);
} }

View File

@ -43,8 +43,8 @@ public class IotDeviceLogDataServiceImpl implements IotDeviceLogDataService{
// } // }
// throw e; // throw e;
// } // }
if(iotDeviceLogDataMapper.checkDeviceLogTableExists()==null){ if(iotDeviceLogDataMapper.checkDeviceLogSTableExists()==null){
log.info("[TDengine] 设备日志超级表不存在,开始创建 {}",iotDeviceLogDataMapper.checkDeviceLogTableExists()); log.info("[TDengine] 设备日志超级表不存在,开始创建");
iotDeviceLogDataMapper.createDeviceLogSTable(); iotDeviceLogDataMapper.createDeviceLogSTable();
}else{ }else{
log.info("[TDengine] 设备日志超级表已存在,跳过创建"); log.info("[TDengine] 设备日志超级表已存在,跳过创建");
@ -72,6 +72,10 @@ public class IotDeviceLogDataServiceImpl implements IotDeviceLogDataService{
// 讨论艿菇 这就是iotDeviceLogDataService的Impl // 讨论艿菇 这就是iotDeviceLogDataService的Impl
@Override @Override
public PageResult<IotDeviceLogDO> getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO) { public PageResult<IotDeviceLogDO> getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO) {
// 当设备日志表未创建时查询会出现报错
if(iotDeviceLogDataMapper.checkDeviceLogTableExists(pageReqVO.getDeviceKey())==null){
return null;
}
// 查询数据 // 查询数据
List<IotDeviceLogDO> list = iotDeviceLogDataMapper.selectPage(pageReqVO); List<IotDeviceLogDO> list = iotDeviceLogDataMapper.selectPage(pageReqVO);
Long total = iotDeviceLogDataMapper.selectCount(pageReqVO); Long total = iotDeviceLogDataMapper.selectCount(pageReqVO);

View File

@ -244,6 +244,7 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe
SelectVisualDO selectVisualDO = new SelectVisualDO(); SelectVisualDO selectVisualDO = new SelectVisualDO();
selectVisualDO.setDataBaseName(getDatabaseName()); selectVisualDO.setDataBaseName(getDatabaseName());
selectVisualDO.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); selectVisualDO.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()));
selectVisualDO.setDeviceKey(device.getDeviceKey());
selectVisualDO.setFieldName(deviceDataReqVO.getIdentifier()); selectVisualDO.setFieldName(deviceDataReqVO.getIdentifier());
selectVisualDO.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); selectVisualDO.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
selectVisualDO.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); selectVisualDO.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
@ -251,8 +252,8 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe
params.put("rows", deviceDataReqVO.getPageSize()); params.put("rows", deviceDataReqVO.getPageSize());
params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize());
selectVisualDO.setParams(params); selectVisualDO.setParams(params);
pageResult.setList(tdEngineDMLMapper.selectHistoryDataList(selectVisualDO)); pageResult.setList(devicePropertyDataMapper.selectHistoryDataList(selectVisualDO));
pageResult.setTotal(tdEngineDMLMapper.selectHistoryCount(selectVisualDO)); pageResult.setTotal(devicePropertyDataMapper.selectHistoryCount(selectVisualDO));
return pageResult; return pageResult;
} }

View File

@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper;
import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper;
import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper;
import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.IotConstants;
@ -61,6 +62,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
@Resource @Resource
private TdEngineDMLMapper tdEngineDMLMapper; private TdEngineDMLMapper tdEngineDMLMapper;
@Resource
private IotDevicePropertyDataMapper iotDevicePropertyDataMapper;
@Resource @Resource
private DeviceDataRedisDAO deviceDataRedisDAO; private DeviceDataRedisDAO deviceDataRedisDAO;
@ -71,7 +75,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
// 1. 判断设备状态如果为未激活状态创建数据表并更新设备状态 // 1. 判断设备状态如果为未激活状态创建数据表并更新设备状态
if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) {
// 1.1 创建设备表 // 1.1 创建设备表
createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); // createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey());
iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO()
.setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus()));
} }
@ -85,14 +89,20 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
// 3. 过滤并收集有效的属性字段缓存设备属性 // 3. 过滤并收集有效的属性字段缓存设备属性
List<TdFieldDO> schemaFieldValues = filterAndCollectValidFields(params, thingModelList, device, thingModelMessage.getTime()); List<TdFieldDO> schemaFieldValues = filterAndCollectValidFields(params, thingModelList, device, thingModelMessage.getTime());
if (schemaFieldValues.size() == 1) { // 仅有时间字段无需保存 if (schemaFieldValues.size() == 0) { // 没有字段无需保存
return; return;
} }
// 4. 构建并保存设备属性数据 // 4. 构建并保存设备属性数据
tdEngineDMLMapper.insertData(TdTableDO.builder() // tdEngineDMLMapper.insertData(TdTableDO.builder()
.dataBaseName(getDatabaseName()) // .dataBaseName(getDatabaseName())
.tableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) // .tableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()))
// .columns(schemaFieldValues)
// .build());
// TODO:复用了旧逻辑,先过渡一下
iotDevicePropertyDataMapper.insertDevicePropertyData(TdTableDO.builder()
.productKey(device.getProductKey())
.deviceKey(device.getDeviceKey())
.columns(schemaFieldValues) .columns(schemaFieldValues)
.build()); .build());
} }
@ -145,7 +155,8 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
// 3. 过滤并收集有效的属性字段 // 3. 过滤并收集有效的属性字段
List<TdFieldDO> schemaFieldValues = new ArrayList<>(); List<TdFieldDO> schemaFieldValues = new ArrayList<>();
schemaFieldValues.add(new TdFieldDO(TIME, time)); //TODO:新版本是使用ts字段
// schemaFieldValues.add(new TdFieldDO(TIME, time));
params.forEach((key, val) -> { params.forEach((key, val) -> {
if (propertyIdentifiers.contains(key)) { if (propertyIdentifiers.contains(key)) {
schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val));

View File

@ -76,8 +76,14 @@
</select> </select>
<!-- 检查设备日志超级表是否存在 --> <!-- 检查设备日志超级表是否存在 -->
<select id="checkDeviceLogTableExists" resultType="Object"> <select id="checkDeviceLogSTableExists" resultType="Object">
SHOW STABLES LIKE 'device_log' SHOW STABLES LIKE 'device_log'
</select> </select>
<!-- 检查设备日志子表是否存在 -->
<select id="checkDeviceLogTableExists" resultType="Object">
SHOW TABLES LIKE 'device_log_${deviceKey}'
</select>
</mapper> </mapper>

View File

@ -42,4 +42,46 @@
DROP COLUMN ${field.field} DROP COLUMN ${field.field}
</update> </update>
<insert id="insertDevicePropertyData">
INSERT INTO device_property_${deviceKey}
USING product_property_${productKey}
TAGS ('${deviceKey}')
(ts
<foreach item="item" collection="columns" separator=",">
,${item.fieldName}
</foreach>
)
VALUES
(NOW
<foreach item="item" collection="columns" separator=",">
,#{item.fieldValue}
</foreach>
)
</insert>
<!-- 描述超级表结构 -->
<select id="describeSuperTable" resultType="java.util.Map">
DESCRIBE product_property_${productKey}
</select>
<!-- 获取历史数据 -->
<select id="selectHistoryDataList" resultType="java.util.Map"
parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
SELECT ${fieldName} AS data, ts AS time
FROM device_property_${deviceKey}
WHERE ts BETWEEN #{startTime} AND #{endTime}
AND ${fieldName} IS NOT NULL
ORDER BY ts DESC
LIMIT #{params.rows} OFFSET #{params.page}
</select>
<!-- 统计历史数据总数 -->
<select id="selectHistoryCount" resultType="java.lang.Long"
parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
SELECT COUNT(*)
FROM device_property_${deviceKey}
WHERE ts BETWEEN #{startTime} AND #{endTime}
AND ${fieldName} IS NOT NULL
</select>
</mapper> </mapper>