Commit 3dafd31da6ba6dad4beba2954ca5ed689a209699

Authored by 安浩浩
1 parent 8c84ac9d

【新增功能】 数据接收,JSON 标准格式数据接收

Showing 16 changed files with 247 additions and 55 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
  2 +
  3 +import cn.iocoder.yudao.module.iot.domain.BaseEntity;
  4 +import lombok.Data;
  5 +
  6 +import java.util.List;
  7 +
  8 +@Data
  9 +public class TableDO extends BaseEntity {
  10 +
  11 + /**
  12 + * 超级表普通列字段的值
  13 + * 值需要与创建超级表时普通列字段的数据类型对应上
  14 + */
  15 + private List<TdFieldDO> schemaFieldValues;
  16 +
  17 + /**
  18 + * 超级表标签字段的值
  19 + * 值需要与创建超级表时标签字段的数据类型对应上
  20 + */
  21 + private List<TdFieldDO> tagsFieldValues;
  22 +
  23 + /**
  24 + * 表名称
  25 + */
  26 + private String tableName;
  27 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java
@@ -16,18 +16,23 @@ public class TableData { @@ -16,18 +16,23 @@ public class TableData {
16 private List<String> schemaFieldList; 16 private List<String> schemaFieldList;
17 17
18 /** 18 /**
19 - * 超级表标签字段的值  
20 - * 值需要与创建超级表时标签字段的数据类型对应上  
21 - */  
22 - private List<Object> tagsValueList;  
23 -  
24 - /**  
25 * 超级表普通列字段的值 19 * 超级表普通列字段的值
26 * 值需要与创建超级表时普通列字段的数据类型对应上 20 * 值需要与创建超级表时普通列字段的数据类型对应上
27 */ 21 */
28 private List<Object> schemaValueList; 22 private List<Object> schemaValueList;
29 23
30 /** 24 /**
  25 + * 超级表标签字段的名称
  26 + */
  27 + private List<String> tagsFieldList;
  28 +
  29 + /**
  30 + * 超级表标签字段的值
  31 + * 值需要与创建超级表时标签字段的数据类型对应上
  32 + */
  33 + private List<Object> tagsValueList;
  34 +
  35 + /**
31 * 表名称 36 * 表名称
32 */ 37 */
33 private String tableName; 38 private String tableName;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java
@@ -20,6 +20,11 @@ public class TdFieldDO { @@ -20,6 +20,11 @@ public class TdFieldDO {
20 private String fieldName; 20 private String fieldName;
21 21
22 /** 22 /**
  23 + * 字段值
  24 + */
  25 + private Object fieldValue;
  26 +
  27 + /**
23 * 字段类型 28 * 字段类型
24 */ 29 */
25 private String dataType; 30 private String dataType;
@@ -28,4 +33,15 @@ public class TdFieldDO { @@ -28,4 +33,15 @@ public class TdFieldDO {
28 * 字段长度 33 * 字段长度
29 */ 34 */
30 private Integer dataLength = 0; 35 private Integer dataLength = 0;
  36 +
  37 + public TdFieldDO(String fieldName, String dataType, Integer dataLength) {
  38 + this.fieldName = fieldName;
  39 + this.dataType = dataType;
  40 + this.dataLength = dataLength;
  41 + }
  42 +
  43 + public TdFieldDO(String fieldName, Object fieldValue) {
  44 + this.fieldName = fieldName;
  45 + this.fieldValue = fieldValue;
  46 + }
31 } 47 }
32 \ No newline at end of file 48 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java
@@ -55,4 +55,7 @@ public interface IotThinkModelFunctionMapper extends BaseMapperX&lt;IotThinkModelFu @@ -55,4 +55,7 @@ public interface IotThinkModelFunctionMapper extends BaseMapperX&lt;IotThinkModelFu
55 IotThinkModelFunctionDO::getName, name); 55 IotThinkModelFunctionDO::getName, name);
56 } 56 }
57 57
  58 + default List<IotThinkModelFunctionDO> selectListByProductKey(String productKey){
  59 + return selectList(IotThinkModelFunctionDO::getProductKey, productKey);
  60 + }
58 } 61 }
59 \ No newline at end of file 62 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java
1 package cn.iocoder.yudao.module.iot.dal.tdengine; 1 package cn.iocoder.yudao.module.iot.dal.tdengine;
2 2
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; 4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
4 import cn.iocoder.yudao.module.iot.domain.FieldsVo; 5 import cn.iocoder.yudao.module.iot.domain.FieldsVo;
5 import cn.iocoder.yudao.module.iot.domain.SelectDto; 6 import cn.iocoder.yudao.module.iot.domain.SelectDto;
6 -import cn.iocoder.yudao.module.iot.domain.TableDto;  
7 import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; 7 import cn.iocoder.yudao.module.iot.domain.TagsSelectDao;
8 import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; 8 import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto;
9 import com.baomidou.dynamic.datasource.annotation.DS; 9 import com.baomidou.dynamic.datasource.annotation.DS;
@@ -86,9 +86,20 @@ public interface TdEngineMapper { @@ -86,9 +86,20 @@ public interface TdEngineMapper {
86 @Param("superTableName") String superTableName, 86 @Param("superTableName") String superTableName,
87 @Param("field") TdFieldDO field); 87 @Param("field") TdFieldDO field);
88 88
89 - void createTable(TableDto tableDto); 89 + /**
  90 + * 创建表 - 创建超级表的子表
  91 + * @param tableDO 表信息
  92 + */
  93 + @InterceptorIgnore(tenantLine = "true")
  94 + void createTable(TableDO tableDO);
