diff --git a/Dockerfile b/Dockerfile
index e5409b4a..56edff47 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
FROM openjdk:11-jre-slim
WORKDIR /app
-ADD iot-standalone/target/iot-standalone-0.4.0-SNAPSHOT.tar /app
+ADD iot-standalone/target/iot-standalone-0.4.1-SNAPSHOT.tar /app
ADD data/init /app/data/init
ADD data/components /app/data/components
ADD data/converters /app/data/converters
diff --git a/data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/iot-http-biz-component-0.3.2-SNAPSHOT.jar b/data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/iot-http-biz-component-0.3.2-SNAPSHOT.jar
deleted file mode 100644
index f46a9ffa..00000000
Binary files a/data/components/3ababc5e-15e9-45a7-8f38-2a6afd45c780/iot-http-biz-component-0.3.2-SNAPSHOT.jar and /dev/null differ
diff --git a/data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/iot-emqx-component-0.3.2-SNAPSHOT.jar b/data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/iot-emqx-component-0.3.2-SNAPSHOT.jar
deleted file mode 100644
index dc9a4378..00000000
Binary files a/data/components/6c095554-35e7-4e9d-a8d2-bb919e9479f4/iot-emqx-component-0.3.2-SNAPSHOT.jar and /dev/null differ
diff --git a/iot-auth-server/pom.xml b/iot-auth-server/pom.xml
index c48e628d..243ce202 100755
--- a/iot-auth-server/pom.xml
+++ b/iot-auth-server/pom.xml
@@ -5,7 +5,7 @@
iotkit-parent
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-common/pom.xml b/iot-common/pom.xml
index 2bfec4f3..0d16f28f 100755
--- a/iot-common/pom.xml
+++ b/iot-common/pom.xml
@@ -5,7 +5,7 @@
iotkit-parent
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-components/iot-component-base/pom.xml b/iot-components/iot-component-base/pom.xml
index 33ae79ae..db7ee641 100755
--- a/iot-components/iot-component-base/pom.xml
+++ b/iot-components/iot-component-base/pom.xml
@@ -5,7 +5,7 @@
iot-components
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-components/iot-component-converter/pom.xml b/iot-components/iot-component-converter/pom.xml
index 35283c03..c062b9ca 100755
--- a/iot-components/iot-component-converter/pom.xml
+++ b/iot-components/iot-component-converter/pom.xml
@@ -5,7 +5,7 @@
iot-components
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-components/iot-component-server/pom.xml b/iot-components/iot-component-server/pom.xml
index b3b3964c..b8c96db4 100755
--- a/iot-components/iot-component-server/pom.xml
+++ b/iot-components/iot-component-server/pom.xml
@@ -5,7 +5,7 @@
iot-components
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DeviceBehaviourService.java b/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DeviceBehaviourService.java
index 3522f264..b1ac60cd 100755
--- a/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DeviceBehaviourService.java
+++ b/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DeviceBehaviourService.java
@@ -139,7 +139,7 @@ public class DeviceBehaviourService {
ThingModelMessage modelMessage = new ThingModelMessage(
UUID.randomUUID().toString(),
UniqueIdUtil.newRequestId(), "",
- pk, dn,
+ pk, dn, uid,
ThingModelMessage.TYPE_LIFETIME, "register",
0, new HashMap<>(), System.currentTimeMillis(),
System.currentTimeMillis()
@@ -193,7 +193,7 @@ public class DeviceBehaviourService {
//否则为父设备,同步透传子设备状态
List subDeviceIds = deviceInfoData.findSubDeviceIds(device.getDeviceId());
for (String subDeviceId : subDeviceIds) {
- DeviceInfo subDevice=deviceInfoData.findByDeviceId(subDeviceId);
+ DeviceInfo subDevice = deviceInfoData.findByDeviceId(subDeviceId);
Product product = productData.findById(subDevice.getProductKey());
Boolean transparent = product.getTransparent();
//透传设备父设备上线,子设备也上线。非透传设备父设备离线,子设备才离线
@@ -217,7 +217,7 @@ public class DeviceBehaviourService {
ThingModelMessage modelMessage = new ThingModelMessage(
UUID.randomUUID().toString(),
UniqueIdUtil.newRequestId(), "",
- device.getProductKey(), device.getDeviceName(),
+ device.getProductKey(), device.getDeviceName(), device.getUid(),
ThingModelMessage.TYPE_STATE,
online ? DeviceState.STATE_ONLINE : DeviceState.STATE_OFFLINE,
0,
diff --git a/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DeviceMessageConsumer.java b/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DeviceMessageConsumer.java
index 2fb4d7d4..e75b1daa 100755
--- a/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DeviceMessageConsumer.java
+++ b/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DeviceMessageConsumer.java
@@ -10,6 +10,8 @@
package cc.iotkit.comps.service;
import cc.iotkit.common.Constants;
+import cc.iotkit.data.IDeviceInfoData;
+import cc.iotkit.model.device.DeviceInfo;
import cc.iotkit.model.device.message.ThingModelMessage;
import cc.iotkit.mq.ConsumerHandler;
import cc.iotkit.mq.MqConsumer;
@@ -17,6 +19,7 @@ import cc.iotkit.mq.MqProducer;
import cc.iotkit.temporal.IThingModelMessageData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@@ -29,6 +32,9 @@ public class DeviceMessageConsumer implements ConsumerHandler
@Autowired
private IThingModelMessageData thingModelMessageData;
@Autowired
+ @Qualifier("deviceInfoDataCache")
+ private IDeviceInfoData deviceInfoData;
+ @Autowired
private MqConsumer thingModelMessageConsumer;
@Autowired
private MqProducer thingModelMessageMqProducer;
@@ -52,6 +58,12 @@ public class DeviceMessageConsumer implements ConsumerHandler
thingModelMessageMqProducer.publish(Constants.DEVICE_CONFIG_TOPIC, msg);
}
+ DeviceInfo device = deviceInfoData.findByDeviceId(msg.getDeviceId());
+ if (device == null) {
+ return;
+ }
+ msg.setUid(device.getUid());
+
//设备消息入库
thingModelMessageData.add(msg);
} catch (Throwable e) {
diff --git a/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DevicePropertyConsumer.java b/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DevicePropertyConsumer.java
index 5e10a6ce..3bdcf5ae 100755
--- a/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DevicePropertyConsumer.java
+++ b/iot-components/iot-component-server/src/main/java/cc/iotkit/comps/service/DevicePropertyConsumer.java
@@ -12,7 +12,6 @@ package cc.iotkit.comps.service;
import cc.iotkit.common.Constants;
import cc.iotkit.common.utils.JsonUtil;
import cc.iotkit.data.IDeviceInfoData;
-import cc.iotkit.model.device.message.DeviceProperty;
import cc.iotkit.model.device.message.ThingModelMessage;
import cc.iotkit.mq.ConsumerHandler;
import cc.iotkit.mq.MqConsumer;
@@ -23,8 +22,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Map;
/**
@@ -59,22 +56,9 @@ public class DevicePropertyConsumer implements ConsumerHandler batch = new ArrayList<>();
- for (String key : properties.keySet()) {
- batch.add(new DeviceProperty(
- //防止重复id被覆盖
- msg.getMid() + "_" + key,
- deviceId,
- key,
- properties.get(key),
- msg.getOccurred()
- ));
- }
-
- //批量保存
+ //保存属性记录
try {
- devicePropertyData.addProperties(batch);
+ devicePropertyData.addProperties(deviceId, properties, msg.getOccurred());
} catch (Throwable e) {
log.warn("save property data error", e);
}
diff --git a/iot-components/iot-ctwing-component/pom.xml b/iot-components/iot-ctwing-component/pom.xml
index 01549882..aba9c598 100644
--- a/iot-components/iot-ctwing-component/pom.xml
+++ b/iot-components/iot-ctwing-component/pom.xml
@@ -5,7 +5,7 @@
iot-components
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-components/iot-emqx-component/dependency-reduced-pom.xml b/iot-components/iot-emqx-component/dependency-reduced-pom.xml
index 5af6fb55..94d56193 100644
--- a/iot-components/iot-emqx-component/dependency-reduced-pom.xml
+++ b/iot-components/iot-emqx-component/dependency-reduced-pom.xml
@@ -3,7 +3,7 @@
iot-components
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
iot-emqx-component
@@ -84,25 +84,25 @@
cc.iotkit
iot-model
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
compile
cc.iotkit
iot-common
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
compile
cc.iotkit
iot-component-base
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
compile
cc.iotkit
iot-data-service
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
compile
diff --git a/iot-components/iot-emqx-component/pom.xml b/iot-components/iot-emqx-component/pom.xml
index 2b155428..a36f68a0 100755
--- a/iot-components/iot-emqx-component/pom.xml
+++ b/iot-components/iot-emqx-component/pom.xml
@@ -5,7 +5,7 @@
iot-components
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-components/iot-http-biz-component/dependency-reduced-pom.xml b/iot-components/iot-http-biz-component/dependency-reduced-pom.xml
index 17259860..cd716b56 100644
--- a/iot-components/iot-http-biz-component/dependency-reduced-pom.xml
+++ b/iot-components/iot-http-biz-component/dependency-reduced-pom.xml
@@ -3,7 +3,7 @@
iot-components
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
iot-http-biz-component
@@ -58,7 +58,7 @@
cc.iotkit
iot-component-base
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
compile
diff --git a/iot-components/iot-http-biz-component/pom.xml b/iot-components/iot-http-biz-component/pom.xml
index 52e0412a..c4f1a884 100755
--- a/iot-components/iot-http-biz-component/pom.xml
+++ b/iot-components/iot-http-biz-component/pom.xml
@@ -5,7 +5,7 @@
iot-components
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-components/iot-mqtt-component/dependency-reduced-pom.xml b/iot-components/iot-mqtt-component/dependency-reduced-pom.xml
index d71f38e8..f9412f1c 100644
--- a/iot-components/iot-mqtt-component/dependency-reduced-pom.xml
+++ b/iot-components/iot-mqtt-component/dependency-reduced-pom.xml
@@ -3,7 +3,7 @@
iot-components
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
iot-mqtt-component
@@ -82,19 +82,19 @@
cc.iotkit
iot-common
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
compile
cc.iotkit
iot-component-base
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
compile
cc.iotkit
iot-data-service
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
compile
diff --git a/iot-components/iot-mqtt-component/pom.xml b/iot-components/iot-mqtt-component/pom.xml
index f123136a..02a8e31c 100755
--- a/iot-components/iot-mqtt-component/pom.xml
+++ b/iot-components/iot-mqtt-component/pom.xml
@@ -5,7 +5,7 @@
iot-components
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-components/pom.xml b/iot-components/pom.xml
index fedc95d5..6824953d 100755
--- a/iot-components/pom.xml
+++ b/iot-components/pom.xml
@@ -5,7 +5,7 @@
iotkit-parent
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-data/iot-data-cache/pom.xml b/iot-data/iot-data-cache/pom.xml
index 053c1931..74fad7ee 100755
--- a/iot-data/iot-data-cache/pom.xml
+++ b/iot-data/iot-data-cache/pom.xml
@@ -5,7 +5,7 @@
iot-data
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-data/iot-data-service/pom.xml b/iot-data/iot-data-service/pom.xml
index 1e6dba2b..960299ee 100755
--- a/iot-data/iot-data-service/pom.xml
+++ b/iot-data/iot-data-service/pom.xml
@@ -5,7 +5,7 @@
iot-data
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-data/iot-es-temporal-service/pom.xml b/iot-data/iot-es-temporal-service/pom.xml
index ed14dc04..0b03763e 100755
--- a/iot-data/iot-es-temporal-service/pom.xml
+++ b/iot-data/iot-es-temporal-service/pom.xml
@@ -5,7 +5,7 @@
iot-data
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
diff --git a/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/DbStructureDataImpl.java b/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/DbStructureDataImpl.java
new file mode 100644
index 00000000..af844b06
--- /dev/null
+++ b/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/DbStructureDataImpl.java
@@ -0,0 +1,23 @@
+package cc.iotkit.temporal.es.service;
+
+import cc.iotkit.model.product.ThingModel;
+import cc.iotkit.temporal.IDbStructureData;
+import org.springframework.stereotype.Service;
+
+@Service
+public class DbStructureDataImpl implements IDbStructureData {
+ @Override
+ public void defineThingModel(ThingModel thingModel) {
+
+ }
+
+ @Override
+ public void undefineThingModel(ThingModel thingModel) {
+
+ }
+
+ @Override
+ public void initDbStructure() {
+
+ }
+}
diff --git a/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/DevicePropertyDataImpl.java b/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/DevicePropertyDataImpl.java
index 82896c9b..ef13a430 100755
--- a/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/DevicePropertyDataImpl.java
+++ b/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/DevicePropertyDataImpl.java
@@ -23,7 +23,10 @@ import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.UUID;
import java.util.stream.Collectors;
@Service
@@ -50,9 +53,13 @@ public class DevicePropertyDataImpl implements IDevicePropertyData {
}
@Override
- public void addProperties(List properties) {
- template.save(properties.stream().map(DevicePropertyMapper.M::toVo)
- .collect(Collectors.toList()));
+ public void addProperties(String deviceId, Map properties, long time) {
+ List deviceProperties = new ArrayList<>();
+ properties.forEach((key, val) -> deviceProperties.add(
+ new DocDeviceProperty(UUID.randomUUID().toString(), deviceId, key, val, time)
+ ));
+
+ template.save(deviceProperties);
}
diff --git a/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/ThingModelMessageDataImpl.java b/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/ThingModelMessageDataImpl.java
index b8989ebd..a156e1e7 100755
--- a/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/ThingModelMessageDataImpl.java
+++ b/iot-data/iot-es-temporal-service/src/main/java/cc/iotkit/temporal/es/service/ThingModelMessageDataImpl.java
@@ -76,6 +76,7 @@ public class ThingModelMessageDataImpl implements IThingModelMessageData {
queryBuilder.must(QueryBuilders.termQuery("uid", uid));
}
+ //按小时统计消息数量
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(queryBuilder)
.withAggregations(AggregationBuilders.dateHistogram("agg")
diff --git a/iot-data/iot-model/pom.xml b/iot-data/iot-model/pom.xml
index 93253210..5a232aba 100755
--- a/iot-data/iot-model/pom.xml
+++ b/iot-data/iot-model/pom.xml
@@ -5,9 +5,9 @@
iot-data
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
iot-model
diff --git a/iot-data/iot-model/src/main/java/cc/iotkit/model/device/message/ThingModelMessage.java b/iot-data/iot-model/src/main/java/cc/iotkit/model/device/message/ThingModelMessage.java
index 173d02ff..def6275b 100755
--- a/iot-data/iot-model/src/main/java/cc/iotkit/model/device/message/ThingModelMessage.java
+++ b/iot-data/iot-model/src/main/java/cc/iotkit/model/device/message/ThingModelMessage.java
@@ -48,6 +48,11 @@ public class ThingModelMessage {
private String deviceName;
+ /**
+ * 所属用户ID
+ */
+ private String uid;
+
/**
* 消息类型
* lifetime:生命周期
diff --git a/iot-data/iot-rdb-data-service/pom.xml b/iot-data/iot-rdb-data-service/pom.xml
index 85682cf3..e27bd6a6 100755
--- a/iot-data/iot-rdb-data-service/pom.xml
+++ b/iot-data/iot-rdb-data-service/pom.xml
@@ -5,9 +5,9 @@
iot-data
cc.iotkit
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
- 0.4.0-SNAPSHOT
+ 0.4.1-SNAPSHOT
4.0.0
iot-rdb-data-service
diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/config/JdbcTemplateConfig.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/config/JdbcTemplateConfig.java
new file mode 100644
index 00000000..0f6d4539
--- /dev/null
+++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/config/JdbcTemplateConfig.java
@@ -0,0 +1,30 @@
+package cc.iotkit.data.config;
+
+
+import org.springframework.boot.autoconfigure.jdbc.JdbcProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.sql.DataSource;
+
+@Configuration(
+ proxyBeanMethods = false
+)
+class JdbcTemplateConfig {
+
+ @Bean
+ @Primary
+ JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+ JdbcProperties.Template template = properties.getTemplate();
+ jdbcTemplate.setFetchSize(template.getFetchSize());
+ jdbcTemplate.setMaxRows(template.getMaxRows());
+ if (template.getQueryTimeout() != null) {
+ jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
+ }
+
+ return jdbcTemplate;
+ }
+}
\ No newline at end of file
diff --git a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceInfoDataImpl.java b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceInfoDataImpl.java
index 1ea9db43..3f6b7d9a 100755
--- a/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceInfoDataImpl.java
+++ b/iot-data/iot-rdb-data-service/src/main/java/cc/iotkit/data/service/DeviceInfoDataImpl.java
@@ -23,7 +23,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
-import java.util.function.ToIntFunction;
import java.util.stream.Collectors;
@Primary
diff --git a/iot-data/iot-td-temporal-service/pom.xml b/iot-data/iot-td-temporal-service/pom.xml
new file mode 100644
index 00000000..f6449363
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/pom.xml
@@ -0,0 +1,65 @@
+
+
+
+ iot-data
+ cc.iotkit
+ 0.4.1-SNAPSHOT
+
+ 4.0.0
+
+ iot-td-temporal-service
+
+
+
+
+ org.springframework
+ spring-context
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+ com.taosdata.jdbc
+ taos-jdbcdriver
+ 2.0.40
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+
+ org.mapstruct
+ mapstruct
+
+
+
+ cn.hutool
+ hutool-http
+
+
+
+ cc.iotkit
+ iot-temporal-service
+
+
+
+ cc.iotkit
+ iot-data-cache
+
+
+
+
+
\ No newline at end of file
diff --git a/iot-data/iot-td-temporal-service/readme.md b/iot-data/iot-td-temporal-service/readme.md
new file mode 100644
index 00000000..905266ca
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/readme.md
@@ -0,0 +1,5 @@
+### 时序数据库服务接口的TDengine实现
+
+版本:v0.4.1
+
+
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/config/Constants.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/config/Constants.java
new file mode 100644
index 00000000..f01931b0
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/config/Constants.java
@@ -0,0 +1,18 @@
+package cc.iotkit.temporal.td.config;
+
+public interface Constants {
+
+ /**
+ * 根据产品key获取产品属性超级表名
+ */
+ static String getProductPropertySTableName(String productKey) {
+ return String.format("product_property_%s", productKey.toLowerCase());
+ }
+
+ /**
+ * 根据deviceId获取设备属性表名
+ */
+ static String getDevicePropertyTableName(String deviceId) {
+ return String.format("device_property_%s", deviceId.toLowerCase());
+ }
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/config/TdDatasourceConfig.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/config/TdDatasourceConfig.java
new file mode 100644
index 00000000..6ac234c3
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/config/TdDatasourceConfig.java
@@ -0,0 +1,34 @@
+package cc.iotkit.temporal.td.config;
+
+import cc.iotkit.temporal.td.dao.TdTemplate;
+import com.zaxxer.hikari.HikariDataSource;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class TdDatasourceConfig {
+
+ @Value("${spring.td-datasource.url}")
+ private String url;
+
+ @Value("${spring.td-datasource.driverClassName}")
+ private String driverClassName;
+
+ @Value("${spring.td-datasource.username}")
+ private String username;
+
+ @Value("${spring.td-datasource.password}")
+ private String password;
+
+ @Bean("tdJdbcTemplate")
+ public TdTemplate tdJdbcTemplate() {
+ HikariDataSource dataSource = new HikariDataSource();
+ dataSource.setJdbcUrl(url);
+ dataSource.setUsername(username);
+ dataSource.setPassword(password);
+ dataSource.setDriverClassName(driverClassName);
+ return new TdTemplate(dataSource);
+ }
+
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dao/TdTemplate.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dao/TdTemplate.java
new file mode 100644
index 00000000..bcd206b2
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dao/TdTemplate.java
@@ -0,0 +1,19 @@
+package cc.iotkit.temporal.td.dao;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.sql.DataSource;
+
+public class TdTemplate extends JdbcTemplate {
+
+ public TdTemplate() {
+ }
+
+ public TdTemplate(DataSource dataSource) {
+ super(dataSource);
+ }
+
+ public TdTemplate(DataSource dataSource, boolean lazyInit) {
+ super(dataSource, lazyInit);
+ }
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/FieldParser.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/FieldParser.java
new file mode 100644
index 00000000..e4e0ecb9
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/FieldParser.java
@@ -0,0 +1,75 @@
+package cc.iotkit.temporal.td.dm;
+
+import cc.iotkit.model.product.ThingModel;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class FieldParser {
+
+ /**
+ * 物模型到td数据类型映射
+ */
+ private static final Map TYPE_MAPPING = Map.of(
+ "int32", "INT",
+ "float", "FLOAT",
+ "bool", "TINYINT",
+ "enum", "TINYINT",
+ "text", "NCHAR",
+ "date", "NCHAR"
+ );
+
+ /**
+ * 将物模型字段转换为td字段
+ */
+ public static TdField parse(ThingModel.Property property) {
+ String filedName = property.getIdentifier().toLowerCase();
+ ThingModel.DataType dataType = property.getDataType();
+ String type = dataType.getType();
+
+ //将物模型字段类型映射为td字段类型
+ String fType = TYPE_MAPPING.get(type);
+ Object specs = dataType.getSpecs();
+ int len = -1;
+ if (specs instanceof Map) {
+ Object objLen = ((Map, ?>) specs).get("length");
+ if (objLen != null) {
+ len = Integer.parseInt(objLen.toString());
+ }
+ }
+
+ return new TdField(filedName, fType, len);
+ }
+
+ /**
+ * 获取物模型中的字段列表
+ */
+ public static List parse(ThingModel thingModel) {
+ return thingModel.getModel().getProperties().stream().map(FieldParser::parse).collect(Collectors.toList());
+ }
+
+ /**
+ * 将从库中查出来的字段信息转换为td字段对象
+ */
+ public static List parse(List rows) {
+ return (List) rows.stream().map((r) -> {
+ List row = (List) r;
+ String type = row.get(1).toString().toUpperCase();
+ return new TdField(
+ row.get(0).toString(),
+ type,
+ type.equals("NCHAR") ? Integer.parseInt(row.get(2).toString()) : -1);
+ }).collect(Collectors.toList());
+ }
+
+ /**
+ * 获取字段字义
+ */
+ public static String getFieldDefine(TdField field) {
+ return field.getName() + " " + (field.getLength() > 0 ?
+ String.format("%s(%d)", field.getType(), field.getLength())
+ : field.getType());
+ }
+
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TableManager.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TableManager.java
new file mode 100644
index 00000000..39a73c85
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TableManager.java
@@ -0,0 +1,126 @@
+package cc.iotkit.temporal.td.dm;
+
+import java.util.List;
+
+public class TableManager {
+
+ /**
+ * 创建超级表模板(含存在判断)
+ */
+ private static final String CREATE_STABLE_INE_TPL = "CREATE STABLE IF NOT EXISTS %s (%s) TAGS (%s);";
+
+ /**
+ * 删除超级表
+ */
+ private static final String DROP_STABLE_TPL = "DROP STABLE IF EXISTS %s;";
+
+ /**
+ * 获取表的结构信息
+ */
+ private static final String DESC_TB_TPL = "DESCRIBE %s;";
+
+ /**
+ * 超级表增加列
+ */
+ private static final String ALTER_STABLE_ADD_COL_TPL = "ALTER STABLE %s ADD COLUMN %s;";
+
+ /**
+ * 超级表修改列
+ */
+ private static final String ALTER_STABLE_MODIFY_COL_TPL = "ALTER STABLE %s MODIFY COLUMN %s;";
+
+ /**
+ * 超级表删除列
+ */
+ private static final String ALTER_STABLE_DROP_COL_TPL = "ALTER STABLE %s DROP COLUMN %s;";
+
+ /**
+ * 获取创建表sql
+ */
+ public static String getCreateSTableSql(String tbName, List fields, TdField... tags) {
+ if (fields.size() == 0) {
+ return null;
+ }
+
+ //生成字段片段
+ StringBuilder sbField = new StringBuilder("time timestamp,");
+
+ for (TdField field : fields) {
+ sbField.append(FieldParser.getFieldDefine(field));
+ sbField.append(",");
+ }
+ sbField.deleteCharAt(sbField.length() - 1);
+
+ String fieldFrag = sbField.toString();
+
+ //生成tag
+ StringBuilder sbTag = new StringBuilder();
+ for (TdField tag : tags) {
+ sbTag.append(FieldParser.getFieldDefine(tag))
+ .append(",");
+ }
+ sbTag.deleteCharAt(sbTag.length() - 1);
+
+ return String.format(CREATE_STABLE_INE_TPL, tbName, fieldFrag, sbTag.toString());
+
+ }
+
+ /**
+ * 取正确的表名
+ *
+ * @param name 表象
+ */
+ public static String rightTbName(String name) {
+ return name.toLowerCase().replace("-", "_");
+ }
+
+ /**
+ * 获取表详情的sql
+ */
+ public static String getDescTableSql(String tbName) {
+ return String.format(DESC_TB_TPL, tbName);
+ }
+
+ /**
+ * 获取添加字段sql
+ */
+ public static String getAddSTableColumnSql(String tbName, List fields) {
+ StringBuilder sbAdd = new StringBuilder();
+ for (TdField field : fields) {
+ sbAdd.append(String.format(ALTER_STABLE_ADD_COL_TPL,
+ tbName,
+ FieldParser.getFieldDefine(field)
+ ));
+ }
+ return sbAdd.toString();
+ }
+
+ /**
+ * 获取修改字段sql
+ */
+ public static String getModifySTableColumnSql(String tbName, List fields) {
+ StringBuilder sbModify = new StringBuilder();
+ for (TdField field : fields) {
+ sbModify.append(String.format(ALTER_STABLE_MODIFY_COL_TPL,
+ tbName,
+ FieldParser.getFieldDefine(field)
+ ));
+ }
+ return sbModify.toString();
+ }
+
+ /**
+ * 获取删除字段sql
+ */
+ public static String getDropSTableColumnSql(String tbName, List fields) {
+ StringBuilder sbDrop = new StringBuilder();
+ for (TdField field : fields) {
+ sbDrop.append(String.format(ALTER_STABLE_DROP_COL_TPL,
+ tbName,
+ field.getName()
+ ));
+ }
+ return sbDrop.toString();
+ }
+
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TdField.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TdField.java
new file mode 100644
index 00000000..3672a39d
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TdField.java
@@ -0,0 +1,14 @@
+package cc.iotkit.temporal.td.dm;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TdField {
+ private String name;
+ private String type;
+ private int length;
+}
\ No newline at end of file
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TdResponse.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TdResponse.java
new file mode 100644
index 00000000..033bf387
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TdResponse.java
@@ -0,0 +1,26 @@
+package cc.iotkit.temporal.td.dm;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TdResponse {
+
+ public static final int CODE_SUCCESS = 0;
+ public static final int CODE_TB_NOT_EXIST = 866;
+
+ private String status;
+
+ private int code;
+
+ private String desc;
+
+ //[["time","TIMESTAMP",8,""],["powerstate","TINYINT",1,""],["brightness","INT",4,""],["deviceid","NCHAR",32,"TAG"]]
+ private List data;
+
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TdRestApi.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TdRestApi.java
new file mode 100644
index 00000000..670a8295
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/dm/TdRestApi.java
@@ -0,0 +1,55 @@
+package cc.iotkit.temporal.td.dm;
+
+import cc.iotkit.common.utils.JsonUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+public class TdRestApi {
+
+ @Value("${spring.td-datasource.url}")
+ private String url;
+
+ @Value("${spring.td-datasource.username}")
+ private String username;
+
+ @Value("${spring.td-datasource.password}")
+ private String password;
+
+ private String getRestApiUrl() {
+ //jdbc:TAOS-RS://127.0.0.1:6041/iotkit?xxxx
+ String restUrl = url.replace("jdbc:TAOS-RS://", "")
+ .replaceAll("\\?.*", "");
+ // /rest/sql/iotkit
+ int idx = restUrl.lastIndexOf("/");
+ //127.0.0.1:6041/rest/sql/iotkit
+ return String.format("%s/rest/sql/%s", restUrl.substring(0, idx), restUrl.substring(idx + 1));
+ }
+
+
+ /**
+ * 新建td api请求对象
+ */
+ public HttpRequest newApiRequest(String sql) {
+ return HttpRequest
+ .post(getRestApiUrl())
+ .body(sql)
+ .basicAuth(username, password);
+ }
+
+ /**
+ * 执行sql
+ */
+ public TdResponse execSql(String sql) {
+ log.info("exec td sql:{}", sql);
+ HttpRequest request = newApiRequest(sql);
+ HttpResponse response = request.execute();
+ return JsonUtil.parse(response.body(), TdResponse.class);
+ }
+
+
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbDeviceProperty.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbDeviceProperty.java
new file mode 100644
index 00000000..4b8919df
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbDeviceProperty.java
@@ -0,0 +1,20 @@
+package cc.iotkit.temporal.td.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TbDeviceProperty {
+
+ private Long time;
+
+ private String deviceId;
+
+ private String name;
+
+ private Object value;
+
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbRuleLog.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbRuleLog.java
new file mode 100644
index 00000000..39ea0894
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbRuleLog.java
@@ -0,0 +1,22 @@
+package cc.iotkit.temporal.td.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TbRuleLog {
+
+ private Long time;
+
+ private String ruleId;
+
+ private String state1;
+
+ private String content;
+
+ private Boolean success;
+
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbTaskLog.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbTaskLog.java
new file mode 100644
index 00000000..0b06b38c
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbTaskLog.java
@@ -0,0 +1,20 @@
+package cc.iotkit.temporal.td.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TbTaskLog {
+
+ private Long time;
+
+ private String taskId;
+
+ private String content;
+
+ private Boolean success;
+
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbThingModelMessage.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbThingModelMessage.java
new file mode 100644
index 00000000..4fe56048
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbThingModelMessage.java
@@ -0,0 +1,34 @@
+package cc.iotkit.temporal.td.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TbThingModelMessage {
+
+ private Long time;
+
+ private String mid;
+
+ private String deviceId;
+
+ private String productKey;
+
+ private String deviceName;
+
+ private String uid;
+
+ private String type;
+
+ private String identifier;
+
+ private int code;
+
+ private String data;
+
+ private Long reportTime;
+
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbVirtualDeviceLog.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbVirtualDeviceLog.java
new file mode 100644
index 00000000..5ab72529
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/model/TbVirtualDeviceLog.java
@@ -0,0 +1,22 @@
+package cc.iotkit.temporal.td.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TbVirtualDeviceLog {
+
+ private Long time;
+
+ private String virtualDeviceId;
+
+ private String virtualDeviceName;
+
+ private int deviceTotal;
+
+ private String result;
+
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/service/DbStructureDataImpl.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/service/DbStructureDataImpl.java
new file mode 100644
index 00000000..6a33359c
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/service/DbStructureDataImpl.java
@@ -0,0 +1,164 @@
+package cc.iotkit.temporal.td.service;
+
+import cc.iotkit.common.utils.JsonUtil;
+import cc.iotkit.model.product.ThingModel;
+import cc.iotkit.temporal.IDbStructureData;
+import cc.iotkit.temporal.td.config.Constants;
+import cc.iotkit.temporal.td.dm.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class DbStructureDataImpl implements IDbStructureData {
+
+ @Autowired
+ private TdRestApi tdRestApi;
+
+ /**
+ * 根据物模型创建超级表
+ */
+ @Override
+ public void defineThingModel(ThingModel thingModel) {
+ //获取物模型中的属性定义
+ List fields = FieldParser.parse(thingModel);
+ String tbName = Constants.getProductPropertySTableName(thingModel.getProductKey());
+ //生成sql
+ String sql = TableManager.getCreateSTableSql(tbName,
+ fields,
+ new TdField("device_id", "NCHAR", 50));
+ if (sql == null) {
+ return;
+ }
+ log.info("executing sql:{}", sql);
+
+ //执行sql
+ TdResponse response = tdRestApi.execSql(sql);
+ if (TdResponse.CODE_SUCCESS != response.getCode()) {
+ throw new RuntimeException(String.format(
+ "create td stable failed,code:%s,desc:%s"
+ , response.getCode(), response.getDesc()));
+ }
+ }
+
+ /**
+ * 根据物模型更新超级表结构
+ */
+ @Override
+ public void undefineThingModel(ThingModel thingModel) {
+ //获取旧字段信息
+ String tbName = Constants.getProductPropertySTableName(thingModel.getProductKey());
+ String sql = TableManager.getDescTableSql(tbName);
+ TdResponse response = tdRestApi.execSql(sql);
+ if (response.getCode() != TdResponse.CODE_SUCCESS) {
+ throw new RuntimeException("get des table error:" + JsonUtil.toJsonString(response));
+ }
+
+ List oldFields = FieldParser.parse(response.getData());
+ List newFields = FieldParser.parse(thingModel);
+ //对比差异
+
+ //找出新增的字段
+ List addFields = newFields.stream().filter((f) -> oldFields.stream()
+ .noneMatch(old -> old.getName().equals(f.getName())))
+ .collect(Collectors.toList());
+ if (addFields.size() > 0) {
+ sql = TableManager.getAddSTableColumnSql(tbName, addFields);
+ response = tdRestApi.execSql(sql);
+ if (response.getCode() != TdResponse.CODE_SUCCESS) {
+ throw new RuntimeException("add table column error:" + JsonUtil.toJsonString(response));
+ }
+ }
+
+ //找出修改的字段
+ List modifyFields = newFields.stream().filter((f) -> oldFields.stream()
+ .anyMatch(old ->
+ old.getName().equals(f.getName()) //字段名相同
+ //字段类型或长度不同
+ && (old.getType().equals(f.getType()) || old.getLength() != f.getLength())
+ ))
+ .collect(Collectors.toList());
+
+ if (modifyFields.size() > 0) {
+ sql = TableManager.getModifySTableColumnSql(tbName, modifyFields);
+ response = tdRestApi.execSql(sql);
+ if (response.getCode() != TdResponse.CODE_SUCCESS) {
+ throw new RuntimeException("modify table column error:" + JsonUtil.toJsonString(response));
+ }
+ }
+
+ //找出删除的字段
+ List dropFields = oldFields.stream().filter((f) -> newFields.stream()
+ .noneMatch(old -> old.getName().equals(f.getName())))
+ .collect(Collectors.toList());
+ if (dropFields.size() > 0) {
+ sql = TableManager.getDropSTableColumnSql(tbName, dropFields);
+ response = tdRestApi.execSql(sql);
+ if (response.getCode() != TdResponse.CODE_SUCCESS) {
+ throw new RuntimeException("drop table column error:" + JsonUtil.toJsonString(response));
+ }
+ }
+ }
+
+ /**
+ * 初始化其它数据结构
+ */
+ @Override
+ @PostConstruct
+ public void initDbStructure() {
+ //创建规则日志超级表
+ String sql = TableManager.getCreateSTableSql("rule_log", List.of(
+ new TdField("state1", "NCHAR", 32),
+ new TdField("content", "NCHAR", 255),
+ new TdField("success", "BOOL", -1)
+ ), new TdField("rule_id", "NCHAR", 50));
+ TdResponse response = tdRestApi.execSql(sql);
+ if (response.getCode() != TdResponse.CODE_SUCCESS) {
+ throw new RuntimeException("create stable rule_log error:" + JsonUtil.toJsonString(response));
+ }
+
+ //创建规则日志超级表
+ sql = TableManager.getCreateSTableSql("task_log", List.of(
+ new TdField("content", "NCHAR", 255),
+ new TdField("success", "BOOL", -1)
+ ), new TdField("task_id", "NCHAR", 50));
+ response = tdRestApi.execSql(sql);
+ if (response.getCode() != TdResponse.CODE_SUCCESS) {
+ throw new RuntimeException("create stable task_log error:" + JsonUtil.toJsonString(response));
+ }
+
+ //创建物模型消息超级表
+ sql = TableManager.getCreateSTableSql("thing_model_message", List.of(
+ new TdField("mid", "NCHAR", 50),
+ new TdField("product_key", "NCHAR", 50),
+ new TdField("device_name", "NCHAR", 50),
+ new TdField("uid", "NCHAR", 50),
+ new TdField("type", "NCHAR", 20),
+ new TdField("identifier", "NCHAR", 50),
+ new TdField("code", "INT", -1),
+ new TdField("data", "NCHAR", 255),
+ new TdField("report_time", "BIGINT", -1)
+ ), new TdField("device_id", "NCHAR", 50));
+ response = tdRestApi.execSql(sql);
+ if (response.getCode() != TdResponse.CODE_SUCCESS) {
+ throw new RuntimeException("create stable thing_model_message error:" + JsonUtil.toJsonString(response));
+ }
+
+ //创建虚拟设备日志超级表
+ sql = TableManager.getCreateSTableSql("virtual_device_log", List.of(
+ new TdField("virtual_device_name", "NCHAR", 50),
+ new TdField("device_total", "INT", -1),
+ new TdField("result", "NCHAR", 255)
+ ), new TdField("virtual_device_id", "NCHAR", 50));
+ response = tdRestApi.execSql(sql);
+ if (response.getCode() != TdResponse.CODE_SUCCESS) {
+ throw new RuntimeException("create stable virtual_device_log error:" + JsonUtil.toJsonString(response));
+ }
+
+ }
+}
diff --git a/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/service/DevicePropertyDataImpl.java b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/service/DevicePropertyDataImpl.java
new file mode 100644
index 00000000..0c244b58
--- /dev/null
+++ b/iot-data/iot-td-temporal-service/src/main/java/cc/iotkit/temporal/td/service/DevicePropertyDataImpl.java
@@ -0,0 +1,98 @@
+/*
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 奇特物联 2021-2022 All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed 未经许可不能去掉「奇特物联」相关版权
+ * +----------------------------------------------------------------------
+ * | Author: xw2sy@163.com
+ * +----------------------------------------------------------------------
+ */
+package cc.iotkit.temporal.td.service;
+
+import cc.iotkit.data.IDeviceInfoData;
+import cc.iotkit.model.device.DeviceInfo;
+import cc.iotkit.model.device.message.DeviceProperty;
+import cc.iotkit.temporal.IDevicePropertyData;
+import cc.iotkit.temporal.td.config.Constants;
+import cc.iotkit.temporal.td.dao.TdTemplate;
+import cc.iotkit.temporal.td.model.TbDeviceProperty;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class DevicePropertyDataImpl implements IDevicePropertyData {
+
+ @Autowired
+ private TdTemplate tdTemplate;
+ @Autowired
+ @Qualifier("deviceInfoDataCache")
+ private IDeviceInfoData deviceInfoData;
+
+ public List findDevicePropertyHistory(String deviceId, String name, long start, long end) {
+ DeviceInfo device = deviceInfoData.findByDeviceId(deviceId);
+ if (device == null) {
+ return new ArrayList<>();
+ }
+
+ String tbName = Constants.getProductPropertySTableName(device.getProductKey());
+ List deviceProperties = tdTemplate.query(String.format(
+ "select time,%s as value,device_id from %s where device_id=? and time>=? and time<=?",
+ name.toLowerCase(), tbName),
+ new BeanPropertyRowMapper<>(TbDeviceProperty.class),
+ deviceId, start, end
+ );
+ return deviceProperties.stream().map(p -> new DeviceProperty(
+ p.getTime().toString(),
+ p.getDeviceId(),
+ name,
+ p.getValue(),
+ p.getTime()))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public void addProperties(String deviceId, Map properties, long time) {
+ DeviceInfo device = deviceInfoData.findByDeviceId(deviceId);
+ if (device == null) {
+ return;
+ }
+ //获取设备旧属性
+ Map oldProperties = deviceInfoData.getProperties(deviceId);
+ //用新属性覆盖
+ oldProperties.putAll(properties);
+
+ StringBuilder sbFieldNames = new StringBuilder();
+ StringBuilder sbFieldPlaces = new StringBuilder();
+ List