From 1d92915d0a858a43677a4c7d0d67795e043d2b43 Mon Sep 17 00:00:00 2001
From: CoderSilence <592486805@qq.com>
Date: 星期一, 31 三月 2025 14:59:45 +0800
Subject: [PATCH] first commit

---
 .gitignore                                                      |   52 +
 src/main/resources/mybatis/mybatis-config.xml                   |   20 
 src/main/java/com/zhitan/config/influxdb/InfluxdbConfig.java    |   17 
 src/main/java/com/zhitan/MQTTGatewayApplication.java            |   17 
 src/main/java/com/zhitan/config/DruidConfig.java                |   82 +++
 pom.xml                                                         |  143 ++++++
 src/main/java/com/zhitan/mapper/CommonMapper.java               |   17 
 src/main/java/com/zhitan/model/entity/ElectricPower.java        |   84 +++
 src/main/java/com/zhitan/config/mqtt/MqttConfig.java            |   42 +
 src/main/java/com/zhitan/config/properties/DruidProperties.java |   89 ++++
 src/main/java/com/zhitan/service/IDataService.java              |   24 +
 src/main/resources/mapper/CommonMapper.xml                      |   11 
 src/main/java/com/zhitan/model/IndexTemplate.java               |   26 +
 src/main/java/com/zhitan/influxdb/InfluxdbRepository.java       |   76 +++
 src/main/java/com/zhitan/redis/RedisCache.java                  |  183 ++++++++
 src/main/resources/application-dev.yml                          |   78 +++
 src/main/java/com/zhitan/config/mqtt/MqttInboundConfig.java     |   44 ++
 src/main/java/com/zhitan/config/redis/RedisConfig.java          |   42 +
 src/main/java/com/zhitan/service/impl/DataServiceImpl.java      |  133 ++++++
 src/main/java/com/zhitan/config/mybatis/MyBatisPlusConfig.java  |   44 ++
 src/main/resources/application.yml                              |   24 +
 src/main/java/com/zhitan/handler/MqttMessageHandler.java        |   40 +
 22 files changed, 1,269 insertions(+), 19 deletions(-)

diff --git a/.gitignore b/.gitignore
index 524f096..5ff6309 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,24 +1,38 @@
-# Compiled class file
-*.class
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
 
-# Log file
-*.log
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
 
-# BlueJ files
-*.ctxt
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
 
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
 