90 95
91 - void insertData(TableDto tableDto); 96 + /**
  97 + * 插入数据 - 指定列插入数据
  98 + *
  99 + * @param tableDto 数据
  100 + */
  101 + @InterceptorIgnore(tenantLine = "true")
  102 + void insertData(TableDO tableDto);
92 103
93 List<Map<String, Object>> selectByTimestamp(SelectDto selectDto); 104 List<Map<String, Object>> selectByTimestamp(SelectDto selectDto);
94 105
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java
@@ -6,6 +6,7 @@ import jakarta.annotation.Resource; @@ -6,6 +6,7 @@ import jakarta.annotation.Resource;
6 import lombok.extern.slf4j.Slf4j; 6 import lombok.extern.slf4j.Slf4j;
7 import org.eclipse.paho.client.mqttv3.MqttClient; 7 import org.eclipse.paho.client.mqttv3.MqttClient;
8 import org.eclipse.paho.client.mqttv3.MqttMessage; 8 import org.eclipse.paho.client.mqttv3.MqttMessage;
  9 +import org.springframework.scheduling.annotation.Async;
9 import org.springframework.stereotype.Service; 10 import org.springframework.stereotype.Service;
10 11
11 // TODO @芋艿:在瞅瞅 12 // TODO @芋艿:在瞅瞅
@@ -24,6 +25,7 @@ public class EmqxServiceImpl implements EmqxService { @@ -24,6 +25,7 @@ public class EmqxServiceImpl implements EmqxService {
24 25
25 // TODO 多线程处理消息 26 // TODO 多线程处理消息
26 @Override 27 @Override
  28 + @Async
27 public void subscribeCallback(String topic, MqttMessage mqttMessage) { 29 public void subscribeCallback(String topic, MqttMessage mqttMessage) {
28 log.info("收到消息,主题: {}, 内容: {}", topic, new String(mqttMessage.getPayload())); 30 log.info("收到消息,主题: {}, 内容: {}", topic, new String(mqttMessage.getPayload()));
29 // 根据不同的主题,处理不同的业务逻辑 31 // 根据不同的主题,处理不同的业务逻辑
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java
@@ -34,6 +34,6 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { @@ -34,6 +34,6 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService {
34 .deviceName(deviceName) 34 .deviceName(deviceName)
35 .deviceKey(device.getDeviceKey()) 35 .deviceKey(device.getDeviceKey())
36 .build(); 36 .build();
37 - thingModelMessageService.saveThingModelMessage(thingModelMessage); 37 + thingModelMessageService.saveThingModelMessage(device,thingModelMessage);
38 } 38 }
39 } 39 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
@@ -20,6 +20,7 @@ import org.springframework.transaction.annotation.Transactional; @@ -20,6 +20,7 @@ import org.springframework.transaction.annotation.Transactional;
20 import org.springframework.validation.annotation.Validated; 20 import org.springframework.validation.annotation.Validated;
21 21
22 import java.time.LocalDateTime; 22 import java.time.LocalDateTime;
  23 +import java.util.Objects;
23 import java.util.UUID; 24 import java.util.UUID;
24 25
25 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -213,10 +214,30 @@ public class IotDeviceServiceImpl implements IotDeviceService { @@ -213,10 +214,30 @@ public class IotDeviceServiceImpl implements IotDeviceService {
213 @Override 214 @Override
214 public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) { 215 public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) {
215 // 校验存在 216 // 校验存在
216 - validateDeviceExists(updateReqVO.getId()); 217 + IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId());
217 218
218 // 更新状态和更新时间 219 // 更新状态和更新时间
219 IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); 220 IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class);
  221 +
  222 + // 以前是未激活,现在是上线,设置设备激活时间
  223 + if (Objects.equals(iotDeviceDO.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus())
  224 + && Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) {
  225 + updateObj.setActiveTime(LocalDateTime.now());
  226 + }
  227 +
  228 + // 如果是上线,设置上线时间
  229 + if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) {
  230 + updateObj.setLastOnlineTime(LocalDateTime.now());
  231 + }
  232 +
  233 + // 如果是离线,设置离线时间
  234 + if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) {
  235 + updateObj.setLastOfflineTime(LocalDateTime.now());
  236 + }
  237 +
  238 + // 设置状态更新时间
  239 + updateObj.setStatusLastUpdateTime(LocalDateTime.now());
  240 +
