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 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 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 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 20 private String fieldName;
21 21  
22 22 /**
  23 + * 字段值
  24 + */
  25 + private Object fieldValue;
  26 +
  27 + /**
23 28 * 字段类型
24 29 */
25 30 private String dataType;
... ... @@ -28,4 +33,15 @@ public class TdFieldDO {
28 33 * 字段长度
29 34 */
30 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 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 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 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 1 package cn.iocoder.yudao.module.iot.dal.tdengine;
2 2  
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
3 4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
4 5 import cn.iocoder.yudao.module.iot.domain.FieldsVo;
5 6 import cn.iocoder.yudao.module.iot.domain.SelectDto;
6   -import cn.iocoder.yudao.module.iot.domain.TableDto;
7 7 import cn.iocoder.yudao.module.iot.domain.TagsSelectDao;
8 8 import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto;
9 9 import com.baomidou.dynamic.datasource.annotation.DS;
... ... @@ -86,9 +86,20 @@ public interface TdEngineMapper {
86 86 @Param("superTableName") String superTableName,
87 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 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 import lombok.extern.slf4j.Slf4j;
7 7 import org.eclipse.paho.client.mqttv3.MqttClient;
8 8 import org.eclipse.paho.client.mqttv3.MqttMessage;
  9 +import org.springframework.scheduling.annotation.Async;
9 10 import org.springframework.stereotype.Service;
10 11  
11 12 // TODO @芋艿:在瞅瞅
... ... @@ -24,6 +25,7 @@ public class EmqxServiceImpl implements EmqxService {
24 25  
25 26 // TODO 多线程处理消息
26 27 @Override
  28 + @Async
27 29 public void subscribeCallback(String topic, MqttMessage mqttMessage) {
28 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 34 .deviceName(deviceName)
35 35 .deviceKey(device.getDeviceKey())
36 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 20 import org.springframework.validation.annotation.Validated;
21 21  
22 22 import java.time.LocalDateTime;
  23 +import java.util.Objects;
23 24 import java.util.UUID;
24 25  
25 26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
... ... @@ -213,10 +214,30 @@ public class IotDeviceServiceImpl implements IotDeviceService {
213 214 @Override
214 215 public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) {
215 216 // 校验存在
216   - validateDeviceExists(updateReqVO.getId());
  217 + IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId());
217 218  
218 219 // 更新状态和更新时间
219 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 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 60 dataType("NCHAR").
61 61 dataLength(64).
62 62 build());
63   - // 年
64 63 tagsFields.add(TdFieldDO.builder().
65   - fieldName("year").
  64 + fieldName("device_type").
66 65 dataType("INT").
67 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 68 // 4. 获取超级表的名称
86 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 1 package cn.iocoder.yudao.module.iot.service.tdengine;
2 2  
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
3 4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
4 5 import cn.iocoder.yudao.module.iot.domain.SelectDto;
5   -import cn.iocoder.yudao.module.iot.domain.TableDto;
6 6 import cn.iocoder.yudao.module.iot.domain.TagsSelectDao;
7 7 import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto;
8 8  
... ... @@ -70,17 +70,15 @@ public interface IotTdEngineService {
70 70 * 创建表
71 71 *
72 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 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 1 package cn.iocoder.yudao.module.iot.service.tdengine;
2 2  
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
3 4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
4 5 import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper;
5 6 import cn.iocoder.yudao.module.iot.domain.SelectDto;
6   -import cn.iocoder.yudao.module.iot.domain.TableDto;
7 7 import cn.iocoder.yudao.module.iot.domain.TagsSelectDao;
8 8 import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto;
9 9 import jakarta.annotation.Resource;
... ... @@ -31,12 +31,12 @@ public class IotTdEngineServiceImpl implements IotTdEngineService {
31 31 }
32 32  
33 33 @Override
34   - public void createTable(TableDto tableDto) {
  34 + public void createTable(TableDO tableDto) {
35 35 tdEngineMapper.createTable(tableDto);
36 36 }
37 37  
38 38 @Override
39   - public void insertData(TableDto tableDto) {
  39 + public void insertData(TableDO tableDto) {
40 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 1 package cn.iocoder.yudao.module.iot.service.tdengine;
2 2  
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
3 4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
4 5  
5 6 /**
... ... @@ -10,7 +11,8 @@ public interface IotThingModelMessageService {
10 11 /**
11 12 * 保存物模型消息
12 13 *
  14 + * @param device 设备
13 15 * @param thingModelMessage 物模型消息
14 16 */
15   - void saveThingModelMessage(ThingModelMessage thingModelMessage);
  17 + void saveThingModelMessage(IotDeviceDO device,ThingModelMessage thingModelMessage);
16 18 }
17 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 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 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 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 26 @Service
7 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 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 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 68 * @param productId 产品编号
69 69 */
70 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 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 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 110 </foreach>
111 111 </update>
112 112  
  113 + <!-- CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...);-->
113 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 122 #{item.fieldValue}
121 123 </foreach>
122 124 </update>
123 125  
  126 + <!-- insert into d1004 (ts, voltage, phase) values("2018-10-04 14:38:06", 223, 0.29) -->
124 127 <insert id="insertData">
125   - insert into #{dataBaseName}.#{tableName}
  128 + INSERT INTO ${dataBaseName}.${tableName}
126 129 <foreach item="item" collection="schemaFieldValues" separator=","
127 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 132 </foreach>
136   - values
  133 + VALUES
137 134 <foreach item="item" collection="schemaFieldValues" separator=","
138 135 open="(" close=")" index="">
139 136 #{item.fieldValue}
... ...