Commit 03d4f60e8027b2e6125e2db4077d87c72ba72ccf
1 parent
4f962bd1
[fix]:code review
Showing
10 changed files
with
138 additions
and
13 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceLogDataMapper.java
| ... | ... | @@ -68,6 +68,15 @@ public interface IotDeviceLogDataMapper { |
| 68 | 68 | /** |
| 69 | 69 | * 查询设备日志表是否存在 |
| 70 | 70 | * |
| 71 | + * @return 不存在返回null | |
| 71 | 72 | */ |
| 72 | - Object checkDeviceLogTableExists(); | |
| 73 | + Object checkDeviceLogSTableExists(); | |
| 74 | + | |
| 75 | + /** | |
| 76 | + * 检查设备日志子表是否存在 | |
| 77 | + * | |
| 78 | + * @param deviceKey 设备标识 | |
| 79 | + * @return 不存在返回null | |
| 80 | + */ | |
| 81 | + Object checkDeviceLogTableExists(@Param("deviceKey") String deviceKey); | |
| 73 | 82 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDevicePropertyDataMapper.java
| ... | ... | @@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.util.ObjectUtil; |
| 5 | +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | |
| 6 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; | |
| 7 | +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; | |
| 5 | 8 | import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField; |
| 6 | 9 | import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS; |
| 7 | 10 | import com.baomidou.mybatisplus.annotation.InterceptorIgnore; |
| ... | ... | @@ -10,6 +13,7 @@ import org.apache.ibatis.annotations.Param; |
| 10 | 13 | |
| 11 | 14 | import java.util.ArrayList; |
| 12 | 15 | import java.util.List; |
| 16 | +import java.util.Map; | |
| 13 | 17 | import java.util.stream.Collectors; |
| 14 | 18 | |
| 15 | 19 | @Mapper |
| ... | ... | @@ -74,4 +78,43 @@ public interface IotDevicePropertyDataMapper { |
| 74 | 78 | void alterProductPropertySTableDropField(@Param("productKey") String productKey, |
| 75 | 79 | @Param("field") TDengineTableField field); |
| 76 | 80 | |
| 81 | + //TODO:先参考一下老逻辑,后续改进 | |
| 82 | + /** | |
| 83 | + * 插入数据 - 指定列插入数据 | |
| 84 | + * | |
| 85 | + * @param table 数据 | |
| 86 | + * productKey 产品 key | |
| 87 | + * deviceKey 设备 key | |
| 88 | + * columns 列 | |
| 89 | + */ | |
| 90 | + void insertDevicePropertyData(TdTableDO table); | |
| 91 | + | |
| 92 | + //TODO:先参考一下老逻辑,后续改进 | |
| 93 | + /** | |
| 94 | + * 查看超级表 - 获取超级表的结构信息 | |
| 95 | + * SQL:DESCRIBE [db_name.]stb_name; | |
| 96 | + * | |
| 97 | + * @param superTable 超级表信息 | |
| 98 | + * productKey 产品 key | |
| 99 | + */ | |
| 100 | + List<Map<String, Object>> describeSuperTable(TdTableDO superTable); | |
| 101 | + | |
| 102 | + /** | |
| 103 | + * 获取历史数据列表 | |
| 104 | + * | |
| 105 | + * @param selectVisualDO 查询条件 | |
| 106 | + * @return 历史数据列表 | |
| 107 | + */ | |
| 108 | + @TenantIgnore | |
| 109 | + List<Map<String, Object>> selectHistoryDataList(SelectVisualDO selectVisualDO); | |
| 110 | + | |
| 111 | + /** | |
| 112 | + * 获取历史数据条数 | |
| 113 | + * | |
| 114 | + * @param selectVisualDO 查询条件 | |
| 115 | + * @return 数据条数 | |
| 116 | + */ | |
| 117 | + @TenantIgnore | |
| 118 | + Long selectHistoryCount(SelectVisualDO selectVisualDO); | |
| 119 | + | |
| 77 | 120 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/deviceconsumer/DeviceConsumer.java
| ... | ... | @@ -30,8 +30,10 @@ public class DeviceConsumer { |
| 30 | 30 | @Async |
| 31 | 31 | public void onMessage(ThingModelMessage message) { |
| 32 | 32 | log.info("[onMessage][消息内容({})]", message); |
| 33 | + //TODO:数据插入这块整体写的比较混乱,整体借鉴了浩浩哥之前写的逻辑,目前是通过模拟设备科插入数据了,但之前的逻辑有大量弃用的部分,后续看看怎么完善 | |
| 34 | + | |
| 33 | 35 | // 设备数据记录 |
| 34 | -// deviceDataService.saveDeviceDataTest(message); | |
| 36 | + deviceDataService.saveDeviceDataTest(message); | |
| 35 | 37 | // 设备日志记录 |
| 36 | 38 | iotDeviceLogDataService.saveDeviceLog(message); |
| 37 | 39 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceLogDataServiceImpl.java
| ... | ... | @@ -43,8 +43,8 @@ public class IotDeviceLogDataServiceImpl implements IotDeviceLogDataService{ |
| 43 | 43 | // } |
| 44 | 44 | // throw e; |
| 45 | 45 | // } |
| 46 | - if(iotDeviceLogDataMapper.checkDeviceLogTableExists()==null){ | |
| 47 | - log.info("[TDengine] 设备日志超级表不存在,开始创建 {}",iotDeviceLogDataMapper.checkDeviceLogTableExists()); | |
| 46 | + if(iotDeviceLogDataMapper.checkDeviceLogSTableExists()==null){ | |
| 47 | + log.info("[TDengine] 设备日志超级表不存在,开始创建"); | |
| 48 | 48 | iotDeviceLogDataMapper.createDeviceLogSTable(); |
| 49 | 49 | }else{ |
| 50 | 50 | log.info("[TDengine] 设备日志超级表已存在,跳过创建"); |
| ... | ... | @@ -72,6 +72,10 @@ public class IotDeviceLogDataServiceImpl implements IotDeviceLogDataService{ |
| 72 | 72 | // 讨论:艿菇 这就是iotDeviceLogDataService的Impl |
| 73 | 73 | @Override |
| 74 | 74 | public PageResult<IotDeviceLogDO> getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO) { |
| 75 | + // 当设备日志表未创建时,查询会出现报错 | |
| 76 | + if(iotDeviceLogDataMapper.checkDeviceLogTableExists(pageReqVO.getDeviceKey())==null){ | |
| 77 | + return null; | |
| 78 | + } | |
| 75 | 79 | // 查询数据 |
| 76 | 80 | List<IotDeviceLogDO> list = iotDeviceLogDataMapper.selectPage(pageReqVO); |
| 77 | 81 | Long total = iotDeviceLogDataMapper.selectCount(pageReqVO); | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataServiceImpl.java
| ... | ... | @@ -244,6 +244,7 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe |
| 244 | 244 | SelectVisualDO selectVisualDO = new SelectVisualDO(); |
| 245 | 245 | selectVisualDO.setDataBaseName(getDatabaseName()); |
| 246 | 246 | selectVisualDO.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); |
| 247 | + selectVisualDO.setDeviceKey(device.getDeviceKey()); | |
| 247 | 248 | selectVisualDO.setFieldName(deviceDataReqVO.getIdentifier()); |
| 248 | 249 | selectVisualDO.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); |
| 249 | 250 | selectVisualDO.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); |
| ... | ... | @@ -251,8 +252,8 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe |
| 251 | 252 | params.put("rows", deviceDataReqVO.getPageSize()); |
| 252 | 253 | params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); |
| 253 | 254 | selectVisualDO.setParams(params); |
| 254 | - pageResult.setList(tdEngineDMLMapper.selectHistoryDataList(selectVisualDO)); | |
| 255 | - pageResult.setTotal(tdEngineDMLMapper.selectHistoryCount(selectVisualDO)); | |
| 255 | + pageResult.setList(devicePropertyDataMapper.selectHistoryDataList(selectVisualDO)); | |
| 256 | + pageResult.setTotal(devicePropertyDataMapper.selectHistoryCount(selectVisualDO)); | |
| 256 | 257 | return pageResult; |
| 257 | 258 | } |
| 258 | 259 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java
| ... | ... | @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; |
| 13 | 13 | import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; |
| 14 | 14 | import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; |
| 15 | 15 | import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; |
| 16 | +import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper; | |
| 16 | 17 | import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; |
| 17 | 18 | import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; |
| 18 | 19 | import cn.iocoder.yudao.module.iot.enums.IotConstants; |
| ... | ... | @@ -62,6 +63,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ |
| 62 | 63 | private TdEngineDMLMapper tdEngineDMLMapper; |
| 63 | 64 | |
| 64 | 65 | @Resource |
| 66 | + private IotDevicePropertyDataMapper iotDevicePropertyDataMapper; | |
| 67 | + | |
| 68 | + @Resource | |
| 65 | 69 | private DeviceDataRedisDAO deviceDataRedisDAO; |
| 66 | 70 | |
| 67 | 71 | // TODO @haohao:这个方法,可以考虑加下 1. 2. 3. 更有层次感 |
| ... | ... | @@ -71,7 +75,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ |
| 71 | 75 | // 1. 判断设备状态,如果为未激活状态,创建数据表并更新设备状态 |
| 72 | 76 | if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { |
| 73 | 77 | // 1.1 创建设备表 |
| 74 | - createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); | |
| 78 | +// createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); | |
| 75 | 79 | iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() |
| 76 | 80 | .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); |
| 77 | 81 | } |
| ... | ... | @@ -85,14 +89,20 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ |
| 85 | 89 | |
| 86 | 90 | // 3. 过滤并收集有效的属性字段,缓存设备属性 |
| 87 | 91 | List<TdFieldDO> schemaFieldValues = filterAndCollectValidFields(params, thingModelList, device, thingModelMessage.getTime()); |
| 88 | - if (schemaFieldValues.size() == 1) { // 仅有时间字段,无需保存 | |
| 92 | + if (schemaFieldValues.size() == 0) { // 没有字段,无需保存 | |
| 89 | 93 | return; |
| 90 | 94 | } |
| 91 | 95 | |
| 92 | 96 | // 4. 构建并保存设备属性数据 |
| 93 | - tdEngineDMLMapper.insertData(TdTableDO.builder() | |
| 94 | - .dataBaseName(getDatabaseName()) | |
| 95 | - .tableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) | |
| 97 | +// tdEngineDMLMapper.insertData(TdTableDO.builder() | |
| 98 | +// .dataBaseName(getDatabaseName()) | |
| 99 | +// .tableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) | |
| 100 | +// .columns(schemaFieldValues) | |
| 101 | +// .build()); | |
| 102 | + // TODO:复用了旧逻辑,先过渡一下 | |
| 103 | + iotDevicePropertyDataMapper.insertDevicePropertyData(TdTableDO.builder() | |
| 104 | + .productKey(device.getProductKey()) | |
| 105 | + .deviceKey(device.getDeviceKey()) | |
| 96 | 106 | .columns(schemaFieldValues) |
| 97 | 107 | .build()); |
| 98 | 108 | } |
| ... | ... | @@ -145,7 +155,8 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ |
| 145 | 155 | |
| 146 | 156 | // 3. 过滤并收集有效的属性字段 |
| 147 | 157 | List<TdFieldDO> schemaFieldValues = new ArrayList<>(); |
| 148 | - schemaFieldValues.add(new TdFieldDO(TIME, time)); | |
| 158 | + //TODO:新版本是使用ts字段 | |
| 159 | +// schemaFieldValues.add(new TdFieldDO(TIME, time)); | |
| 149 | 160 | params.forEach((key, val) -> { |
| 150 | 161 | if (propertyIdentifiers.contains(key)) { |
| 151 | 162 | schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDeviceLogDataMapper.xml
| ... | ... | @@ -76,8 +76,14 @@ |
| 76 | 76 | </select> |
| 77 | 77 | |
| 78 | 78 | <!-- 检查设备日志超级表是否存在 --> |
| 79 | - <select id="checkDeviceLogTableExists" resultType="Object"> | |
| 79 | + <select id="checkDeviceLogSTableExists" resultType="Object"> | |
| 80 | 80 | SHOW STABLES LIKE 'device_log' |
| 81 | 81 | </select> |
| 82 | 82 | |
| 83 | + <!-- 检查设备日志子表是否存在 --> | |
| 84 | + <select id="checkDeviceLogTableExists" resultType="Object"> | |
| 85 | + SHOW TABLES LIKE 'device_log_${deviceKey}' | |
| 86 | + </select> | |
| 87 | + | |
| 88 | + | |
| 83 | 89 | </mapper> |
| 84 | 90 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDevicePropertyDataMapper.xml
| ... | ... | @@ -42,4 +42,46 @@ |
| 42 | 42 | DROP COLUMN ${field.field} |
| 43 | 43 | </update> |
| 44 | 44 | |
| 45 | + <insert id="insertDevicePropertyData"> | |
| 46 | + INSERT INTO device_property_${deviceKey} | |
| 47 | + USING product_property_${productKey} | |
| 48 | + TAGS ('${deviceKey}') | |
| 49 | + (ts | |
| 50 | + <foreach item="item" collection="columns" separator=","> | |
| 51 | + ,${item.fieldName} | |
| 52 | + </foreach> | |
| 53 | + ) | |
| 54 | + VALUES | |
| 55 | + (NOW | |
| 56 | + <foreach item="item" collection="columns" separator=","> | |
| 57 | + ,#{item.fieldValue} | |
| 58 | + </foreach> | |
| 59 | + ) | |
| 60 | + </insert> | |
| 61 | + | |
| 62 | + <!-- 描述超级表结构 --> | |
| 63 | + <select id="describeSuperTable" resultType="java.util.Map"> | |
| 64 | + DESCRIBE product_property_${productKey} | |
| 65 | + </select> | |
| 66 | + | |
| 67 | + <!-- 获取历史数据 --> | |
| 68 | + <select id="selectHistoryDataList" resultType="java.util.Map" | |
| 69 | + parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO"> | |
| 70 | + SELECT ${fieldName} AS data, ts AS time | |
| 71 | + FROM device_property_${deviceKey} | |
| 72 | + WHERE ts BETWEEN #{startTime} AND #{endTime} | |
| 73 | + AND ${fieldName} IS NOT NULL | |
| 74 | + ORDER BY ts DESC | |
| 75 | + LIMIT #{params.rows} OFFSET #{params.page} | |
| 76 | + </select> | |
| 77 | + | |
| 78 | + <!-- 统计历史数据总数 --> | |
| 79 | + <select id="selectHistoryCount" resultType="java.lang.Long" | |
| 80 | + parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO"> | |
| 81 | + SELECT COUNT(*) | |
| 82 | + FROM device_property_${deviceKey} | |
| 83 | + WHERE ts BETWEEN #{startTime} AND #{endTime} | |
| 84 | + AND ${fieldName} IS NOT NULL | |
| 85 | + </select> | |
| 86 | + | |
| 45 | 87 | </mapper> |
| 46 | 88 | \ No newline at end of file | ... | ... |