-# Package Files #
-*.jar
-*.war
-*.nar
-*.ear
-*.zip
-*.tar.gz
-*.rar
+### VS Code ###
+.vscode/
 
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
-replay_pid*
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..9ccc7d2
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.zhitan</groupId>
+    <artifactId>MQTTGateway</artifactId>
+    <version>1.0</version>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.6.15</version>
+    </parent>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <integration.version>3.4.3</integration.version>
+        <druid.version>1.2.20</druid.version>
+        <mybatis-plus.version>3.5.6</mybatis-plus.version>
+        <influxdb-client.version>6.6.0</influxdb-client.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                    <groupId>org.springframework.boot</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.integration</groupId>
+            <artifactId>spring-integration-mqtt</artifactId>
+        </dependency>
+        <!-- 闃块噷鏁版嵁搴撹繛鎺ユ睜 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+            <version>${druid.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>${mybatis-plus.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.influxdb</groupId>
+            <artifactId>influxdb-client-java</artifactId>
+            <version>${influxdb-client.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains.kotlin</groupId>
+            <artifactId>kotlin-stdlib</artifactId>
+            <version>1.8.20</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains</groupId>
+            <artifactId>annotations</artifactId>
+            <version>26.0.2</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+
+    <repositories>
+        <repository>
+            <id>central</id>
+            <url>https://maven.aliyun.com/repository/central</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>ali-public</id>
+            <name>ali-public</name>
+            <url>https://maven.aliyun.com/repository/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.5.15</version>
+                <configuration>
+                    <fork>true</fork> <!-- 濡傛灉娌℃湁璇ラ厤缃紝devtools涓嶄細鐢熸晥 -->
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/src/main/java/com/zhitan/MQTTGatewayApplication.java b/src/main/java/com/zhitan/MQTTGatewayApplication.java
new file mode 100644
index 0000000..e24a8ff
--- /dev/null
+++ b/src/main/java/com/zhitan/MQTTGatewayApplication.java
@@ -0,0 +1,17 @@
+package com.zhitan;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * application
+ */
+@SpringBootApplication
+@MapperScan(basePackages = {"com.zhitan.mapper"})
+public class MQTTGatewayApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(MQTTGatewayApplication.class, args);
+        System.out.println("MQTT Gateway Application Started");
+    }
+}
diff --git a/src/main/java/com/zhitan/config/DruidConfig.java b/src/main/java/com/zhitan/config/DruidConfig.java
new file mode 100644
index 0000000..4c29a94
--- /dev/null
+++ b/src/main/java/com/zhitan/config/DruidConfig.java
@@ -0,0 +1,82 @@
+package com.zhitan.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
+import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
+import com.alibaba.druid.util.Utils;
+import com.zhitan.config.properties.DruidProperties;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.*;
+import javax.sql.DataSource;
+import java.io.IOException;
+
+/**
+ * druid 閰嶇疆澶氭暟鎹簮
+ *
+ * @author zhitan
+ */
+@Configuration
+public class DruidConfig {
+    @Bean
+    @ConfigurationProperties("spring.datasource.druid.master")
+    public DataSource masterDataSource(DruidProperties druidProperties) {
+        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+        return druidProperties.dataSource(dataSource);
+    }
+
+    @Bean
+    @ConfigurationProperties("spring.datasource.druid.slave")
+    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
+    public DataSource slaveDataSource(DruidProperties druidProperties) {
+        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+        return druidProperties.dataSource(dataSource);
+    }
+
+    /**
+     * 鍘婚櫎鐩戞帶椤甸潰搴曢儴鐨勫箍鍛�
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    @Bean
+    @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
+    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) {
+        // 鑾峰彇web鐩戞帶椤甸潰鐨勫弬鏁�
+        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
+        // 鎻愬彇common.js鐨勯厤缃矾寰�
+        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
+        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
+        final String filePath = "support/http/resources/js/common.js";
+        // 鍒涘缓filter杩涜杩囨护
+        Filter filter = new Filter() {
+            @Override
+            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
+            }
+
+            @Override
+            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+                    throws IOException, ServletException {
+                chain.doFilter(request, response);
+                // 閲嶇疆缂撳啿鍖猴紝鍝嶅簲澶翠笉浼氳閲嶇疆
+                response.resetBuffer();
+                // 鑾峰彇common.js
+                String text = Utils.readFromResource(filePath);
+                // 姝e垯鏇挎崲banner, 闄ゅ幓搴曢儴鐨勫箍鍛婁俊鎭�
+                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
+                text = text.replaceAll("powered.*?shrek.wang</a>", "");
+                response.getWriter().write(text);
+            }
+
+            @Override
+            public void destroy() {
+            }
+        };
+        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
+        registrationBean.setFilter(filter);
+        registrationBean.addUrlPatterns(commonJsPattern);
+        return registrationBean;
+    }
+}
diff --git a/src/main/java/com/zhitan/config/influxdb/InfluxdbConfig.java b/src/main/java/com/zhitan/config/influxdb/InfluxdbConfig.java
new file mode 100644
index 0000000..346d469
--- /dev/null
+++ b/src/main/java/com/zhitan/config/influxdb/InfluxdbConfig.java
@@ -0,0 +1,17 @@
+package com.zhitan.config.influxdb;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "influxdb")
+public class InfluxdbConfig {
+    private String host;
+    private String org;
+    private String bucket;
+    private String token;
+    private String measurement;
+    private boolean enable;
+}
diff --git a/src/main/java/com/zhitan/config/mqtt/MqttConfig.java b/src/main/java/com/zhitan/config/mqtt/MqttConfig.java
new file mode 100644
index 0000000..b8cd6c0
--- /dev/null
+++ b/src/main/java/com/zhitan/config/mqtt/MqttConfig.java
@@ -0,0 +1,42 @@
+package com.zhitan.config.mqtt;
+
+import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
+import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
+
+@Configuration
+public class MqttConfig {
+
+    @Value("${spring.mqtt.broker-url}")
+    private String brokerUrl;
+
+    @Value("${spring.mqtt.username}")
+    private String username;
+
+    @Value("${spring.mqtt.password}")
+    private String password;
+
+    @Value("${spring.mqtt.timeout}")
+    private int timeout;
+
+    @Value("${spring.mqtt.keep-alive}")
+    private int keepAlive;
+
+    // 閰嶇疆MQTT瀹㈡埛绔伐鍘�
+    @Bean
+    public MqttPahoClientFactory mqttClientFactory() {
+        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
+        MqttConnectOptions options = new MqttConnectOptions();
+        options.setServerURIs(new String[]{brokerUrl});
+        options.setUserName(username);
+        options.setPassword(password.toCharArray());
+        options.setConnectionTimeout(timeout);
+        options.setKeepAliveInterval(keepAlive);
+        options.setAutomaticReconnect(true); // 鑷姩閲嶈繛
+        factory.setConnectionOptions(options);
+        return factory;
+    }
+}
diff --git a/src/main/java/com/zhitan/config/mqtt/MqttInboundConfig.java b/src/main/java/com/zhitan/config/mqtt/MqttInboundConfig.java
new file mode 100644
index 0000000..019c1d6
--- /dev/null
+++ b/src/main/java/com/zhitan/config/mqtt/MqttInboundConfig.java
@@ -0,0 +1,44 @@
+package com.zhitan.config.mqtt;
+
+import com.zhitan.handler.MqttMessageHandler;
+import com.zhitan.service.IDataService;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.integration.dsl.IntegrationFlow;
+import org.springframework.integration.dsl.IntegrationFlows;
+import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
+import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
+
+@Configuration
+public class MqttInboundConfig {
+
+    private final MqttPahoClientFactory mqttClientFactory;
+
+    private final IDataService dataService;
+
+    @Value("${spring.mqtt.client-id}")
+    private String clientId;
+
+    @Value("${spring.mqtt.default-topic}")
+    private String defaultTopic;
+
+    public MqttInboundConfig(MqttPahoClientFactory mqttClientFactory, IDataService dataService) {
+        this.mqttClientFactory = mqttClientFactory;
+        this.dataService = dataService;
+    }
+
+    // 璁㈤槄娑堟伅閫傞厤鍣�
+    @Bean
+    public MqttPahoMessageDrivenChannelAdapter inboundAdapter() {
+        return new MqttPahoMessageDrivenChannelAdapter(clientId + "-inbound", mqttClientFactory, defaultTopic);
+    }
+
+    // 瀹氫箟娑堟伅澶勭悊娴�
+    @Bean
+    public IntegrationFlow mqttInFlow() {
+        return IntegrationFlows.from(inboundAdapter())
+                .handle(new MqttMessageHandler(dataService))
+                .get();
+    }
+}
diff --git a/src/main/java/com/zhitan/config/mybatis/MyBatisPlusConfig.java b/src/main/java/com/zhitan/config/mybatis/MyBatisPlusConfig.java
new file mode 100644
index 0000000..239b96b
--- /dev/null
+++ b/src/main/java/com/zhitan/config/mybatis/MyBatisPlusConfig.java
@@ -0,0 +1,44 @@
+package com.zhitan.config.mybatis;
+
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * mybatis plus閰嶇疆
+ */
+@Configuration
+@EnableTransactionManagement(proxyTargetClass = true)
+public class MyBatisPlusConfig {
+
+    /**
+     * 涓�缂撳拰浜岀紦閬靛惊mybatis鐨勮鍒�,闇�瑕佽缃�
+     * MybatisConfiguration#useDeprecatedExecutor = false 閬垮厤缂撳瓨涓囦竴鍑虹幇闂
+     */
+    @Bean
+    public MybatisPlusInterceptor paginationInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        // 涔愯閿佹彃浠�
+        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
+        // 闃绘柇鎻掍欢
+        interceptor.addInnerInterceptor(blockAttackInnerInterceptor());
+        return interceptor;
+    }
+
+    /**
+     * 涔愯閿佹彃浠� https://baomidou.com/guide/interceptor-optimistic-locker.html
+     */
+    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
+        return new OptimisticLockerInnerInterceptor();
+    }
+
+    /**
+     * 濡傛灉鏄鍏ㄨ〃鐨勫垹闄ゆ垨鏇存柊鎿嶄綔锛屽氨浼氱粓姝㈣鎿嶄綔 https://baomidou.com/guide/interceptor-block-attack.html
+     */
+    public BlockAttackInnerInterceptor blockAttackInnerInterceptor() {
+        return new BlockAttackInnerInterceptor();
+    }
+}
diff --git a/src/main/java/com/zhitan/config/properties/DruidProperties.java b/src/main/java/com/zhitan/config/properties/DruidProperties.java
new file mode 100644
index 0000000..f1ba6ee
--- /dev/null
+++ b/src/main/java/com/zhitan/config/properties/DruidProperties.java
@@ -0,0 +1,89 @@
+package com.zhitan.config.properties;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * druid 閰嶇疆灞炴��
+ *
+ * @author zhitan
+ */
+@Configuration
+public class DruidProperties {
+    @Value("${spring.datasource.druid.initialSize}")
+    private int initialSize;
+
+    @Value("${spring.datasource.druid.minIdle}")
+    private int minIdle;
+
+    @Value("${spring.datasource.druid.maxActive}")
+    private int maxActive;
+
+    @Value("${spring.datasource.druid.maxWait}")
+    private int maxWait;
+
+    @Value("${spring.datasource.druid.connectTimeout}")
+    private int connectTimeout;
+
+    @Value("${spring.datasource.druid.socketTimeout}")
+    private int socketTimeout;
+
+    @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
+    private int timeBetweenEvictionRunsMillis;
+
+    @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
+    private int minEvictableIdleTimeMillis;
+
+    @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
+    private int maxEvictableIdleTimeMillis;
+
+    @Value("${spring.datasource.druid.validationQuery}")
+    private String validationQuery;
+
+    @Value("${spring.datasource.druid.testWhileIdle}")
+    private boolean testWhileIdle;
+
+    @Value("${spring.datasource.druid.testOnBorrow}")
+    private boolean testOnBorrow;
+
+    @Value("${spring.datasource.druid.testOnReturn}")
+    private boolean testOnReturn;
+
+    public DruidDataSource dataSource(DruidDataSource datasource) {
+        /* 閰嶇疆鍒濆鍖栧ぇ灏忋�佹渶灏忋�佹渶澶� */
+        datasource.setInitialSize(initialSize);
+        datasource.setMaxActive(maxActive);
+        datasource.setMinIdle(minIdle);
+
+        /* 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂� */
+        datasource.setMaxWait(maxWait);
+
+        /* 閰嶇疆椹卞姩杩炴帴瓒呮椂鏃堕棿锛屾娴嬫暟鎹簱寤虹珛杩炴帴鐨勮秴鏃舵椂闂达紝鍗曚綅鏄绉� */
+        datasource.setConnectTimeout(connectTimeout);
+
+        /* 閰嶇疆缃戠粶瓒呮椂鏃堕棿锛岀瓑寰呮暟鎹簱鎿嶄綔瀹屾垚鐨勭綉缁滆秴鏃舵椂闂达紝鍗曚綅鏄绉� */
+        datasource.setSocketTimeout(socketTimeout);
+
+        /* 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣 */
+        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
+
+        /* 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忋�佹渶澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣 */
+        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+        datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
+
+        /*
+         * 鐢ㄦ潵妫�娴嬭繛鎺ユ槸鍚︽湁鏁堢殑sql锛岃姹傛槸涓�涓煡璇㈣鍙ワ紝甯哥敤select 'x'銆�
+         * 濡傛灉validationQuery涓簄ull锛宼estOnBorrow銆乼estOnReturn銆乼estWhileIdle閮戒笉浼氳捣浣滅敤銆�
+         */
+        datasource.setValidationQuery(validationQuery);
+        /* 寤鸿閰嶇疆涓簍rue锛屼笉褰卞搷鎬ц兘锛屽苟涓斾繚璇佸畨鍏ㄦ�с�傜敵璇疯繛鎺ョ殑鏃跺�欐娴嬶紝
+        濡傛灉绌洪棽鏃堕棿澶т簬timeBetweenEvictionRunsMillis锛屾墽琛寁alidationQuery妫�娴嬭繛鎺ユ槸鍚︽湁鏁堛�� */
+        datasource.setTestWhileIdle(testWhileIdle);
+        /* 鐢宠杩炴帴鏃舵墽琛寁alidationQuery妫�娴嬭繛鎺ユ槸鍚︽湁鏁堬紝鍋氫簡杩欎釜閰嶇疆浼氶檷浣庢�ц兘銆� */
+        datasource.setTestOnBorrow(testOnBorrow);
+        /* 褰掕繕杩炴帴鏃舵墽琛寁alidationQuery妫�娴嬭繛鎺ユ槸鍚︽湁鏁堬紝鍋氫簡杩欎釜閰嶇疆浼氶檷浣庢�ц兘銆� */
+        datasource.setTestOnReturn(testOnReturn);
+        return datasource;
+    }
+}
diff --git a/src/main/java/com/zhitan/config/redis/RedisConfig.java b/src/main/java/com/zhitan/config/redis/RedisConfig.java
new file mode 100644
index 0000000..dad07a0
--- /dev/null
+++ b/src/main/java/com/zhitan/config/redis/RedisConfig.java
@@ -0,0 +1,42 @@
+package com.zhitan.config.redis;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Configuration
+@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport {
+    @Bean
+    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<Object, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 浣跨敤 Jackson2JsonRedisSerializer 搴忓垪鍖栧��
+        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
+        serializer.setObjectMapper(objectMapper);
+
+        // 璁剧疆 Key 鍜� Value 鐨勫簭鍒楀寲瑙勫垯
+        // Key 浣跨敤瀛楃涓插簭鍒楀寲
+        template.setKeySerializer(new StringRedisSerializer());
+        // Value 浣跨敤 JSON 搴忓垪鍖�
+        template.setValueSerializer(serializer);
+        // Hash Key 浣跨敤瀛楃涓插簭鍒楀寲
+        template.setHashKeySerializer(new StringRedisSerializer());
+        // Hash Value 浣跨敤 JSON 搴忓垪
+        template.setHashValueSerializer(serializer);
+        template.afterPropertiesSet();
+        return template;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/zhitan/handler/MqttMessageHandler.java b/src/main/java/com/zhitan/handler/MqttMessageHandler.java
new file mode 100644
index 0000000..d1f8b83
--- /dev/null
+++ b/src/main/java/com/zhitan/handler/MqttMessageHandler.java
@@ -0,0 +1,40 @@
+package com.zhitan.handler;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zhitan.model.entity.ElectricPower;
+import com.zhitan.service.IDataService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageHandler;
+import org.springframework.messaging.MessagingException;
+
+/**
+ * mqtt 娑堟伅澶勭悊绫�
+ */
+@Slf4j
+public class MqttMessageHandler implements MessageHandler {
+    private final IDataService dataService;
+
+    public MqttMessageHandler(IDataService dataService) {
+        this.dataService = dataService;
+    }
+
+    @Override
+    public void handleMessage(Message<?> message) throws MessagingException {
+        String topic = (String) message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC);
+        String payload = (String) message.getPayload();
+        System.out.println("Received message from topic " + topic + ": " + payload);
+
+//        dataService.writeTimeSeriesData(payload);
+//
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            // 灏� JSON 瀛楃涓茶浆鎹负 SensorData 瀵硅薄
+            ElectricPower electricPower = objectMapper.readValue(payload, ElectricPower.class);
+            dataService.writeTimeSeriesData(electricPower);
+        } catch (Exception e) {
+            log.error(e.getMessage());
+        }
+    }
+}
diff --git a/src/main/java/com/zhitan/influxdb/InfluxdbRepository.java b/src/main/java/com/zhitan/influxdb/InfluxdbRepository.java
new file mode 100644
index 0000000..b55ef44
--- /dev/null
+++ b/src/main/java/com/zhitan/influxdb/InfluxdbRepository.java
@@ -0,0 +1,76 @@
+package com.zhitan.influxdb;
+
+import com.influxdb.LogLevel;
+import com.influxdb.client.InfluxDBClient;
+import com.influxdb.client.InfluxDBClientFactory;
+import com.influxdb.client.WriteApiBlocking;
+import com.influxdb.client.write.Point;
+import com.zhitan.config.influxdb.InfluxdbConfig;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * influxdb鐨勫熀纭�鏈嶅姟
+ *
+ * @author Silence
+ * @version 1.0
+ */
+@Slf4j
+@Repository
+public class InfluxdbRepository {
+
+    protected InfluxdbConfig config;
+    protected InfluxDBClient client;
+
+    @Autowired
+    public InfluxdbRepository(InfluxdbConfig config) {
+        this.config = config;
+        init();
+    }
+
+    /**
+     * 鍒濆鍖�
+     */
+    private void init() {
+        if (config.isEnable()) {
+            if (null == client) {
+                client = InfluxDBClientFactory.create(config.getHost(), config.getToken().toCharArray(),
+                                config.getOrg(), config.getBucket())
+                        .enableGzip()
+                        .setLogLevel(LogLevel.BASIC);
+            }
+            if (!client.ping()) {
+                log.error("瀹炴椂搴撹繛鎺ュけ璐�");
+            } else {
+                log.info("瀹炴椂搴撹繛鎺ユ垚鍔�");
+            }
+        } else {
+            log.debug("鏃跺簭搴撲笉鍙敤");
+        }
+    }
+
+    /**
+     * 鍐欏叆鍗曚釜鐐逛綅
+     */
+    public void writePoint(Point point) {
+        if (null == point) {
+            return;
+        }
+        WriteApiBlocking writeApi = client.getWriteApiBlocking();
+        writeApi.writePoint(point);
+    }
+
+    /**
+     * 鍐欏叆澶氫釜鐐逛綅
+     */
+    public void writePoints(List<Point> points) {
+        if (null == points || points.isEmpty()) {
+            return;
+        }
+        WriteApiBlocking writeApi = client.getWriteApiBlocking();
+        writeApi.writePoints(points);
+    }
+}
diff --git a/src/main/java/com/zhitan/mapper/CommonMapper.java b/src/main/java/com/zhitan/mapper/CommonMapper.java
new file mode 100644
index 0000000..4c17486
--- /dev/null
+++ b/src/main/java/com/zhitan/mapper/CommonMapper.java
@@ -0,0 +1,17 @@
+package com.zhitan.mapper;
+
+import com.zhitan.model.IndexTemplate;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * common mapper
+ */
+public interface CommonMapper {
+
+    /**
+     * 鑾峰彇鐐逛綅妯℃澘
+     */
+    List<IndexTemplate> getIndexTemplate();
+}
diff --git a/src/main/java/com/zhitan/model/IndexTemplate.java b/src/main/java/com/zhitan/model/IndexTemplate.java
new file mode 100644
index 0000000..af27b15
--- /dev/null
+++ b/src/main/java/com/zhitan/model/IndexTemplate.java
@@ -0,0 +1,26 @@
+package com.zhitan.model;
+
+import lombok.Data;
+
+/**
+ * 妯℃澘
+ */
+@Data
+public class IndexTemplate {
+    /**
+     * code
+     */
+    private String code;
+    /**
+     * name
+     */
+    private String name;
+    /**
+     * deviceType
+     */
+    private Integer deviceType;
+    /**
+     * gatewayKey
+     */
+    private String gatewayKey;
+}
diff --git a/src/main/java/com/zhitan/model/entity/ElectricPower.java b/src/main/java/com/zhitan/model/entity/ElectricPower.java
new file mode 100644
index 0000000..325ef98
--- /dev/null
+++ b/src/main/java/com/zhitan/model/entity/ElectricPower.java
@@ -0,0 +1,84 @@
+package com.zhitan.model.entity;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * 鐢佃〃鐨勬暟鎹粨鏋�
+ */
+@Data
+public class ElectricPower {
+    @JsonProperty("SN")
+    private String sn;
+
+    @JsonProperty("Pt")
+    private double pt;
+
+    @JsonProperty("Ua")
+    private double ua;
+
+    @JsonProperty("Ub")
+    private double ub;
+
+    @JsonProperty("Uc")
+    private double uc;
+
+    @JsonProperty("Uab")
+    private double uab;
+
+    @JsonProperty("Ubc")
+    private double ubc;
+
+    @JsonProperty("Uca")
+    private double uca;
+    @JsonProperty("Ia")
+    private double ia;
+
+    @JsonProperty("Ib")
+    private double ib;
+
+    @JsonProperty("Ic")
+    private double ic;
+
+    @JsonProperty("Pw")
+    private double pw;
+
+    @JsonProperty("Pwa")
+    private double pwa;
+
+    @JsonProperty("Pwb")
+    private double pwb;
+
+    @JsonProperty("Pwc")
+    private double pwc;
+
+    @JsonProperty("Pq")
+    private double pq;
+
+    @JsonProperty("Pqa")
+    private double pqa;
+
+    @JsonProperty("Pqb")
+    private double pqb;
+
+    @JsonProperty("Pqc")
+    private double pqc;
+
+    @JsonProperty("Q")
+    private double q;
+
+    @JsonProperty("Qa")
+    private double qa;
+
+    @JsonProperty("Qb")
+    private double qb;
+
+    @JsonProperty("Qc")
+    private double qc;
+
+    @JsonProperty("Time")
+    private String time;
+
+    @JsonProperty("Type")
+    private int type;
+}
diff --git a/src/main/java/com/zhitan/redis/RedisCache.java b/src/main/java/com/zhitan/redis/RedisCache.java
new file mode 100644
index 0000000..d008cb7
--- /dev/null
+++ b/src/main/java/com/zhitan/redis/RedisCache.java
@@ -0,0 +1,183 @@
+package com.zhitan.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.*;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * spring redis 宸ュ叿绫�
+ *
+ * @author ruoyi
+ **/
+@SuppressWarnings(value = {"unchecked", "rawtypes"})
+@Component
+public class RedisCache {
+    private final RedisTemplate redisTemplate;
+
+    @Autowired
+    public RedisCache(RedisTemplate redisTemplate) {
+        this.redisTemplate = redisTemplate;
+    }
+
+    /**
+     * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
+     *
+     * @param key   缂撳瓨鐨勯敭鍊�
+     * @param value 缂撳瓨鐨勫��
+     * @return 缂撳瓨鐨勫璞�
+     */
+    public <T> ValueOperations<String, T> setCacheObject(String key, T value) {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        operation.set(key, value);
+        return operation;
+    }
+
+    /**
+     * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
+     *
+     * @param key      缂撳瓨鐨勯敭鍊�
+     * @param value    缂撳瓨鐨勫��
+     * @param timeout  鏃堕棿
+     * @param timeUnit 鏃堕棿棰楃矑搴�
+     * @return 缂撳瓨鐨勫璞�
+     */
+    public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit) {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        operation.set(key, value, timeout, timeUnit);
+        return operation;
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨勫熀鏈璞°��
+     *
+     * @param key 缂撳瓨閿��
+     * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
+     */
+    public <T> T getCacheObject(String key) {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        return operation.get(key);
+    }
+
+    /**
+     * 鍒犻櫎鍗曚釜瀵硅薄
+     *
+     * @param key
+     */
+    public void deleteObject(String key) {
+        redisTemplate.delete(key);
+    }
+
+    /**
+     * 鍒犻櫎闆嗗悎瀵硅薄
+     *
+     * @param collection
+     */
+    public void deleteObject(Collection collection) {
+        redisTemplate.delete(collection);
+    }
+
+    /**
+     * 缂撳瓨List鏁版嵁
+     *
+     * @param key      缂撳瓨鐨勯敭鍊�
+     * @param dataList 寰呯紦瀛樼殑List鏁版嵁
+     * @return 缂撳瓨鐨勫璞�
+     */
+    public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList) {
+        ListOperations listOperation = redisTemplate.opsForList();
+        if (null != dataList) {
+            int size = dataList.size();
+            for (int i = 0; i < size; i++) {
+                listOperation.leftPush(key, dataList.get(i));
+            }
+        }
+        return listOperation;
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨刲ist瀵硅薄
+     *
+     * @param key 缂撳瓨鐨勯敭鍊�
+     * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
+     */
+    public <T> List<T> getCacheList(String key) {
+        List<T> dataList = new ArrayList<T>();
+        ListOperations<String, T> listOperation = redisTemplate.opsForList();
+        Long size = listOperation.size(key);
+
+        for (int i = 0; i < size; i++) {
+            dataList.add(listOperation.index(key, i));
+        }
+        return dataList;
+    }
+
+    /**
+     * 缂撳瓨Set
+     *
+     * @param key     缂撳瓨閿��
+     * @param dataSet 缂撳瓨鐨勬暟鎹�
+     * @return 缂撳瓨鏁版嵁鐨勫璞�
+     */
+    public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet) {
+        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
+        Iterator<T> it = dataSet.iterator();
+        while (it.hasNext()) {
+            setOperation.add(it.next());
+        }
+        return setOperation;
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨剆et
+     *
+     * @param key
+     * @return
+     */
+    public <T> Set<T> getCacheSet(String key) {
+        Set<T> dataSet = new HashSet<T>();
+        BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
+        dataSet = operation.members();
+        return dataSet;
+    }
+
+    /**
+     * 缂撳瓨Map
+     *
+     * @param key
+     * @param dataMap
+     * @return
+     */
+    public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) {
+        HashOperations hashOperations = redisTemplate.opsForHash();
+        if (null != dataMap) {
+            for (Map.Entry<String, T> entry : dataMap.entrySet()) {
+                hashOperations.put(key, entry.getKey(), entry.getValue());
+            }
+        }
+        return hashOperations;
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨凪ap
+     *
+     * @param key
+     * @return
+     */
+    public <T> Map<String, T> getCacheMap(String key) {
+        Map<String, T> map = redisTemplate.opsForHash().entries(key);
+        return map;
+    }
+
+    /**
+     * 鑾峰緱缂撳瓨鐨勫熀鏈璞″垪琛�
+     *
+     * @param pattern 瀛楃涓插墠缂�
+     * @return 瀵硅薄鍒楄〃
+     */
+    public Collection<String> keys(String pattern) {
+        return redisTemplate.keys(pattern);
+    }
+}
diff --git a/src/main/java/com/zhitan/service/IDataService.java b/src/main/java/com/zhitan/service/IDataService.java
new file mode 100644
index 0000000..f04f0cc
--- /dev/null
+++ b/src/main/java/com/zhitan/service/IDataService.java
@@ -0,0 +1,24 @@
+package com.zhitan.service;
+
+import com.zhitan.model.entity.ElectricPower;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * 鏁版嵁service
+ */
+public interface IDataService {
+
+    /**
+     * 鍐欏叆鏁版嵁-閫傚悎鍔ㄦ�佸啓鍏ey鍞竴鐨�
+     *
+     * @param jsonString json鏍煎紡鐨勬暟鎹�
+     */
+    void writeTimeSeriesData(@NotNull String jsonString);
+
+    /**
+     * 鍐欏叆鐢靛姏鐩稿叧鏁版嵁-鍥哄畾鏍煎紡锛屽彲鑷畾涔変慨鏀�
+     *
+     * @param electricPower 鍥哄畾鏍煎紡鐨勬暟鎹�
+     */
+    void writeTimeSeriesData(@NotNull ElectricPower electricPower);
+}
diff --git a/src/main/java/com/zhitan/service/impl/DataServiceImpl.java b/src/main/java/com/zhitan/service/impl/DataServiceImpl.java
new file mode 100644
index 0000000..fc1af3d
--- /dev/null
+++ b/src/main/java/com/zhitan/service/impl/DataServiceImpl.java
@@ -0,0 +1,133 @@
+package com.zhitan.service.impl;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+import com.influxdb.client.domain.WritePrecision;
+import com.influxdb.client.write.Point;
+import com.zhitan.config.influxdb.InfluxdbConfig;
+import com.zhitan.model.IndexTemplate;
+import com.zhitan.model.entity.ElectricPower;
+import com.zhitan.influxdb.InfluxdbRepository;
+import com.zhitan.mapper.CommonMapper;
+import com.zhitan.redis.RedisCache;
+import com.zhitan.service.IDataService;
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.lang.reflect.Field;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鏁版嵁service
+ */
+@Slf4j
+@Service
+public class DataServiceImpl implements IDataService {
+
+    private final String TAG = "tag";
+    private final String FIELD_VALUE = "value";
+    private final InfluxdbRepository repository;
+    private final InfluxdbConfig influxdbConfig;
+    private final CommonMapper commonMapper;
+    private final RedisCache redisCache;
+
+    @Autowired
+    public DataServiceImpl(InfluxdbRepository repository, InfluxdbConfig influxdbConfig,
+                           CommonMapper commonMapper, RedisCache redisCache) {
+        this.repository = repository;
+        this.influxdbConfig = influxdbConfig;
+        this.commonMapper = commonMapper;
+        this.redisCache = redisCache;
+    }
+
+    /**
+     * 鍐欏叆鏃跺簭鏁版嵁
+     *
+     * @param jsonString json鏁版嵁
+     */
+    @Override
+    public void writeTimeSeriesData(@NotNull String jsonString) {
+        if (jsonString.isEmpty()) {
+            return;
+        }
+        List<Point> points = new ArrayList<>();
+        JsonObject jsonObject = JsonParser.parseString(jsonString).getAsJsonObject();
+        for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
+            String key = entry.getKey();
+            JsonElement value = entry.getValue();
+            JsonPrimitive primitive = value.getAsJsonPrimitive();
+            Point point = Point
+                    .measurement(influxdbConfig.getMeasurement())
+                    .addTag(TAG, key)
+                    .time(Instant.now(), WritePrecision.S);
+            if (primitive.isJsonPrimitive()) {
+                if (primitive.isNumber()) {
+                    point.addField(FIELD_VALUE, value.getAsDouble());
+                    points.add(point);
+                } else if (primitive.isString()) {
+                    //point.addField(FIELD_VALUE, value.getAsString());
+                } else if (primitive.isBoolean()) {
+                    //point.addField(FIELD_VALUE, value.getAsBoolean());
+                }
+            }
+        }
+        repository.writePoints(points);
+    }
+
+    /**
+     * 鍐欏叆鐢靛姏鐩稿叧鏁版嵁-鍥哄畾鏍煎紡锛屽彲鑷畾涔変慨鏀�
+     *
+     * @param electricPower 鍥哄畾鏍煎紡鐨勬暟鎹�
+     */
+    @Override
+    public void writeTimeSeriesData(@NotNull ElectricPower electricPower) {
+        List<IndexTemplate> templates = getIndexTemplate();
+        // 鑾峰彇绫讳腑鎵�鏈夊0鏄庣殑瀛楁
+        Field[] fields = electricPower.getClass().getDeclaredFields();
+        List<Point> points = new ArrayList<>();
+        for (Field field : fields) {
+            IndexTemplate indexTemplate = templates.stream().filter(template ->
+                            field.getName().equalsIgnoreCase(template.getGatewayKey()))
+                    .findFirst().orElse(null);
+            if (indexTemplate != null) {
+                Point point = Point
+                        .measurement(influxdbConfig.getMeasurement())
+                        .addTag(TAG, electricPower.getSn() + "_" + indexTemplate.getCode())
+                        .time(Instant.now(), WritePrecision.S);
+                // 璁剧疆瀛楁鍙闂紝鍏佽璁块棶绉佹湁瀛楁
+                field.setAccessible(true);
+                if (Number.class.isAssignableFrom(field.getType()) || field.getType().isPrimitive()) {
+                    try {
+                        // 鑾峰彇瀛楁鍊�
+                        double value = field.getDouble(electricPower);
+                        point.addField(FIELD_VALUE, value);
+                        points.add(point);
+                    } catch (IllegalAccessException e) {
+                        log.error("鑾峰彇灞炴�у�煎け璐�:{}", e.getMessage());
+                    }
+                }
+            }
+        }
+        repository.writePoints(points);
+    }
+
+    /**
+     * 鑾峰彇鐐逛綅妯℃澘
+     */
+    protected List<IndexTemplate> getIndexTemplate() {
+        String TEMPLATE_KEY = "template";
+        List<IndexTemplate> result = redisCache.getCacheList(TEMPLATE_KEY);
+        if (result == null || result.isEmpty()) {
+            result = commonMapper.getIndexTemplate();
+            redisCache.setCacheList(TEMPLATE_KEY, result);
+        }
+        return result;
+    }
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
new file mode 100644
index 0000000..3804c3f
--- /dev/null
+++ b/src/main/resources/application-dev.yml
@@ -0,0 +1,78 @@
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: org.postgresql.Driver
+    druid:
+      master:
+        url: jdbc:postgresql://localhost:5432/energy
+        username: postgres
+        password: postgres
+      # 鍒濆杩炴帴鏁�
+      initialSize: 5
+      # 鏈�灏忚繛鎺ユ睜鏁伴噺
+      minIdle: 10
+      # 鏈�澶ц繛鎺ユ睜鏁伴噺
+      maxActive: 20
+      # 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂�
+      maxWait: 60000
+      # 閰嶇疆杩炴帴瓒呮椂鏃堕棿
+      connectTimeout: 30000
+      # 閰嶇疆缃戠粶瓒呮椂鏃堕棿
+      socketTimeout: 60000
+      # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣
+      timeBetweenEvictionRunsMillis: 60000
+      # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+      minEvictableIdleTimeMillis: 300000
+      # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+      maxEvictableIdleTimeMillis: 900000
+      # 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁�
+      validationQuery: SELECT 1
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 璁剧疆鐧藉悕鍗曪紝涓嶅~鍒欏厑璁告墍鏈夎闂�
+        allow:
+        url-pattern: /druid/*
+        # 鎺у埗鍙扮鐞嗙敤鎴峰悕鍜屽瘑鐮�
+        login-username: admin
+        login-password: 123456
+      filter:
+        stat:
+          enabled: true
+          # 鎱QL璁板綍
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+  mqtt:
+    # 鑷畾涔�
+    client-id: 202503181042
+    # 鍏叡MQTT鏈嶅姟鍣紝鐢熶骇鐜闇�瑕佹浛鎹负鑷繁鐨�
+    broker-url: tcp://broker.emqx.io
+    username:
+    password:
+    #榛樿璁㈤槄鐨勪富棰�
+    default-topic: zhitan
+    timeout: 30
+    keep-alive: 60
+  redis:
+    database: 0
+    host: localhost
+    port: 6379
+    password:
+influxdb:
+  host: "http://localhost:8086"
+  #淇敼涓鸿嚜宸辩殑鏃跺簭搴撹闂畂rg
+  org: "org"
+  #淇敼涓鸿嚜宸辩殑鏃跺簭搴揵ucket
+  bucket: "bucket"
+  #淇敼涓鸿嚜宸辩殑鏃跺簭搴撹闂畉oken
+  token: "token"
+  measurement: data
+  enable: true
\ No newline at end of file
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..50a8bde
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,24 @@
+spring:
+  profiles:
+    active: dev
+  # 鏈嶅姟妯″潡
+  devtools:
+    restart:
+      # 鐑儴缃插紑鍏�
+      enabled: false
+# 鏃ュ織閰嶇疆
+logging:
+  level:
+    com.zhitan: debug
+    org.springframework: warn
+
+mybatis-plus:
+  type-aliases-package: com.zhitan.entity
+  mapper-locations: classpath*:/mapper/*Mapper.xml
+  # 鍔犺浇鍏ㄥ眬鐨勯厤缃枃浠�
+  config-location: classpath:/mybatis/mybatis-config.xml
+  global-config:
+    db-config:
+      logic-delete-field: del_flag # 鍏ㄥ眬閫昏緫鍒犻櫎瀛楁鍚�
+      logic-delete-value: 2 # 閫昏緫宸插垹闄ゅ��
+      logic-not-delete-value: 0 # 閫昏緫鏈垹闄ゅ��
\ No newline at end of file
diff --git a/src/main/resources/mapper/CommonMapper.xml b/src/main/resources/mapper/CommonMapper.xml
new file mode 100644
index 0000000..b874b8a
--- /dev/null
+++ b/src/main/resources/mapper/CommonMapper.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.zhitan.mapper.CommonMapper">
+    <select id="getIndexTemplate" resultType="com.zhitan.model.IndexTemplate">
+        SELECT code,
+               "name",
+               device_type,
+               gateway_key
+        FROM daq_template;
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mybatis/mybatis-config.xml b/src/main/resources/mybatis/mybatis-config.xml
new file mode 100644
index 0000000..dc7b13b
--- /dev/null
+++ b/src/main/resources/mybatis/mybatis-config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE configuration
+        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-config.dtd">
+<configuration>
+    <!-- 鍏ㄥ眬鍙傛暟 -->
+    <settings>
+        <!-- 浣垮叏灞�鐨勬槧灏勫櫒鍚敤鎴栫鐢ㄧ紦瀛� -->
+        <setting name="cacheEnabled" value="true"/>
+        <!-- 鍏佽JDBC 鏀寔鑷姩鐢熸垚涓婚敭 -->
+        <setting name="useGeneratedKeys" value="true"/>
+        <!-- 閰嶇疆榛樿鐨勬墽琛屽櫒.SIMPLE灏辨槸鏅�氭墽琛屽櫒;REUSE鎵ц鍣ㄤ細閲嶇敤棰勫鐞嗚鍙�(prepared statements);BATCH鎵ц鍣ㄥ皢閲嶇敤璇彞骞舵墽琛屾壒閲忔洿鏂� -->
+        <setting name="defaultExecutorType" value="SIMPLE"/>
+        <!-- 鎸囧畾 MyBatis 鎵�鐢ㄦ棩蹇楃殑鍏蜂綋瀹炵幇 -->
+        <setting name="logImpl" value="SLF4J"/>
+        <!-- 浣跨敤椹煎嘲鍛藉悕娉曡浆鎹㈠瓧娈� -->
+        <setting name="mapUnderscoreToCamelCase" value="true"/>
+    </settings>
+
+</configuration>
\ No newline at end of file

--
Gitblit v1.9.3