220 deviceMapper.updateById(updateObj); 241 deviceMapper.updateById(updateObj);
221 } 242 }
222 243
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java
@@ -60,27 +60,10 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService @@ -60,27 +60,10 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService
60 dataType("NCHAR"). 60 dataType("NCHAR").
61 dataLength(64). 61 dataLength(64).
62 build()); 62 build());
63 - // 年  
64 tagsFields.add(TdFieldDO.builder(). 63 tagsFields.add(TdFieldDO.builder().
65 - fieldName("year"). 64 + fieldName("device_type").
66 dataType("INT"). 65 dataType("INT").
67 build()); 66 build());
68 - // 月  
69 - tagsFields.add(TdFieldDO.builder().  
70 - fieldName("month").  
71 - dataType("INT").  
72 - build());  
73 - // 日  
74 - tagsFields.add(TdFieldDO.builder().  
75 - fieldName("day").  
76 - dataType("INT").  
77 - build());  
78 - // 时  
79 - tagsFields.add(TdFieldDO.builder().  
80 - fieldName("hour").  
81 - dataType("INT").  
82 - build());  
83 -  
84 67
85 // 4. 获取超级表的名称 68 // 4. 获取超级表的名称
86 String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); 69 String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey());
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java
1 package cn.iocoder.yudao.module.iot.service.tdengine; 1 package cn.iocoder.yudao.module.iot.service.tdengine;
2 2
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; 4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
4 import cn.iocoder.yudao.module.iot.domain.SelectDto; 5 import cn.iocoder.yudao.module.iot.domain.SelectDto;
5 -import cn.iocoder.yudao.module.iot.domain.TableDto;  
6 import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; 6 import cn.iocoder.yudao.module.iot.domain.TagsSelectDao;
7 import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; 7 import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto;
8 8
@@ -70,17 +70,15 @@ public interface IotTdEngineService { @@ -70,17 +70,15 @@ public interface IotTdEngineService {
70 * 创建表 70 * 创建表
71 * 71 *
72 * @param tableDto 表信息 72 * @param tableDto 表信息
73 - * @throws Exception 异常  
74 */ 73 */
75 - void createTable(TableDto tableDto) throws Exception; 74 + void createTable(TableDO tableDto);
76 75
77 /** 76 /**
78 * 插入数据 77 * 插入数据
79 * 78 *
80 * @param tableDto 表信息 79 * @param tableDto 表信息
81 - * @throws Exception 异常  
82 */ 80 */
83 - void insertData(TableDto tableDto) throws Exception; 81 + void insertData(TableDO tableDto);
84 82
85 /** 83 /**
86 * 根据时间戳查询数据 84 * 根据时间戳查询数据
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java
1 package cn.iocoder.yudao.module.iot.service.tdengine; 1 package cn.iocoder.yudao.module.iot.service.tdengine;
2 2
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; 4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
4 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; 5 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper;
5 import cn.iocoder.yudao.module.iot.domain.SelectDto; 6 import cn.iocoder.yudao.module.iot.domain.SelectDto;
6 -import cn.iocoder.yudao.module.iot.domain.TableDto;  
7 import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; 7 import cn.iocoder.yudao.module.iot.domain.TagsSelectDao;
8 import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; 8 import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto;
9 import jakarta.annotation.Resource; 9 import jakarta.annotation.Resource;
@@ -31,12 +31,12 @@ public class IotTdEngineServiceImpl implements IotTdEngineService { @@ -31,12 +31,12 @@ public class IotTdEngineServiceImpl implements IotTdEngineService {
31 } 31 }
32 32
33 @Override 33 @Override
34 - public void createTable(TableDto tableDto) { 34 + public void createTable(TableDO tableDto) {
35 tdEngineMapper.createTable(tableDto); 35 tdEngineMapper.createTable(tableDto);
36 } 36 }
37 37
38 @Override 38 @Override
39 - public void insertData(TableDto tableDto) { 39 + public void insertData(TableDO tableDto) {
40 tdEngineMapper.insertData(tableDto); 40 tdEngineMapper.insertData(tableDto);
41 } 41 }
42 42
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java
1 package cn.iocoder.yudao.module.iot.service.tdengine; 1 package cn.iocoder.yudao.module.iot.service.tdengine;
2 2
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; 4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
4 5
5 /** 6 /**
@@ -10,7 +11,8 @@ public interface IotThingModelMessageService { @@ -10,7 +11,8 @@ public interface IotThingModelMessageService {
10 /** 11 /**
11 * 保存物模型消息 12 * 保存物模型消息
12 * 13 *
  14 + * @param device 设备
13 * @param thingModelMessage 物模型消息 15 * @param thingModelMessage 物模型消息
14 */ 16 */
15 - void saveThingModelMessage(ThingModelMessage thingModelMessage); 17 + void saveThingModelMessage(IotDeviceDO device,ThingModelMessage thingModelMessage);
16 } 18 }
17 \ No newline at end of file 19 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java
1 package cn.iocoder.yudao.module.iot.service.tdengine; 1 package cn.iocoder.yudao.module.iot.service.tdengine;
2 2
  3 +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
  4 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO;
  5 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
  6 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser;
  7 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
  8 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; 9 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
  10 +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
  11 +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum;
  12 +import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
  13 +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
  14 +import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService;
  15 +import jakarta.annotation.Resource;
  16 +import lombok.extern.slf4j.Slf4j;
  17 +import org.springframework.beans.factory.annotation.Value;
