diff --git a/README.md b/README.md
index 5bbaed04..2ee2713e 100644
--- a/README.md
+++ b/README.md
@@ -75,6 +75,8 @@
* [Mqtt消息服务器EMQX4.0](https://github.com/emqx/emqx)
* [ESP8266 Core For Arduino](https://github.com/esp8266/Arduino)
* [uCharts高性能跨平台图表库](https://www.ucharts.cn)
+* [TDengine时序数据库](https://www.taosdata.com/?zh)
+
##### Docker快速安装
* Mysql中创建wumei-smart数据库,[导入Sql脚本](https://gitee.com/kerwincui/wumei-smart/tree/master/springboot/sql)
* 修改命令中的Mysql配置,并执行
@@ -110,6 +112,9 @@ kerwincui/wumei-smart:1.1
| [SXH](https://gitee.com/sixiaohu) | [Redamancy_zxp](https://gitee.com/redamancy-zxp) | [LEE](https://gitee.com/yueming188) | [LemonTree](https://gitee.com/fishhunterplus) | [Tang](https://gitee.com/mexiaotang)
|--|--|--|--|--|
+| [xxmfl](https://gitee.com/xxmfl) |
+|--|
+
### 九、部分图片
diff --git a/springboot/wumei-admin/src/main/resources/application-druid.yml b/springboot/wumei-admin/src/main/resources/application-druid.yml
index 9578e066..f8135ae5 100644
--- a/springboot/wumei-admin/src/main/resources/application-druid.yml
+++ b/springboot/wumei-admin/src/main/resources/application-druid.yml
@@ -16,6 +16,17 @@ spring:
url:
username:
password:
+
+ # TDengine数据库
+ tdengine-server:
+ # 默认不启用TDengine,true=启用,false=不启用
+ enabled: false
+ driverClassName: com.taosdata.jdbc.TSDBDriver
+ url: jdbc:TAOS://127.0.0.1:6030/wumei_smart_log?timezone=Asia/Beijing&charset=utf-8
+ username: root
+ password: taosdata
+ dbName: wumei_smart_log
+
# 初始连接数
initialSize: 5
# 最小连接池数量
diff --git a/springboot/wumei-admin/src/main/resources/application.yml b/springboot/wumei-admin/src/main/resources/application.yml
index a99c9bb5..60297c88 100644
--- a/springboot/wumei-admin/src/main/resources/application.yml
+++ b/springboot/wumei-admin/src/main/resources/application.yml
@@ -8,7 +8,7 @@ ruoyi:
copyrightYear: 2021
# 实例演示开关
demoEnabled: true
- # 文件路径 示例( Windows配置D:/wumei-smart/uploadPath,Linux配置 /var/wumei-smart/java/uploadPath)
+ # 文件路径,以uploadPath结尾 示例( Windows配置D:/wumei-smart/uploadPath,Linux配置 /var/wumei-smart/java/uploadPath)
profile: /var/wumei-smart/java/uploadPath
# 获取ip地址开关
addressEnabled: true
diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java
index 057c9419..56463e7a 100644
--- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java
+++ b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java
@@ -9,10 +9,13 @@ import javax.sql.DataSource;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
@@ -21,12 +24,13 @@ import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.util.ClassUtils;
import com.ruoyi.common.utils.StringUtils;
/**
* Mybatis支持*匹配扫描包
- *
+ *
* @author ruoyi
*/
@Configuration
@@ -113,7 +117,8 @@ public class MyBatisConfig
return resources.toArray(new Resource[resources.size()]);
}
- @Bean
+ @Bean(name = "mysqlSessionFactory")
+ @Primary
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
{
String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
@@ -129,4 +134,16 @@ public class MyBatisConfig
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
return sessionFactory.getObject();
}
+
+ @Bean(name = "mysqlTransactionManager")
+ @Primary
+ public DataSourceTransactionManager mysqlTransactionManager(@Qualifier("dynamicDataSource") DataSource dataSource) {
+ return new DataSourceTransactionManager(dataSource);
+ }
+
+ @Bean(name = "mysqlSqlSessionTemplate")
+ @Primary
+ public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
+ return new SqlSessionTemplate(sqlSessionFactory);
+ }
}
\ No newline at end of file
diff --git a/springboot/wumei-iot/pom.xml b/springboot/wumei-iot/pom.xml
index f0d12628..c716b72a 100644
--- a/springboot/wumei-iot/pom.xml
+++ b/springboot/wumei-iot/pom.xml
@@ -89,6 +89,15 @@
+
+
+ com.taosdata.jdbc
+ taos-jdbcdriver
+ 2.0.38
+
+
+
+
\ No newline at end of file
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceLog.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceLog.java
index b2909ef8..83f9c7c8 100644
--- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceLog.java
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/DeviceLog.java
@@ -5,9 +5,11 @@ import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
+import java.util.Date;
+
/**
* 设备日志对象 iot_device_log
- *
+ *
* @author kerwincui
* @date 2022-01-13
*/
@@ -15,6 +17,8 @@ public class DeviceLog extends BaseEntity
{
private static final long serialVersionUID = 1L;
+ @Excel(name = "时间戳")
+ private Date ts;
/** 设备日志ID */
private Long logId;
@@ -46,6 +50,15 @@ public class DeviceLog extends BaseEntity
@Excel(name = "是否监测数据", readConverterExp = "1==是,0=否")
private Integer isMonitor;
+
+ public Date getTs() {
+ return ts;
+ }
+
+ public void setTs(Date ts) {
+ this.ts = ts;
+ }
+
public String getSerialNumber() {
return serialNumber;
}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceLogMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceLogMapper.java
index 619d0d57..73b66fc9 100644
--- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceLogMapper.java
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/DeviceLogMapper.java
@@ -4,11 +4,12 @@ import com.ruoyi.iot.domain.DeviceLog;
import com.ruoyi.iot.model.MonitorModel;
import org.springframework.stereotype.Repository;
+import java.util.Date;
import java.util.List;
/**
* 设备日志Mapper接口
- *
+ *
* @author kerwincui
* @date 2022-01-13
*/
@@ -17,7 +18,7 @@ public interface DeviceLogMapper
{
/**
* 查询设备日志
- *
+ *
* @param logId 设备日志主键
* @return 设备日志
*/
@@ -25,7 +26,7 @@ public interface DeviceLogMapper
/**
* 查询设备日志列表
- *
+ *
* @param deviceLog 设备日志
* @return 设备日志集合
*/
@@ -41,7 +42,7 @@ public interface DeviceLogMapper
/**
* 新增设备日志
- *
+ *
* @param deviceLog 设备日志
* @return 结果
*/
@@ -49,7 +50,7 @@ public interface DeviceLogMapper
/**
* 修改设备日志
- *
+ *
* @param deviceLog 设备日志
* @return 结果
*/
@@ -57,7 +58,7 @@ public interface DeviceLogMapper
/**
* 删除设备日志
- *
+ *
* @param logId 设备日志主键
* @return 结果
*/
@@ -65,7 +66,7 @@ public interface DeviceLogMapper
/**
* 批量删除设备日志
- *
+ *
* @param logIds 需要删除的数据主键集合
* @return 结果
*/
@@ -78,4 +79,7 @@ public interface DeviceLogMapper
* @return 结果
*/
public int deleteDeviceLogByDeviceIds(Long[] deviceIds);
+
+
+// List selectLogList(Long deviceId,String serialNumber,Long isMonitor,Long logType, Date beginDate, Date endDate);
}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxService.java
index 98de2000..bca6e263 100644
--- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxService.java
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mqtt/EmqxService.java
@@ -10,6 +10,7 @@ import com.ruoyi.iot.model.ThingsModels.ThingsModelValueRemarkItem;
import com.ruoyi.iot.model.ThingsModels.ThingsModelValuesInput;
import com.ruoyi.iot.service.IDeviceLogService;
import com.ruoyi.iot.service.IDeviceService;
+import com.ruoyi.iot.tdengine.service.ILogService;
import org.eclipse.paho.client.mqttv3.MqttAsyncClient;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
@@ -32,8 +33,11 @@ public class EmqxService {
@Autowired
private IDeviceService deviceService;
+// @Autowired
+// private IDeviceLogService deviceLogService;
+
@Autowired
- private IDeviceLogService deviceLogService;
+ private ILogService logService;
/**
* 订阅的主题
@@ -190,7 +194,8 @@ public class EmqxService {
deviceLog.setIdentity(thingsModelValueRemarkItems.get(i).getId());
deviceLog.setLogType(3);
deviceLog.setIsMonitor(0);
- deviceLogService.insertDeviceLog(deviceLog);
+// deviceLogService.insertDeviceLog(deviceLog);
+ logService.saveDeviceLog(deviceLog);
}
} catch (Exception e) {
logger.error("接收事件,解析数据时异常 message={}", e.getMessage());
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceLogServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceLogServiceImpl.java
index c0fbd020..54a9ef64 100644
--- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceLogServiceImpl.java
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceLogServiceImpl.java
@@ -2,6 +2,7 @@ package com.ruoyi.iot.service.impl;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.iot.domain.DeviceLog;
+import com.ruoyi.iot.tdengine.service.ILogService;
import com.ruoyi.iot.mapper.DeviceLogMapper;
import com.ruoyi.iot.model.MonitorModel;
import com.ruoyi.iot.service.IDeviceLogService;
@@ -22,6 +23,9 @@ public class DeviceLogServiceImpl implements IDeviceLogService
@Autowired
private DeviceLogMapper deviceLogMapper;
+ @Autowired
+ private ILogService logService;
+
/**
* 查询设备日志
*
@@ -43,7 +47,8 @@ public class DeviceLogServiceImpl implements IDeviceLogService
@Override
public List selectDeviceLogList(DeviceLog deviceLog)
{
- return deviceLogMapper.selectDeviceLogList(deviceLog);
+// deviceLogMapper.selectDeviceLogList(deviceLog);
+ return logService.selectDeviceLogList(deviceLog);
}
/**
@@ -55,7 +60,8 @@ public class DeviceLogServiceImpl implements IDeviceLogService
@Override
public List selectMonitorList(DeviceLog deviceLog)
{
- return deviceLogMapper.selectMonitorList(deviceLog);
+// return deviceLogMapper.selectMonitorList(deviceLog);
+ return logService.selectMonitorList(deviceLog);
}
/**
@@ -68,7 +74,8 @@ public class DeviceLogServiceImpl implements IDeviceLogService
public int insertDeviceLog(DeviceLog deviceLog)
{
deviceLog.setCreateTime(DateUtils.getNowDate());
- return deviceLogMapper.insertDeviceLog(deviceLog);
+// return deviceLogMapper.insertDeviceLog(deviceLog);
+ return logService.saveDeviceLog(deviceLog);
}
/**
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceServiceImpl.java
index 91235878..26f52715 100644
--- a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceServiceImpl.java
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/DeviceServiceImpl.java
@@ -11,13 +11,13 @@ import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.iot.domain.Device;
import com.ruoyi.iot.domain.DeviceLog;
import com.ruoyi.iot.domain.Product;
+import com.ruoyi.iot.tdengine.service.ILogService;
import com.ruoyi.iot.mapper.DeviceLogMapper;
import com.ruoyi.iot.mapper.DeviceMapper;
import com.ruoyi.iot.mapper.DeviceUserMapper;
import com.ruoyi.iot.model.*;
import com.ruoyi.iot.model.ThingsModelItem.*;
import com.ruoyi.iot.model.ThingsModels.*;
-import com.ruoyi.iot.service.IDeviceLogService;
import com.ruoyi.iot.service.IDeviceService;
import com.ruoyi.iot.service.IProductService;
import com.ruoyi.iot.service.IToolService;
@@ -73,8 +73,11 @@ public class DeviceServiceImpl implements IDeviceService {
@Autowired
private ISysUserService userService;
+// @Autowired
+// private IDeviceLogService deviceLogService;
+
@Autowired
- private IDeviceLogService deviceLogService;
+ private ILogService logService;
/**
* 查询设备
@@ -196,7 +199,8 @@ public class DeviceServiceImpl implements IDeviceService {
deviceLog.setCreateTime(DateUtils.getNowDate());
deviceLog.setIsMonitor(valueList.get(k).getIsMonitor());
deviceLog.setLogType(type);
- deviceLogMapper.insertDeviceLog(deviceLog);
+ logService.saveDeviceLog(deviceLog);
+// deviceLogMapper.insertDeviceLog(deviceLog);
break;
}
}
@@ -591,7 +595,8 @@ public class DeviceServiceImpl implements IDeviceService {
deviceLog.setIdentity("offline");
deviceLog.setLogType(6);
}
- deviceLogService.insertDeviceLog(deviceLog);
+ logService.saveDeviceLog(deviceLog);
+// deviceLogService.insertDeviceLog(deviceLog);
return result;
}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/config/TDengineConfig.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/config/TDengineConfig.java
new file mode 100644
index 00000000..c71a0812
--- /dev/null
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/config/TDengineConfig.java
@@ -0,0 +1,93 @@
+package com.ruoyi.iot.tdengine.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.ruoyi.common.utils.StringUtils;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+
+import javax.sql.DataSource;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 类名: TDengineConfig
+ * 描述: TDengine配置类
+ * 时间: 2022/5/13,0016 1:14
+ * 开发人: wxy
+ */
+@Configuration
+@MapperScan(basePackages = {"com.ruoyi.iot.tdengine.dao"}, sqlSessionTemplateRef = "tdengineSqlSessionTemplate")
+@ConditionalOnProperty(name = "spring.datasource.druid.tdengine-server.enabled", havingValue = "true")
+public class TDengineConfig {
+
+ @Value("${spring.datasource.druid.tdengine-server.dbName}")
+ private String dbName;
+
+
+ @Bean(name = "tDengineDataSource")
+ @ConfigurationProperties(prefix = "spring.datasource.druid.tdengine-server")
+ public DataSource tdengineDataSource() {
+ return new DruidDataSource();
+ }
+
+
+
+ @Bean(name = "tDengineSqlSessionFactory")
+ public SqlSessionFactory tDengineSqlSessionFactory(@Qualifier("tDengineDataSource") DataSource dataSource) throws Exception {
+ SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
+ sqlSessionFactoryBean.setMapperLocations(resolveMapperLocations(StringUtils.split("classpath:mapper/tdengine/*Mapper.xml", ",")));
+ sqlSessionFactoryBean.setDataSource(dataSource);
+ return sqlSessionFactoryBean.getObject();
+ }
+
+
+ @Bean(name = "tdengineSqlSessionTemplate")
+ public SqlSessionTemplate tdengineSqlSessionTemplate(@Qualifier("tDengineSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
+ return new SqlSessionTemplate(sqlSessionFactory);
+ }
+
+ public String getDbName() {
+ return dbName;
+ }
+
+ public void setDbName(String dbName) {
+ this.dbName = dbName;
+ }
+ public Resource[] resolveMapperLocations(String[] mapperLocations)
+ {
+ ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
+ List resources = new ArrayList();
+ if (mapperLocations != null)
+ {
+ for (String mapperLocation : mapperLocations)
+ {
+ try
+ {
+ Resource[] mappers = resourceResolver.getResources(mapperLocation);
+ resources.addAll(Arrays.asList(mappers));
+ }
+ catch (IOException e)
+ {
+ // ignore
+ }
+ }
+ }
+ return resources.toArray(new Resource[resources.size()]);
+ }
+
+
+}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/dao/DatabaseDAO.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/dao/DatabaseDAO.java
new file mode 100644
index 00000000..3044d692
--- /dev/null
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/dao/DatabaseDAO.java
@@ -0,0 +1,25 @@
+package com.ruoyi.iot.tdengine.dao;
+
+import org.springframework.stereotype.Repository;
+
+/**
+ * @package com.ruoyi.mysql.mysql.tdengine
+ * 类名: DatabaseMapper
+ * 描述: TODO
+ * 时间: 2022/5/16,0016 1:27
+ * 开发人: wxy
+ */
+@Repository
+public interface DatabaseDAO {
+
+ int createDB();
+
+ int dropDatabase();
+
+ int useDatabase();
+
+ int createTable();
+
+
+
+}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/dao/TDDeviceLogDAO.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/dao/TDDeviceLogDAO.java
new file mode 100644
index 00000000..b4907756
--- /dev/null
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/dao/TDDeviceLogDAO.java
@@ -0,0 +1,41 @@
+package com.ruoyi.iot.tdengine.dao;
+
+import com.ruoyi.iot.domain.DeviceLog;
+import com.ruoyi.iot.model.MonitorModel;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @package com.ruoyi.mysql.mysql.tdengine
+ * 类名: DatabaseMapper
+ * 描述: TODO
+ * 时间: 2022/5/16,0016 1:27
+ * 开发人: wxy
+ */
+@Repository
+public interface TDDeviceLogDAO {
+
+
+ int createDB( String database);
+
+ int createSTable(String database);
+
+ int createTable(String database,String deviceId);
+
+ int save(@Param("database") String database,@Param("device") DeviceLog deviceLog);
+
+ List selectSTable(String database,DeviceLog deviceLog);
+
+ int delete(String dbName, DeviceLog deviceLog);
+
+// List selectLogListByPage(String dbName, Integer pageSize, Integer pageNum, String deviceNum, Date beginDate, Date endDate);
+
+ List selectLogList(String dbName, Long deviceId, String serialNumber, Long isMonitor, Long logType, Date beginDate, Date endDate);
+
+ List selectMonitorList(@Param("database") String database, @Param("device") DeviceLog deviceLog);
+
+ List selectDeviceLogList(@Param("database") String database,@Param("device") DeviceLog deviceLog);
+}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/init/ApplicationStarted.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/init/ApplicationStarted.java
new file mode 100644
index 00000000..7d38f986
--- /dev/null
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/init/ApplicationStarted.java
@@ -0,0 +1,79 @@
+package com.ruoyi.iot.tdengine.init;
+
+
+import com.ruoyi.iot.tdengine.config.TDengineConfig;
+import com.ruoyi.iot.tdengine.dao.TDDeviceLogDAO;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.context.ApplicationContext;
+import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Component;
+
+/**
+ * 类名: ApplicationStarted
+ * 描述: TODO
+ * 时间: 2022/5/18,0018 1:41
+ * 开发人: wxy
+ */
+@Component
+public class ApplicationStarted implements ApplicationRunner {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationStarted.class);
+
+ @Autowired
+ private ApplicationContext applicationContext;
+
+ @Override
+ public void run(ApplicationArguments args) {
+ //先获取TDengine的配置,检测TDengine是否已经配置
+ if (containBean(TDengineConfig.class)) {
+ TDengineConfig tDengineConfig = applicationContext.getBean(TDengineConfig.class);
+ TDDeviceLogDAO tDDeviceLogDAO = applicationContext.getBean(TDDeviceLogDAO.class);
+ initTDengine(tDengineConfig, tDDeviceLogDAO);
+ LOGGER.info("使用TDengine存储设备数据,初始化成功");
+ }else{
+ LOGGER.info("使用MySql存储设备数据,初始化成功");
+ }
+ }
+
+ /**
+ * @return
+ * @Method
+ * @Description 开始初始化加载系统参数, 创建数据库和超级表
+ * @Param null
+ * @date 2022/5/22,0022 14:27
+ * @author wxy
+ */
+ public void initTDengine(TDengineConfig dengineConfig, TDDeviceLogDAO deviceLogMapper) {
+ try {
+ String dbName = dengineConfig.getDbName();
+ // TODO 目前还不支持自动创建数据库
+ int db = deviceLogMapper.createDB(dbName);
+ deviceLogMapper.createSTable(dbName);
+ } catch (Exception e) {
+ LOGGER.info("错误",e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * @return
+ * @Method containBean
+ * @Description 根据类判断是否有对应bean
+ * @Param 类
+ * @date 2022/5/22,0022 14:12
+ * @author wxy
+ */
+ private boolean containBean(@Nullable Class> T) {
+ String[] beans = applicationContext.getBeanNamesForType(T);
+ if (beans == null || beans.length == 0) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/ILogService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/ILogService.java
new file mode 100644
index 00000000..f775ade5
--- /dev/null
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/ILogService.java
@@ -0,0 +1,25 @@
+package com.ruoyi.iot.tdengine.service;
+
+import com.ruoyi.iot.domain.DeviceLog;
+
+import com.ruoyi.iot.model.MonitorModel;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @package iot.iot.log
+ * 类名: LogService
+ * 描述: 设备日志记录接口
+ * 时间: 2022/5/19,0019 18:04
+ * 开发人: admin
+ */
+public interface ILogService {
+
+ int saveDeviceLog(DeviceLog deviceLog);
+
+ List selectDeviceLogList(DeviceLog deviceLog);
+
+ List selectMonitorList(DeviceLog deviceLog);
+}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/factory/LogServiceFactory.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/factory/LogServiceFactory.java
new file mode 100644
index 00000000..49500315
--- /dev/null
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/factory/LogServiceFactory.java
@@ -0,0 +1,63 @@
+package com.ruoyi.iot.tdengine.service.factory;
+
+import com.ruoyi.framework.config.MyBatisConfig;
+import com.ruoyi.iot.tdengine.service.impl.MySqlLogServiceImpl;
+import com.ruoyi.iot.tdengine.service.impl.TdengineLogServiceImpl;
+import com.ruoyi.iot.tdengine.config.TDengineConfig;
+import com.ruoyi.iot.tdengine.service.ILogService;
+import com.ruoyi.iot.mapper.DeviceLogMapper;
+import com.ruoyi.iot.tdengine.dao.TDDeviceLogDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Component;
+
+/**
+ * 类名: DeviceLogServiceImpl
+ * 描述: TODO
+ * 时间: 2022/5/19,0019 18:09
+ * 开发人: wxy
+ */
+@Component
+public class LogServiceFactory {
+
+ @Autowired
+ private ApplicationContext applicationContext;
+
+ @Bean
+ public ILogService getLogService() {
+ //先获取TDengine的配置,检测TDengine是否已经配置
+ if (containBean(TDengineConfig.class)) {
+ TDengineConfig tDengineConfig = applicationContext.getBean(TDengineConfig.class);
+ TDDeviceLogDAO tDDeviceLogDAO = applicationContext.getBean(TDDeviceLogDAO.class);
+ ILogService logService = new TdengineLogServiceImpl(tDengineConfig, tDDeviceLogDAO);
+ return logService;
+ } else if (containBean(MyBatisConfig.class)) {
+ //没有配置TDengine,那么使用MySQL的日志配置
+ DeviceLogMapper deviceLogMapper = applicationContext.getBean( DeviceLogMapper.class);
+ ILogService logService = new MySqlLogServiceImpl(deviceLogMapper);
+ return logService;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @Method containBean
+ * @Description 根据类判断是否有对应bean
+ * @Param 类
+ * @return
+ * @date 2022/5/22,0022 14:12
+ * @author wxy
+ *
+ */
+ private boolean containBean(@Nullable Class> T) {
+ String[] beans = applicationContext.getBeanNamesForType(T);
+ if (beans == null || beans.length == 0) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/MySqlLogServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/MySqlLogServiceImpl.java
new file mode 100644
index 00000000..ecd4719b
--- /dev/null
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/MySqlLogServiceImpl.java
@@ -0,0 +1,37 @@
+package com.ruoyi.iot.tdengine.service.impl;
+
+import com.ruoyi.iot.domain.DeviceLog;
+import com.ruoyi.iot.tdengine.service.ILogService;
+import com.ruoyi.iot.mapper.DeviceLogMapper;
+import com.ruoyi.iot.model.MonitorModel;
+
+import java.util.List;
+
+/**
+ * 类名: MySqlLogServiceImpl
+ * 描述: MySQL存储日志实现类
+ * 时间: 2022/5/22,0022 13:37
+ * 开发人: admin
+ */
+public class MySqlLogServiceImpl implements ILogService {
+
+ private DeviceLogMapper deviceLogMapper;
+
+ public MySqlLogServiceImpl(DeviceLogMapper _deviceLogMapper){
+ this.deviceLogMapper=_deviceLogMapper;
+ }
+ @Override
+ public int saveDeviceLog(DeviceLog deviceLog) {
+ return deviceLogMapper.insertDeviceLog(deviceLog);
+ }
+
+ @Override
+ public List selectDeviceLogList(DeviceLog deviceLog) {
+ return deviceLogMapper.selectDeviceLogList(deviceLog);
+ }
+
+ @Override
+ public List selectMonitorList(DeviceLog deviceLog) {
+ return deviceLogMapper.selectMonitorList(deviceLog);
+ }
+}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/TdengineLogServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/TdengineLogServiceImpl.java
new file mode 100644
index 00000000..01322450
--- /dev/null
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/tdengine/service/impl/TdengineLogServiceImpl.java
@@ -0,0 +1,54 @@
+package com.ruoyi.iot.tdengine.service.impl;
+
+import com.ruoyi.iot.domain.DeviceLog;
+import com.ruoyi.iot.tdengine.service.ILogService;
+import com.ruoyi.iot.model.MonitorModel;
+import com.ruoyi.iot.tdengine.config.TDengineConfig;
+import com.ruoyi.iot.tdengine.dao.TDDeviceLogDAO;
+import com.ruoyi.iot.util.SnowflakeIdWorker;
+import org.springframework.context.ApplicationContext;
+
+import java.util.List;
+
+/**
+ * 类名: TdengineLogServiceImpl
+ * 描述: TDengine存储日志数据实现类
+ * 时间: 2022/5/22,0022 13:38
+ * 开发人: admin
+ */
+public class TdengineLogServiceImpl implements ILogService {
+
+ private ApplicationContext applicationContext;
+
+ private TDDeviceLogDAO tdDeviceLogDAO;
+
+ private TDengineConfig tDengineConfig;
+
+ private SnowflakeIdWorker snowflakeIdWorker;
+
+ private String dbName;
+
+ public TdengineLogServiceImpl(TDengineConfig _tDengineConfig, TDDeviceLogDAO _tdDeviceLogDAO) {
+ this.tdDeviceLogDAO = _tdDeviceLogDAO;
+ this.tDengineConfig = _tDengineConfig;
+ snowflakeIdWorker=new SnowflakeIdWorker(1);
+ this.dbName=_tDengineConfig.getDbName();
+ }
+
+ @Override
+ public int saveDeviceLog(DeviceLog deviceLog) {
+ long logId = snowflakeIdWorker.nextId();
+ deviceLog.setLogId(logId);
+ return tdDeviceLogDAO.save(dbName,deviceLog);
+ }
+
+ @Override
+ public List selectDeviceLogList(DeviceLog deviceLog) {
+ return tdDeviceLogDAO.selectDeviceLogList(dbName,deviceLog);
+ }
+
+ @Override
+ public List selectMonitorList(DeviceLog deviceLog) {
+ return tdDeviceLogDAO.selectMonitorList(dbName,deviceLog);
+ }
+}
diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/SnowflakeIdWorker.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/SnowflakeIdWorker.java
new file mode 100644
index 00000000..ff5a11d3
--- /dev/null
+++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/util/SnowflakeIdWorker.java
@@ -0,0 +1,104 @@
+package com.ruoyi.iot.util;
+
+public class SnowflakeIdWorker {
+ /**
+ * 开始时间:2020-01-01 00:00:00
+ */
+ private final long beginTs = 1577808000000L;
+
+ private final long workerIdBits = 10;
+
+ /**
+ * 2^10 - 1 = 1023
+ */
+ private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+ private final long sequenceBits = 12;
+
+ /**
+ * 2^12 - 1 = 4095
+ */
+ private final long maxSequence = -1L ^ (-1L << sequenceBits);
+
+ /**
+ * 时间戳左移22位
+ */
+ private final long timestampLeftOffset = workerIdBits + sequenceBits;
+
+ /**
+ * 业务ID左移12位
+ */
+ private final long workerIdLeftOffset = sequenceBits;
+
+ /**
+ * 合并了机器ID和数据标示ID,统称业务ID,10位
+ */
+ private long workerId;
+
+ /**
+ * 毫秒内序列,12位,2^12 = 4096个数字
+ */
+ private long sequence = 0L;
+
+ /**
+ * 上一次生成的ID的时间戳,同一个worker中
+ */
+ private long lastTimestamp = -1L;
+
+ public SnowflakeIdWorker(long workerId) {
+ if (workerId > maxWorkerId || workerId < 0) {
+ throw new IllegalArgumentException(String.format("WorkerId必须大于或等于0且小于或等于%d", maxWorkerId));
+ }
+
+ this.workerId = workerId;
+ }
+
+ public synchronized long nextId() {
+ long ts = System.currentTimeMillis();
+ if (ts < lastTimestamp) {
+ throw new RuntimeException(String.format("系统时钟回退了%d毫秒", (lastTimestamp - ts)));
+ }
+
+ // 同一时间内,则计算序列号
+ if (ts == lastTimestamp) {
+ // 序列号溢出
+ if (++sequence > maxSequence) {
+ ts = tilNextMillis(lastTimestamp);
+ sequence = 0L;
+ }
+ } else {
+ // 时间戳改变,重置序列号
+ sequence = 0L;
+ }
+
+ lastTimestamp = ts;
+
+ // 0 - 00000000 00000000 00000000 00000000 00000000 0 - 00000000 00 - 00000000 0000
+ // 左移后,低位补0,进行按位或运算相当于二进制拼接
+ // 本来高位还有个0<<63,0与任何数字按位或都是本身,所以写不写效果一样
+ return (ts - beginTs) << timestampLeftOffset | workerId << workerIdLeftOffset | sequence;
+ }
+
+ /**
+ * 阻塞到下一个毫秒
+ *
+ * @param lastTimestamp
+ * @return
+ */
+ private long tilNextMillis(long lastTimestamp) {
+ long ts = System.currentTimeMillis();
+ while (ts <= lastTimestamp) {
+ ts = System.currentTimeMillis();
+ }
+
+ return ts;
+ }
+
+ public static void main(String[] args) {
+ SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(7);
+ for (int i = 0; i < 10; i++) {
+ long id = snowflakeIdWorker.nextId();
+ System.out.println(id);
+ }
+ }
+}
\ No newline at end of file
diff --git a/springboot/wumei-iot/src/main/resources/mapper/tdengine/DatabaseMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/tdengine/DatabaseMapper.xml
new file mode 100644
index 00000000..f5a6853a
--- /dev/null
+++ b/springboot/wumei-iot/src/main/resources/mapper/tdengine/DatabaseMapper.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+ create database if not exists ${dbName};
+
+
+
+
+ DROP database if exists ${dbName};
+
+
+
+
+ use ${dbName};
+
+
+
+ create stable if not exists ${tableName}
+ (ts timestamp,
+ log_id BIGINT,
+ identity NCHAR(100),
+ log_type NCHAR(20),
+ log_value NCHAR(100),
+ device_id BIGINT,
+ device_name NCHAR(100),
+ serial_number NCHAR(100),
+ is_monitor int,
+ create_by NCHAR(100),
+ create_time timestamp,
+ remark NCHAR(1000),
+ );
+
+
+
+
\ No newline at end of file
diff --git a/springboot/wumei-iot/src/main/resources/mapper/tdengine/TDDeviceLogMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/tdengine/TDDeviceLogMapper.xml
new file mode 100644
index 00000000..1bf0071b
--- /dev/null
+++ b/springboot/wumei-iot/src/main/resources/mapper/tdengine/TDDeviceLogMapper.xml
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ create database if not exists ${database};
+
+
+
+
+ create STABLE if not exists ${database}.device_log
+ (
+ ts timestamp,
+ log_id BIGINT,
+ log_type TINYINT,
+ `identity` BINARY(100),
+ `log_value` BINARY(100),
+ is_monitor TINYINT,
+ create_by BINARY(100),
+ create_time timestamp,
+ remark BINARY(500)
+
+ )
+ TAGS(
+ device_id BIGINT,
+ device_name BINARY(100),
+ serial_number BINARY(50));
+
+
+
+ create TABLE if not exists ${database}.${tableName}
+ USING ${database}.device_${deviceId} TAGS(log_type,is_monitor,create_by,create_time,remark)
+ (ts2 timestamp,
+ log_type BINARY(100)
+ );
+
+
+
+
+
+ INSERT INTO ${database}.device_${device.serialNumber} USING device_log
+ TAGS (#{device.deviceId},#{device.deviceName},#{device.serialNumber})
+ VALUES (now, #{device.logId}, #{device.logType},#{device.identity},#{device.logValue},#{device.isMonitor},#{device.createBy},now,#{device.remark} );
+
+
+
+ delete from ${database}.device_${device.serialNumber}
+
+
+ log_id = #{logId}
+
+
+ device_id = #{deviceId}
+
+
+ serial_number = #{serialNumber}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file