4 import org.springframework.stereotype.Service; 18 import org.springframework.stereotype.Service;
5 19
  20 +import java.util.ArrayList;
  21 +import java.util.List;
  22 +import java.util.Map;
  23 +import java.util.stream.Collectors;
  24 +
  25 +@Slf4j
6 @Service 26 @Service
7 public class IotThingModelMessageServiceImpl implements IotThingModelMessageService { 27 public class IotThingModelMessageServiceImpl implements IotThingModelMessageService {
8 28
  29 + @Value("${spring.datasource.dynamic.datasource.tdengine.url}")
  30 + private String url;
  31 +
  32 + @Resource
  33 + private IotThinkModelFunctionService iotThinkModelFunctionService;
  34 + @Resource
  35 + private IotDeviceService iotDeviceService;
  36 + @Resource
  37 + private IotTdEngineService iotTdEngineService;
  38 +
9 @Override 39 @Override
10 - public void saveThingModelMessage(ThingModelMessage thingModelMessage) {  
11 - // TODO 芋艿,后续实现 40 + @TenantIgnore
  41 + public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) {
  42 + // 判断设备状态,如果为未激活状态,创建数据表
  43 + if (device.getStatus().equals(0)) {
  44 + // 创建设备数据表
  45 + createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey());
  46 + // 更新设备状态
  47 + IotDeviceStatusUpdateReqVO updateReqVO = new IotDeviceStatusUpdateReqVO();
  48 + updateReqVO.setId(device.getId());
  49 + updateReqVO.setStatus(IotDeviceStatusEnum.ONLINE.getStatus());
  50 + iotDeviceService.updateDeviceStatus(updateReqVO);
  51 + }
  52 +
  53 + // 1. 获取设备属性
  54 + Map<String, Object> params = thingModelMessage.dataToMap();
  55 +
  56 + // 2. 物模型校验,过滤非物模型属性
  57 + List<IotThinkModelFunctionDO> thinkModelFunctionListByProductKey = iotThinkModelFunctionService.getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey());
  58 +
  59 + // 2.1 筛选是属性 IotProductFunctionTypeEnum
  60 + thinkModelFunctionListByProductKey.removeIf(iotThinkModelFunctionDO -> !iotThinkModelFunctionDO.getType().equals(IotProductFunctionTypeEnum.PROPERTY.getType()));
  61 + if (thinkModelFunctionListByProductKey.isEmpty()) {
  62 + return;
  63 + }
  64 + // 2.2 获取属性名称
  65 + Map<String, String> thingModelProperties = thinkModelFunctionListByProductKey.stream().collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, IotThinkModelFunctionDO::getName));
  66 +
  67 + // 4. 保存属性记录
  68 + List<TdFieldDO> schemaFieldValues = new ArrayList<>();
  69 +
  70 + // 1. 设置字段名
  71 + schemaFieldValues.add(new TdFieldDO("time", thingModelMessage.getTime()));
  72 +
  73 + // 2. 遍历新属性
  74 + params.forEach((key, val) -> {
  75 + if (thingModelProperties.containsKey(key)) {
  76 + schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val));
  77 + }
  78 + });
  79 +
  80 + // 3. 保存设备属性
  81 + TableDO tableData = new TableDO();
  82 + tableData.setDataBaseName(url.substring(url.lastIndexOf("/") + 1));
  83 + tableData.setSuperTableName(getProductPropertySTableName(device.getDeviceType(), device.getProductKey()));
  84 + tableData.setTableName("device_" + device.getProductKey().toLowerCase() + "_" + device.getDeviceName().toLowerCase());
  85 + tableData.setSchemaFieldValues(schemaFieldValues);
  86 +
  87 + // 4. 保存数据
  88 + iotTdEngineService.insertData(tableData);
  89 + }
  90 +
  91 + private void createDeviceTable(Integer deviceType, String productKey, String deviceName, String deviceKey) {
  92 + List<TdFieldDO> tagsFieldValues = new ArrayList<>();
  93 + String SuperTableName = getProductPropertySTableName(deviceType, productKey);
  94 + List<Map<String, Object>> maps = iotTdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), SuperTableName);
  95 + if (maps != null) {
  96 + List<Map<String, Object>> taggedNotesList = maps.stream().filter(map -> "TAG".equals(map.get("note"))).toList();
  97 + tagsFieldValues = FieldParser.parse(taggedNotesList.stream()
  98 + .map(map -> List.of(map.get("field"), map.get("type"), map.get("length")))
  99 + .collect(Collectors.toList()));
  100 + for (TdFieldDO tagsFieldValue : tagsFieldValues) {
  101 + switch (tagsFieldValue.getFieldName()) {
  102 + case "product_key" -> tagsFieldValue.setFieldValue(productKey);
  103 + case "device_key" -> tagsFieldValue.setFieldValue(deviceKey);
  104 + case "device_name" -> tagsFieldValue.setFieldValue(deviceName);
  105 + case "device_type" -> tagsFieldValue.setFieldValue(deviceType);
  106 + }
  107 + }
  108 + }
  109 +
  110 + // 1. 创建设备数据表
  111 + String tableName = "device_" + productKey.toLowerCase() + "_" + deviceName.toLowerCase();
  112 + TableDO tableDto = new TableDO();
  113 + tableDto.setDataBaseName(url.substring(url.lastIndexOf("/") + 1));
  114 + tableDto.setSuperTableName(SuperTableName);
  115 + tableDto.setTableName(tableName);
  116 + tableDto.setTagsFieldValues(tagsFieldValues);
  117 + iotTdEngineService.createTable(tableDto);
  118 + }
  119 +
  120 + static String getProductPropertySTableName(Integer deviceType, String productKey) {
  121 + return switch (deviceType) {
  122 + case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase();
  123 + case 2 -> String.format("gateway_%s", productKey).toLowerCase();
  124 + default -> String.format("device_%s", productKey).toLowerCase();
  125 + };
12 } 126 }
13 } 127 }
14 \ No newline at end of file 128 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java
@@ -68,4 +68,12 @@ public interface IotThinkModelFunctionService { @@ -68,4 +68,12 @@ public interface IotThinkModelFunctionService {
68 * @param productId 产品编号 68 * @param productId 产品编号
69 */ 69 */
70 void createSuperTableDataModel(Long productId); 70 void createSuperTableDataModel(Long productId);
  71 +
  72 + /**
  73 + * 获得产品物模型列表
  74 + *
  75 + * @param productKey 产品 Key
  76 + * @return 产品物模型列表
  77 + */
  78 + List<IotThinkModelFunctionDO> getThinkModelFunctionListByProductKey(String productKey);
71 } 79 }
72 \ No newline at end of file 80 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
@@ -199,6 +199,11 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe @@ -199,6 +199,11 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
199 dbStructureDataService.createSuperTableDataModel(product, functionList); 199 dbStructureDataService.createSuperTableDataModel(product, functionList);
200 } 200 }
201 201
  202 + @Override
  203 + public List<IotThinkModelFunctionDO> getThinkModelFunctionListByProductKey(String productKey) {
  204 + return thinkModelFunctionMapper.selectListByProductKey(productKey);
  205 + }
  206 +
202 /** 207 /**
203 * 创建默认的事件和服务 208 * 创建默认的事件和服务
204 */ 209 */
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml
@@ -110,30 +110,27 @@ @@ -110,30 +110,27 @@
110 </foreach> 110 </foreach>
111 </update> 111 </update>
112 112
  113 + <!-- CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...);-->
113 <update id="createTable"> 114 <update id="createTable">
114 - create table  
115 - if not exists #{dataBaseName}.#{tableName}  
116 - using #{dataBaseName}.#{superTableName}  
117 - tags  
118 - <foreach item="item" collection="tagsFieldValues" separator=","  
119 - open="(" close=")" index=""> 115 + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}
  116 + USING ${dataBaseName}.${superTableName}
  117 + <foreach item="item" collection="tagsFieldValues" separator="," open="(" close=")">
  118 + ${item.fieldName}
  119 + </foreach>
  120 + TAGS
  121 + <foreach item="item" collection="tagsFieldValues" separator="," open="(" close=")">
120 #{item.fieldValue} 122 #{item.fieldValue}
121 </foreach> 123 </foreach>
122 </update> 124 </update>
123 125
  126 + <!-- insert into d1004 (ts, voltage, phase) values("2018-10-04 14:38:06", 223, 0.29) -->
124 <insert id="insertData"> 127 <insert id="insertData">
125 - insert into #{dataBaseName}.#{tableName} 128 + INSERT INTO ${dataBaseName}.${tableName}
126 <foreach item="item" collection="schemaFieldValues" separator="," 129 <foreach item="item" collection="schemaFieldValues" separator=","
127 open="(" close=")" index=""> 130 open="(" close=")" index="">
128 - #{item.fieldName}  
129 - </foreach>  
130 - using #{dataBaseName}.#{superTableName}  
131 - tags  
132 - <foreach item="item" collection="tagsFieldValues" separator=","  
133 - open="(" close=")" index="">  
134 - #{item.fieldValue} 131 + ${item.fieldName}
135 </foreach> 132 </foreach>
136 - values 133 + VALUES
137 <foreach item="item" collection="schemaFieldValues" separator="," 134 <foreach item="item" collection="schemaFieldValues" separator=","
138 open="(" close=")" index=""> 135 open="(" close=")" index="">
139 #{item.fieldValue} 136 #{item.fieldValue}