From 698cec92bdf4f5c416874fd89fb6cbc50b8d9c14 Mon Sep 17 00:00:00 2001
From: 安浩浩 <1036606149@qq.com>
Date: Fri, 24 Jan 2025 23:17:26 +0800
Subject: [PATCH] 【功能完善】IoT: 重命名插件模块,重构插件管理逻辑,优化代码结构,更新配置文件以支持新插件架构。
---
yudao-module-iot/pom.xml | 2 +-
yudao-module-iot/yudao-module-iot-plugin/pom.xml | 26 --------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/plugin.properties | 6 ------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/pom.xml | 164 --------------------------------------------------------------------------------------------------------------------------------------------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml | 31 -------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java | 42 ------------------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/dependency-reduced-pom.xml | 43 -------------------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/plugin.properties | 6 ------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml | 150 ------------------------------------------------------------------------------------------------------------------------------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml | 24 ------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java | 26 --------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/HttpVertxPlugin.java | 81 ---------------------------------------------------------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java | 69 ---------------------------------------------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/service/HttpVertxHandler.java | 105 ---------------------------------------------------------------------------------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/resources/application.yml | 3 ---
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/plugin.properties | 7 -------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/pom.xml | 155 -----------------------------------------------------------------------------------------------------------------------------------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml | 31 -------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java | 36 ------------------------------------
yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java | 231 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
yudao-module-iot/yudao-module-iot-plugins/pom.xml | 27 +++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/pom.xml | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/api/DeviceDataApiClient.java | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/config/DeviceDataApiInitializer.java | 29 +++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/package-info.java | 1 +
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/plugin.properties | 6 ++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/pom.xml | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml | 31 +++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java | 42 ++++++++++++++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/plugin.properties | 6 ++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/pom.xml | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml | 24 ++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/HttpPluginSpringbootApplication.java | 16 ++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/HttpVertxPlugin.java | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/HttpVertxPluginConfiguration.java | 16 ++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/service/HttpVertxHandler.java | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/resources/application.yml | 7 +++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/plugin.properties | 7 +++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/pom.xml | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml | 31 +++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java | 36 ++++++++++++++++++++++++++++++++++++
yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
42 files changed, 1267 insertions(+), 1237 deletions(-)
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/pom.xml
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/plugin.properties
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/pom.xml
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/dependency-reduced-pom.xml
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/plugin.properties
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/HttpVertxPlugin.java
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/service/HttpVertxHandler.java
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/resources/application.yml
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/plugin.properties
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/pom.xml
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java
delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/pom.xml
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/pom.xml
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/api/DeviceDataApiClient.java
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/config/DeviceDataApiInitializer.java
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/package-info.java
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/plugin.properties
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/pom.xml
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/plugin.properties
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/pom.xml
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/HttpPluginSpringbootApplication.java
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/HttpVertxPlugin.java
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/HttpVertxPluginConfiguration.java
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/service/HttpVertxHandler.java
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/resources/application.yml
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/plugin.properties
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/pom.xml
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java
create mode 100644 yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java
diff --git a/yudao-module-iot/pom.xml b/yudao-module-iot/pom.xml
index d9002ab..0422c5d 100644
--- a/yudao-module-iot/pom.xml
+++ b/yudao-module-iot/pom.xml
@@ -10,7 +10,7 @@
yudao-module-iot-api
yudao-module-iot-biz
- yudao-module-iot-plugin
+ yudao-module-iot-plugins
4.0.0
diff --git a/yudao-module-iot/yudao-module-iot-plugin/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/pom.xml
deleted file mode 100644
index 949ff13..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/pom.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- yudao-module-iot
- cn.iocoder.boot
- ${revision}
-
-
- yudao-module-iot-plugin-http
- yudao-module-iot-plugin-mqtt
- yudao-module-iot-plugin-emqx
-
-
- 4.0.0
-
- yudao-module-iot-plugin
- pom
-
- ${project.artifactId}
-
- 物联网 插件 模块
-
-
-
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/plugin.properties b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/plugin.properties
deleted file mode 100644
index 7f565b7..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/plugin.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-plugin.id=plugin-emqx
-plugin.class=cn.iocoder.yudao.module.iot.plugin.EmqxPlugin
-plugin.version=1.0.0
-plugin.provider=ahh
-plugin.dependencies=
-plugin.description=plugin-emqx-1.0.0
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/pom.xml
deleted file mode 100644
index 266e45f..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/pom.xml
+++ /dev/null
@@ -1,164 +0,0 @@
-
-
-
- yudao-module-iot-plugin
- cn.iocoder.boot
- ${revision}
-
- 4.0.0
- jar
-
- yudao-module-iot-plugin-emqx
-
- ${project.artifactId}
-
- 物联网 插件模块 - emqx 插件
-
-
-
-
- emqx-plugin
- cn.iocoder.yudao.module.iot.plugin.EmqxPlugin
- 0.0.1
- ahh
- emqx-plugin-0.0.1
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
- 1.6
-
-
- unzip jar file
- package
-
-
-
-
-
-
- run
-
-
-
-
-
-
- maven-assembly-plugin
- 2.3
-
-
-
- src/main/assembly/assembly.xml
-
-
- false
-
-
-
- make-assembly
- package
-
- attached
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 2.4
-
-
-
- ${plugin.id}
- ${plugin.class}
- ${plugin.version}
- ${plugin.provider}
- ${plugin.description}
- ${plugin.dependencies}
-
-
-
-
-
-
- maven-deploy-plugin
-
- true
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
- org.pf4j
- pf4j-spring
- provided
-
-
-
- cn.iocoder.boot
- yudao-module-iot-api
- ${revision}
-
-
- org.projectlombok
- lombok
- ${lombok.version}
- provided
-
-
-
- io.vertx
- vertx-core
-
-
-
- io.vertx
- vertx-web
-
-
-
- org.eclipse.paho
- org.eclipse.paho.client.mqttv3
-
-
-
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml
deleted file mode 100644
index daec9e4..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
- plugin
-
- zip
-
- false
-
-
- false
- runtime
- lib
-
- *:jar:*
-
-
-
-
-
-
- target/plugin-classes
- classes
-
-
-
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java
deleted file mode 100644
index 27b9042..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin;
-
-import cn.hutool.extra.spring.SpringUtil;
-import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
-import lombok.extern.slf4j.Slf4j;
-import org.pf4j.Plugin;
-import org.pf4j.PluginWrapper;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-@Slf4j
-public class EmqxPlugin extends Plugin {
-
- private ExecutorService executorService;
-
- public EmqxPlugin(PluginWrapper wrapper) {
- super(wrapper);
- this.executorService = Executors.newSingleThreadExecutor();
- }
-
- @Override
- public void start() {
- log.info("EmqxPlugin.start()");
-
- if (executorService.isShutdown() || executorService.isTerminated()) {
- executorService = Executors.newSingleThreadExecutor();
- }
-
- DeviceDataApi deviceDataApi = SpringUtil.getBean(DeviceDataApi.class);
- if (deviceDataApi == null) {
- log.error("未能从 ServiceRegistry 获取 DeviceDataApi 实例,请确保主程序已正确注册!");
- return;
- }
-
- }
-
- @Override
- public void stop() {
- log.info("EmqxPlugin.stop()");
- }
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/dependency-reduced-pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/dependency-reduced-pom.xml
deleted file mode 100644
index 260ef9c..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/dependency-reduced-pom.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
- yudao-module-iot-plugin
- cn.iocoder.boot
- 2.2.0-snapshot
-
- 4.0.0
- yudao-module-iot-plugin-http
- ${project.artifactId}
- 1.0.0
- 物联网 插件模块 - http 插件
-
-
-
- maven-shade-plugin
- 3.2.4
-
-
- package
-
- shade
-
-
-
-
- com.example.HttpPluginSpringbootApplication
-
-
-
-
-
-
-
-
-
- ${project.artifactId}
- ${project.artifactId}-${project.version}
- cn.iocoder.yudao.module.iot.config.HttpVertxPlugin
- ${project.version}
- yudao
-
-
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/plugin.properties b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/plugin.properties
deleted file mode 100644
index 49aef5b..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/plugin.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-plugin.id=yudao-module-iot-plugin-http
-plugin.class=cn.iocoder.yudao.module.iot.config.HttpVertxPlugin
-plugin.version=1.0.0
-plugin.provider=yudao
-plugin.dependencies=
-plugin.description=yudao-module-iot-plugin-http-1.0.0
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml
deleted file mode 100644
index cfea789..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml
+++ /dev/null
@@ -1,150 +0,0 @@
-
-
-
- yudao-module-iot-plugin
- cn.iocoder.boot
- ${revision}
-
- 4.0.0
- jar
-
- yudao-module-iot-plugin-http
- 1.0.0
-
- ${project.artifactId}
-
- 物联网 插件模块 - http 插件
-
-
-
-
- ${project.artifactId}
- cn.iocoder.yudao.module.iot.config.HttpVertxPlugin
- ${project.version}
- yudao
- ${project.artifactId}-${project.version}
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
- 1.6
-
-
- unzip jar file
- package
-
-
-
-
-
-
- run
-
-
-
-
-
-
- maven-assembly-plugin
- 2.3
-
-
-
- src/main/assembly/assembly.xml
-
-
- false
-
-
-
- make-assembly
- package
-
- attached
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 2.4
-
-
-
- ${plugin.id}
- ${plugin.class}
- ${plugin.version}
- ${plugin.provider}
- ${plugin.description}
- ${plugin.dependencies}
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
- ${spring.boot.version}
-
-
-
- repackage
-
-
- -standalone
-
-
-
-
-
-
- maven-deploy-plugin
-
- true
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
- org.pf4j
- pf4j-spring
-
-
-
- cn.iocoder.boot
- yudao-module-iot-api
- ${revision}
-
-
- org.projectlombok
- lombok
-
-
-
- io.vertx
- vertx-web
-
-
-
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml
deleted file mode 100644
index 9b79e61..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
- plugin
-
- zip
-
- false
-
-
- false
- runtime
- lib
-
- *:jar:*
-
-
-
-
-
-
- target/plugin-classes
- classes
-
-
-
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java
deleted file mode 100644
index 7b29367..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package cn.iocoder.yudao.module.iot;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.WebApplicationType;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-// TODO @haohao:建议包名:cn.iocoder.yudao.module.iot.plugin.${pluginName},例如说 http。然后子包如下:
-// config:方配置类,以及 HttpVertxPlugin 初始化
-// service:放 HttpVertxHandler 逻辑;
-@SpringBootApplication
-public class HttpPluginSpringbootApplication {
-
- public static void main(String[] args) {
-// SpringApplication.run(HttpPluginSpringbootApplication.class, args);
- SpringApplication application = new SpringApplication(HttpPluginSpringbootApplication.class);
- application.setWebApplicationType(WebApplicationType.NONE);
- application.run(args);
- }
-
-}
-
-// TODO @haohao:如下是 sdk 的包:cn.iocoder.yudao.module.iot.plugin.sdk
-// 1. api 包:实现 DeviceDataApi 接口,通过 resttemplate 调用
-// 2. config 包:初始化 DeviceDataApi 等等
-
-// 3. 其中 resttemplate 调用的后端地址,通过每个服务的 application.yaml 进行注入。
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/HttpVertxPlugin.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/HttpVertxPlugin.java
deleted file mode 100644
index d77f990..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/HttpVertxPlugin.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package cn.iocoder.yudao.module.iot.config;
-
-import cn.hutool.extra.spring.SpringUtil;
-import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
-import cn.iocoder.yudao.module.iot.service.HttpVertxHandler;
-import io.vertx.core.Vertx;
-import io.vertx.ext.web.Router;
-import io.vertx.ext.web.handler.BodyHandler;
-import lombok.extern.slf4j.Slf4j;
-import org.pf4j.PluginWrapper;
-import org.pf4j.spring.SpringPlugin;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.AnnotationConfigApplicationContext;
-
-@Slf4j
-public class HttpVertxPlugin extends SpringPlugin {
-
- private static final int PORT = 8092;
- private Vertx vertx;
-
- public HttpVertxPlugin(PluginWrapper wrapper) {
- super(wrapper);
- }
-
- @Override
- public void start() {
- log.info("HttpVertxPlugin.start()");
-
- // 获取 DeviceDataApi 实例
- DeviceDataApi deviceDataApi = SpringUtil.getBean(DeviceDataApi.class);
- if (deviceDataApi == null) {
- log.error("未能从 ServiceRegistry 获取 DeviceDataApi 实例,请确保主程序已正确注册!");
- return;
- }
-
- // 初始化 Vert.x
- vertx = Vertx.vertx();
- Router router = Router.router(vertx);
-
- // 处理 Body
- router.route().handler(BodyHandler.create());
-
- // 设置路由
- router.post("/sys/:productKey/:deviceName/thing/event/property/post")
- .handler(new HttpVertxHandler(deviceDataApi));
-
- // 启动 HTTP 服务器
- vertx.createHttpServer()
- .requestHandler(router)
- .listen(PORT, http -> {
- if (http.succeeded()) {
- log.info("HTTP 服务器启动成功,端口为: {}", PORT);
- } else {
- log.error("HTTP 服务器启动失败", http.cause());
- }
- });
- }
-
- @Override
- public void stop() {
- log.info("HttpVertxPlugin.stop()");
- if (vertx != null) {
- vertx.close(ar -> {
- if (ar.succeeded()) {
- log.info("Vert.x 关闭成功");
- } else {
- log.error("Vert.x 关闭失败", ar.cause());
- }
- });
- }
- }
-
- @Override
- protected ApplicationContext createApplicationContext() {
- AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
- applicationContext.setClassLoader(getWrapper().getPluginClassLoader());
- applicationContext.refresh();
-
- return applicationContext;
- }
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java
deleted file mode 100644
index 18f6b28..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package cn.iocoder.yudao.module.iot.config;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
-import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceEventReportReqDTO;
-import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO;
-import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceStatusUpdateReqDTO;
-import org.pf4j.DefaultPluginManager;
-import org.pf4j.PluginWrapper;
-import org.springframework.boot.web.client.RestTemplateBuilder;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.client.RestTemplate;
-
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-
-// TODO 芋艿:临时实现;
-@Configuration
-public class TestConfiguration {
-
-// @Resource
-// private RestTemplate restTemplate;
-
- // TODO 芋艿:这里,后续看看怎么创建好点
- @Bean
- public RestTemplate restTemplate() {
- return new RestTemplateBuilder().build();
- }
-
- @Bean
- public DeviceDataApi deviceDataApi(RestTemplate restTemplate) {
- return new DeviceDataApi() {
-
- @Override
- public CommonResult updateDeviceStatus(IotDeviceStatusUpdateReqDTO updateReqDTO) {
- // TODO haohao:待实现
- return null;
- }
-
- @Override
- public CommonResult reportDeviceEventData(IotDeviceEventReportReqDTO reportReqDTO) {
- // TODO haohao:待实现
- return null;
- }
-
- @Override
- public CommonResult reportDevicePropertyData(IotDevicePropertyReportReqDTO reportReqDTO) {
- // TODO haohao:待完整实现
- String url = "http://127.0.0.1:48080/rpc-api/iot/device-data/report-property";
- try {
- restTemplate.postForObject(url, reportReqDTO, CommonResult.class);
- return success(true);
- } catch (Exception e) {
- e.printStackTrace();
- return CommonResult.error(400, "error");
- }
- }
-
- };
- }
-
- // TODO @haohao:可能要看下,有没更好的方式
- @Bean(initMethod = "start")
- public HttpVertxPlugin HttpVertxPlugin() {
- PluginWrapper pluginWrapper = new PluginWrapper(new DefaultPluginManager(), null, null, null);
- return new HttpVertxPlugin(pluginWrapper);
- }
-
-}
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/service/HttpVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/service/HttpVertxHandler.java
deleted file mode 100644
index b92b086..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/service/HttpVertxHandler.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package cn.iocoder.yudao.module.iot.service;
-
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
-import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO;
-import io.vertx.core.Handler;
-import io.vertx.ext.web.RequestBody;
-import io.vertx.ext.web.RoutingContext;
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-public class HttpVertxHandler implements Handler {
-
- private final DeviceDataApi deviceDataApi;
-
- public HttpVertxHandler(DeviceDataApi deviceDataApi) {
- this.deviceDataApi = deviceDataApi;
- }
-
- @Override
- public void handle(RoutingContext ctx) {
- String productKey = ctx.pathParam("productKey");
- String deviceName = ctx.pathParam("deviceName");
- RequestBody requestBody = ctx.body();
-
- JSONObject jsonData;
- try {
- jsonData = JSONUtil.parseObj(requestBody.asJsonObject());
- } catch (Exception e) {
- JSONObject res = createResponseJson(
- 400,
- new JSONObject(),
- null,
- "请求数据不是合法的 JSON 格式: " + e.getMessage(),
- "thing.event.property.post",
- "1.0");
- ctx.response()
- .setStatusCode(400)
- .putHeader("Content-Type", "application/json; charset=UTF-8")
- .end(res.toString());
- return;
- }
-
- String id = jsonData.getStr("id", null);
-
- try {
- // 调用主程序的接口保存数据
- IotDevicePropertyReportReqDTO createDTO = IotDevicePropertyReportReqDTO.builder()
- .productKey(productKey)
- .deviceName(deviceName)
- .params(jsonData) // TODO 芋艿:这块要优化
- .build();
- deviceDataApi.reportDevicePropertyData(createDTO);
-
- // 构造成功响应内容
- JSONObject successRes = createResponseJson(
- 200,
- new JSONObject(),
- id,
- "success",
- "thing.event.property.post",
- "1.0");
- ctx.response()
- .setStatusCode(200)
- .putHeader("Content-Type", "application/json; charset=UTF-8")
- .end(successRes.toString());
- } catch (Exception e) {
- JSONObject errorRes = createResponseJson(
- 500,
- new JSONObject(),
- id,
- "The format of result is error!",
- "thing.event.property.post",
- "1.0");
- ctx.response()
- .setStatusCode(500)
- .putHeader("Content-Type", "application/json; charset=UTF-8")
- .end(errorRes.toString());
- }
- }
-
- /**
- * 创建标准化的响应 JSON 对象
- *
- * @param code 响应状态码(业务层面的)
- * @param data 返回的数据对象(JSON)
- * @param id 请求的 id(可选)
- * @param message 返回的提示信息
- * @param method 返回的 method 标识
- * @param version 返回的版本号
- * @return 构造好的 JSON 对象
- */
- private JSONObject createResponseJson(int code, JSONObject data, String id, String message, String method,
- String version) {
- JSONObject res = new JSONObject();
- res.set("code", code);
- res.set("data", data != null ? data : new JSONObject());
- res.set("id", id);
- res.set("message", message);
- res.set("method", method);
- res.set("version", version);
- return res;
- }
-}
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/resources/application.yml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/resources/application.yml
deleted file mode 100644
index c5a1ee8..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/resources/application.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-spring:
- application:
- name: yudao-module-iot-plugin-http
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/plugin.properties b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/plugin.properties
deleted file mode 100644
index 939e0f6..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/plugin.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-plugin.id=mqtt-plugin
-plugin.description=Vert.x MQTT plugin
-plugin.class=cn.iocoder.yudao.module.iot.plugin.MqttPlugin
-plugin.version=1.0.0
-plugin.requires=
-plugin.provider=ahh
-plugin.license=Apache-2.0
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/pom.xml
deleted file mode 100644
index 7e4689b..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/pom.xml
+++ /dev/null
@@ -1,155 +0,0 @@
-
-
-
- yudao-module-iot-plugin
- cn.iocoder.boot
- ${revision}
-
- 4.0.0
- jar
-
- yudao-module-iot-plugin-mqtt
-
- ${project.artifactId}
-
- 物联网 插件模块 - mqtt 插件
-
-
-
-
- mqtt-plugin
- cn.iocoder.yudao.module.iot.plugin.MqttPlugin
- 0.0.1
- ahh
- mqtt-plugin-0.0.1
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
- 1.6
-
-
- unzip jar file
- package
-
-
-
-
-
-
- run
-
-
-
-
-
-
- maven-assembly-plugin
- 2.3
-
-
-
- src/main/assembly/assembly.xml
-
-
- false
-
-
-
- make-assembly
- package
-
- attached
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 2.4
-
-
-
- ${plugin.id}
- ${plugin.class}
- ${plugin.version}
- ${plugin.provider}
- ${plugin.description}
- ${plugin.dependencies}
-
-
-
-
-
-
- maven-deploy-plugin
-
- true
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
- org.pf4j
- pf4j-spring
- provided
-
-
-
- cn.iocoder.boot
- yudao-module-iot-api
- ${revision}
-
-
- org.projectlombok
- lombok
- ${lombok.version}
- provided
-
-
-
- io.vertx
- vertx-mqtt
- 4.5.11
-
-
-
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml
deleted file mode 100644
index daec9e4..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
- plugin
-
- zip
-
- false
-
-
- false
- runtime
- lib
-
- *:jar:*
-
-
-
-
-
-
- target/plugin-classes
- classes
-
-
-
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java
deleted file mode 100644
index 54ff31f..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin;
-
-import lombok.extern.slf4j.Slf4j;
-import org.pf4j.Plugin;
-import org.pf4j.PluginWrapper;
-
-@Slf4j
-public class MqttPlugin extends Plugin {
-
- private MqttServerExtension mqttServerExtension;
-
- public MqttPlugin(PluginWrapper wrapper) {
- super(wrapper);
- }
-
- @Override
- public void start() {
- log.info("MQTT Plugin started.");
- mqttServerExtension = new MqttServerExtension();
- mqttServerExtension.startMqttServer();
- }
-
- @Override
- public void stop() {
- log.info("MQTT Plugin stopped.");
- if (mqttServerExtension != null) {
- mqttServerExtension.stopMqttServer().onComplete(ar -> {
- if (ar.succeeded()) {
- log.info("Stopped MQTT Server successfully");
- } else {
- log.error("Failed to stop MQTT Server: {}", ar.cause().getMessage());
- }
- });
- }
- }
-}
diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java
deleted file mode 100644
index 868d238..0000000
--- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java
+++ /dev/null
@@ -1,231 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin;
-
-import io.netty.handler.codec.mqtt.MqttProperties;
-import io.netty.handler.codec.mqtt.MqttQoS;
-import io.vertx.core.Future;
-import io.vertx.core.Vertx;
-import io.vertx.core.buffer.Buffer;
-import io.vertx.mqtt.MqttEndpoint;
-import io.vertx.mqtt.MqttServer;
-import io.vertx.mqtt.MqttServerOptions;
-import io.vertx.mqtt.MqttTopicSubscription;
-import io.vertx.mqtt.messages.MqttDisconnectMessage;
-import io.vertx.mqtt.messages.MqttPublishMessage;
-import io.vertx.mqtt.messages.MqttSubscribeMessage;
-import io.vertx.mqtt.messages.MqttUnsubscribeMessage;
-import io.vertx.mqtt.messages.codes.MqttSubAckReasonCode;
-import lombok.extern.slf4j.Slf4j;
-import org.pf4j.Extension;
-
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 根据官方示例,整合常见 MQTT 功能到 PF4J 的 Extension 类中
- */
-@Slf4j
-@Extension
-public class MqttServerExtension {
-
- private Vertx vertx;
- private MqttServer mqttServer;
-
- /**
- * 启动 MQTT 服务端
- * 可根据需要决定是否启用 SSL/TLS、WebSocket、多实例部署等
- */
- public void startMqttServer() {
- // 初始化 Vert.x
- vertx = Vertx.vertx();
-
- // ========== 如果需要 SSL/TLS,请参考下面注释,启用注释并替换端口、证书路径等 ==========
- // MqttServerOptions options = new MqttServerOptions()
- // .setPort(8883)
- // .setKeyCertOptions(new PemKeyCertOptions()
- // .setKeyPath("./src/test/resources/tls/server-key.pem")
- // .setCertPath("./src/test/resources/tls/server-cert.pem"))
- // .setSsl(true);
-
- // ========== 如果需要 WebSocket,请设置 setUseWebSocket(true) ==========
- // options.setUseWebSocket(true);
-
- // ========== 默认不启用 SSL 的示例 ==========
- MqttServerOptions options = new MqttServerOptions()
- .setPort(1883)
- .setHost("0.0.0.0")
- .setUseWebSocket(false); // 如果需要 WebSocket,请改为 true
-
- mqttServer = MqttServer.create(vertx, options);
-
- // 指定 endpointHandler,处理客户端连接等
- mqttServer.endpointHandler(endpoint -> {
- handleClientConnect(endpoint);
- handleDisconnect(endpoint);
- handleSubscribe(endpoint);
- handleUnsubscribe(endpoint);
- handlePublish(endpoint);
- handlePing(endpoint);
- });
-
- // 启动监听
- mqttServer.listen(ar -> {
- if (ar.succeeded()) {
- log.info("MQTT server is listening on port {}", mqttServer.actualPort());
- } else {
- log.error("Error on starting the server", ar.cause());
- }
- });
- }
-
- /**
- * 优雅关闭 MQTT 服务端
- */
- public Future stopMqttServer() {
- if (mqttServer != null) {
- return mqttServer.close().onComplete(ar -> {
- if (ar.succeeded()) {
- log.info("MQTT server closed.");
- if (vertx != null) {
- vertx.close();
- log.info("Vert.x instance closed.");
- }
- } else {
- log.error("Failed to close MQTT server: {}", ar.cause().getMessage());
- }
- });
- }
- return Future.succeededFuture();
- }
-
- // ==================== 以下为官方示例中常见事件的处理封装 ====================
-
- /**
- * 处理客户端连接 (CONNECT)
- */
- private void handleClientConnect(MqttEndpoint endpoint) {
- // 打印 CONNECT 的主要信息
- log.info("MQTT client [{}] request to connect, clean session = {}",
- endpoint.clientIdentifier(), endpoint.isCleanSession());
-
- if (endpoint.auth() != null) {
- log.info("[username = {}, password = {}]", endpoint.auth().getUsername(), endpoint.auth().getPassword());
- }
- log.info("[properties = {}]", endpoint.connectProperties());
-
- if (endpoint.will() != null) {
- log.info("[will topic = {}, msg = {}, QoS = {}, isRetain = {}]",
- endpoint.will().getWillTopic(),
- new String(endpoint.will().getWillMessageBytes()),
- endpoint.will().getWillQos(),
- endpoint.will().isWillRetain());
- }
-
- log.info("[keep alive timeout = {}]", endpoint.keepAliveTimeSeconds());
-
- // 接受远程客户端的连接
- endpoint.accept(false);
- }
-
- /**
- * 处理客户端主动断开 (DISCONNECT)
- */
- private void handleDisconnect(MqttEndpoint endpoint) {
- endpoint.disconnectMessageHandler((MqttDisconnectMessage disconnectMessage) -> {
- log.info("Received disconnect from client [{}], reason code = {}",
- endpoint.clientIdentifier(), disconnectMessage.code());
- });
- }
-
- /**
- * 处理客户端订阅 (SUBSCRIBE)
- */
- private void handleSubscribe(MqttEndpoint endpoint) {
- endpoint.subscribeHandler((MqttSubscribeMessage subscribe) -> {
- List reasonCodes = new ArrayList<>();
- for (MqttTopicSubscription s : subscribe.topicSubscriptions()) {
- log.info("Subscription for {} with QoS {}", s.topicName(), s.qualityOfService());
- // 将客户端请求的 QoS 转换为返回给客户端的 reason code(可能是错误码或实际 granted QoS)
- reasonCodes.add(MqttSubAckReasonCode.qosGranted(s.qualityOfService()));
- }
- // 回复 SUBACK,MQTT 5.0 时可指定 reasonCodes、properties
- endpoint.subscribeAcknowledge(subscribe.messageId(), reasonCodes, MqttProperties.NO_PROPERTIES);
- });
- }
-
- /**
- * 处理客户端取消订阅 (UNSUBSCRIBE)
- */
- private void handleUnsubscribe(MqttEndpoint endpoint) {
- endpoint.unsubscribeHandler((MqttUnsubscribeMessage unsubscribe) -> {
- for (String topic : unsubscribe.topics()) {
- log.info("Unsubscription for {}", topic);
- }
- // 回复 UNSUBACK,MQTT 5.0 时可指定 reasonCodes、properties
- endpoint.unsubscribeAcknowledge(unsubscribe.messageId());
- });
- }
-
- /**
- * 处理客户端发布的消息 (PUBLISH)
- */
- private void handlePublish(MqttEndpoint endpoint) {
- // 接收 PUBLISH 消息
- endpoint.publishHandler((MqttPublishMessage message) -> {
- String payload = message.payload().toString(Charset.defaultCharset());
- log.info("Received message [{}] on topic [{}] with QoS [{}]",
- payload, message.topicName(), message.qosLevel());
-
- // 根据不同 QoS,回复客户端
- if (message.qosLevel() == MqttQoS.AT_LEAST_ONCE) {
- endpoint.publishAcknowledge(message.messageId());
- } else if (message.qosLevel() == MqttQoS.EXACTLY_ONCE) {
- endpoint.publishReceived(message.messageId());
- }
- });
-
- // 如果 QoS = 2,需要处理 PUBREL
- endpoint.publishReleaseHandler(messageId -> {
- endpoint.publishComplete(messageId);
- });
- }
-
- /**
- * 处理客户端 PINGREQ
- */
- private void handlePing(MqttEndpoint endpoint) {
- endpoint.pingHandler(v -> {
- // 这里仅做日志, PINGRESP 已自动发送
- log.info("Ping received from client [{}]", endpoint.clientIdentifier());
- });
- }
-
- // ==================== 如果需要服务端向客户端发布消息,可用以下示例 ====================
-
- /**
- * 服务端主动向已连接的某个 endpoint 发布消息的示例
- * 如果使用 MQTT 5.0,可以传递更多消息属性
- */
- public void publishToClient(MqttEndpoint endpoint, String topic, String content) {
- endpoint.publish(topic,
- Buffer.buffer(content),
- MqttQoS.AT_LEAST_ONCE, // QoS 自行选择
- false,
- false);
-
- // 处理 QoS 1 和 QoS 2 的 ACK
- endpoint.publishAcknowledgeHandler(messageId -> {
- log.info("Received PUBACK from client [{}] for messageId = {}", endpoint.clientIdentifier(), messageId);
- }).publishReceivedHandler(messageId -> {
- endpoint.publishRelease(messageId);
- }).publishCompletionHandler(messageId -> {
- log.info("Received PUBCOMP from client [{}] for messageId = {}", endpoint.clientIdentifier(), messageId);
- });
- }
-
- // ==================== 如果需要多实例部署,用于多核扩展,可参考以下思路 ====================
- // 例如,在宿主应用或插件中循环启动多个 MqttServerExtension 实例,或使用 Vert.x 的 deployVerticle:
- // DeploymentOptions options = new DeploymentOptions().setInstances(10);
- // vertx.deployVerticle(() -> new MyMqttVerticle(), options);
-
-}
diff --git a/yudao-module-iot/yudao-module-iot-plugins/pom.xml b/yudao-module-iot/yudao-module-iot-plugins/pom.xml
new file mode 100644
index 0000000..d332925
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/pom.xml
@@ -0,0 +1,27 @@
+
+
+
+ yudao-module-iot
+ cn.iocoder.boot
+ ${revision}
+
+
+ yudao-module-iot-plugin-common
+ yudao-module-iot-plugin-http
+ yudao-module-iot-plugin-mqtt
+ yudao-module-iot-plugin-emqx
+
+
+ 4.0.0
+
+ yudao-module-iot-plugins
+ pom
+
+ ${project.artifactId}
+
+ 物联网 插件 模块
+
+
+
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/pom.xml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/pom.xml
new file mode 100644
index 0000000..568f862
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/pom.xml
@@ -0,0 +1,55 @@
+
+
+
+ yudao-module-iot-plugins
+ cn.iocoder.boot
+ ${revision}
+
+ 4.0.0
+ yudao-module-iot-plugin-common
+ jar
+
+ ${project.artifactId}
+
+ 物联网 插件 模块 - 通用功能
+
+
+
+
+ cn.iocoder.boot
+ yudao-common
+
+
+
+ cn.iocoder.boot
+ yudao-module-iot-api
+ ${revision}
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.pf4j
+ pf4j-spring
+
+
+ org.slf4j
+ slf4j-log4j12
+
+
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/api/DeviceDataApiClient.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/api/DeviceDataApiClient.java
new file mode 100644
index 0000000..183c76e
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/api/DeviceDataApiClient.java
@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.module.iot.plugin.common.api;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
+import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceEventReportReqDTO;
+import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO;
+import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceStatusUpdateReqDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.client.RestTemplate;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Slf4j
+public class DeviceDataApiClient implements DeviceDataApi {
+
+ private final RestTemplate restTemplate;
+ private final String deviceDataUrl;
+
+ // 可以通过构造器把 RestTemplate 和 baseUrl 注入进来
+ public DeviceDataApiClient(RestTemplate restTemplate, String deviceDataUrl) {
+ this.restTemplate = restTemplate;
+ this.deviceDataUrl = deviceDataUrl;
+ }
+
+ @Override
+ public CommonResult updateDeviceStatus(IotDeviceStatusUpdateReqDTO updateReqDTO) {
+ // 示例:如果对应的远程地址是 /rpc-api/iot/device-data/update-status
+ String url = deviceDataUrl + "/rpc-api/iot/device-data/update-status";
+ return doPost(url, updateReqDTO, "updateDeviceStatus");
+ }
+
+ @Override
+ public CommonResult reportDeviceEventData(IotDeviceEventReportReqDTO reportReqDTO) {
+ // 示例:如果对应的远程地址是 /rpc-api/iot/device-data/report-event
+ String url = deviceDataUrl + "/rpc-api/iot/device-data/report-event";
+ return doPost(url, reportReqDTO, "reportDeviceEventData");
+ }
+
+ @Override
+ public CommonResult reportDevicePropertyData(IotDevicePropertyReportReqDTO reportReqDTO) {
+ // 示例:如果对应的远程地址是 /rpc-api/iot/device-data/report-property
+ String url = deviceDataUrl + "/rpc-api/iot/device-data/report-property";
+ return doPost(url, reportReqDTO, "reportDevicePropertyData");
+ }
+
+ /**
+ * 将与远程服务交互的通用逻辑抽取成一个私有方法
+ */
+ private CommonResult doPost(String url, T requestBody, String actionName) {
+ log.info("[{}] Sending request to URL: {}", actionName, url);
+ try {
+ // 这里指定返回类型为 CommonResult>,根据后台服务返回的实际结构做调整
+ restTemplate.postForObject(url, requestBody, CommonResult.class);
+ return success(true);
+ } catch (Exception e) {
+ log.error("[{}] Error sending request to URL: {}", actionName, url, e);
+ return CommonResult.error(400, "Request error: " + e.getMessage());
+ }
+ }
+}
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/config/DeviceDataApiInitializer.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/config/DeviceDataApiInitializer.java
new file mode 100644
index 0000000..9473033
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/config/DeviceDataApiInitializer.java
@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.iot.plugin.common.config;
+
+import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
+import cn.iocoder.yudao.module.iot.plugin.common.api.DeviceDataApiClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class DeviceDataApiInitializer {
+
+ @Value("${iot.device-data.url}")
+ private String deviceDataUrl;
+
+ @Bean
+ public RestTemplate restTemplate() {
+ // 如果你有更多的自定义需求,比如连接池、超时时间等,可以在这里设置
+ return new RestTemplateBuilder().build();
+ }
+
+ @Bean
+ public DeviceDataApi deviceDataApi(RestTemplate restTemplate) {
+ // 返回我们自定义的 Client 实例
+ return new DeviceDataApiClient(restTemplate, deviceDataUrl);
+ }
+
+}
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/package-info.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/package-info.java
new file mode 100644
index 0000000..f9eae49
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/package-info.java
@@ -0,0 +1 @@
+package cn.iocoder.yudao.module.iot.plugin.common;
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/plugin.properties b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/plugin.properties
new file mode 100644
index 0000000..7f565b7
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/plugin.properties
@@ -0,0 +1,6 @@
+plugin.id=plugin-emqx
+plugin.class=cn.iocoder.yudao.module.iot.plugin.EmqxPlugin
+plugin.version=1.0.0
+plugin.provider=ahh
+plugin.dependencies=
+plugin.description=plugin-emqx-1.0.0
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/pom.xml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/pom.xml
new file mode 100644
index 0000000..cd89743
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/pom.xml
@@ -0,0 +1,164 @@
+
+
+
+ yudao-module-iot-plugins
+ cn.iocoder.boot
+ ${revision}
+
+ 4.0.0
+ jar
+
+ yudao-module-iot-plugin-emqx
+
+ ${project.artifactId}
+
+ 物联网 插件模块 - emqx 插件
+
+
+
+
+ emqx-plugin
+ cn.iocoder.yudao.module.iot.plugin.EmqxPlugin
+ 0.0.1
+ ahh
+ emqx-plugin-0.0.1
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 1.6
+
+
+ unzip jar file
+ package
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+ maven-assembly-plugin
+ 2.3
+
+
+
+ src/main/assembly/assembly.xml
+
+
+ false
+
+
+
+ make-assembly
+ package
+
+ attached
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+
+ ${plugin.id}
+ ${plugin.class}
+ ${plugin.version}
+ ${plugin.provider}
+ ${plugin.description}
+ ${plugin.dependencies}
+
+
+
+
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.pf4j
+ pf4j-spring
+ provided
+
+
+
+ cn.iocoder.boot
+ yudao-module-iot-api
+ ${revision}
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
+ io.vertx
+ vertx-core
+
+
+
+ io.vertx
+ vertx-web
+
+
+
+ org.eclipse.paho
+ org.eclipse.paho.client.mqttv3
+
+
+
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..daec9e4
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml
@@ -0,0 +1,31 @@
+
+ plugin
+
+ zip
+
+ false
+
+
+ false
+ runtime
+ lib
+
+ *:jar:*
+
+
+
+
+
+
+ target/plugin-classes
+ classes
+
+
+
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java
new file mode 100644
index 0000000..27b9042
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.iot.plugin;
+
+import cn.hutool.extra.spring.SpringUtil;
+import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
+import lombok.extern.slf4j.Slf4j;
+import org.pf4j.Plugin;
+import org.pf4j.PluginWrapper;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@Slf4j
+public class EmqxPlugin extends Plugin {
+
+ private ExecutorService executorService;
+
+ public EmqxPlugin(PluginWrapper wrapper) {
+ super(wrapper);
+ this.executorService = Executors.newSingleThreadExecutor();
+ }
+
+ @Override
+ public void start() {
+ log.info("EmqxPlugin.start()");
+
+ if (executorService.isShutdown() || executorService.isTerminated()) {
+ executorService = Executors.newSingleThreadExecutor();
+ }
+
+ DeviceDataApi deviceDataApi = SpringUtil.getBean(DeviceDataApi.class);
+ if (deviceDataApi == null) {
+ log.error("未能从 ServiceRegistry 获取 DeviceDataApi 实例,请确保主程序已正确注册!");
+ return;
+ }
+
+ }
+
+ @Override
+ public void stop() {
+ log.info("EmqxPlugin.stop()");
+ }
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/plugin.properties b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/plugin.properties
new file mode 100644
index 0000000..bcdce07
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/plugin.properties
@@ -0,0 +1,6 @@
+plugin.id=yudao-module-iot-plugin-http
+plugin.class=cn.iocoder.yudao.module.iot.plugin.http.config.HttpVertxPlugin
+plugin.version=1.0.0
+plugin.provider=yudao
+plugin.dependencies=
+plugin.description=yudao-module-iot-plugin-http-1.0.0
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/pom.xml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/pom.xml
new file mode 100644
index 0000000..15adef3
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/pom.xml
@@ -0,0 +1,136 @@
+
+
+
+ yudao-module-iot-plugins
+ cn.iocoder.boot
+ ${revision}
+
+ 4.0.0
+ jar
+
+ yudao-module-iot-plugin-http
+ 1.0.0
+
+ ${project.artifactId}
+
+ 物联网 插件模块 - http 插件
+
+
+
+
+ ${project.artifactId}
+ cn.iocoder.yudao.module.iot.plugin.http.config.HttpVertxPlugin
+ ${project.version}
+ yudao
+ ${project.artifactId}-${project.version}
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 1.6
+
+
+ unzip jar file
+ package
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+ maven-assembly-plugin
+ 2.3
+
+
+
+ src/main/assembly/assembly.xml
+
+
+ false
+
+
+
+ make-assembly
+ package
+
+ attached
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+
+ ${plugin.id}
+ ${plugin.class}
+ ${plugin.version}
+ ${plugin.provider}
+ ${plugin.description}
+ ${plugin.dependencies}
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.version}
+
+
+
+ repackage
+
+
+ -standalone
+
+
+
+
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+
+
+
+ cn.iocoder.boot
+ yudao-module-iot-plugin-common
+ ${revision}
+
+
+
+ io.vertx
+ vertx-web
+
+
+
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..9b79e61
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml
@@ -0,0 +1,24 @@
+
+ plugin
+
+ zip
+
+ false
+
+
+ false
+ runtime
+ lib
+
+ *:jar:*
+
+
+
+
+
+
+ target/plugin-classes
+ classes
+
+
+
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/HttpPluginSpringbootApplication.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/HttpPluginSpringbootApplication.java
new file mode 100644
index 0000000..74c5651
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/HttpPluginSpringbootApplication.java
@@ -0,0 +1,16 @@
+package cn.iocoder.yudao.module.iot.plugin.http;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication(scanBasePackages = "cn.iocoder.yudao.module.iot.plugin")
+public class HttpPluginSpringbootApplication {
+
+ public static void main(String[] args) {
+ SpringApplication application = new SpringApplication(HttpPluginSpringbootApplication.class);
+ application.setWebApplicationType(WebApplicationType.NONE);
+ application.run(args);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/HttpVertxPlugin.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/HttpVertxPlugin.java
new file mode 100644
index 0000000..e6145b9
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/HttpVertxPlugin.java
@@ -0,0 +1,81 @@
+package cn.iocoder.yudao.module.iot.plugin.http.config;
+
+import cn.hutool.extra.spring.SpringUtil;
+import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
+import cn.iocoder.yudao.module.iot.plugin.http.service.HttpVertxHandler;
+import io.vertx.core.Vertx;
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.handler.BodyHandler;
+import lombok.extern.slf4j.Slf4j;
+import org.pf4j.PluginWrapper;
+import org.pf4j.spring.SpringPlugin;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+@Slf4j
+public class HttpVertxPlugin extends SpringPlugin {
+
+ private static final int PORT = 8092;
+ private Vertx vertx;
+
+ public HttpVertxPlugin(PluginWrapper wrapper) {
+ super(wrapper);
+ }
+
+ @Override
+ public void start() {
+ log.info("HttpVertxPlugin.start()");
+
+ // 获取 DeviceDataApi 实例
+ DeviceDataApi deviceDataApi = SpringUtil.getBean(DeviceDataApi.class);
+ if (deviceDataApi == null) {
+ log.error("未能从 ServiceRegistry 获取 DeviceDataApi 实例,请确保主程序已正确注册!");
+ return;
+ }
+
+ // 初始化 Vert.x
+ vertx = Vertx.vertx();
+ Router router = Router.router(vertx);
+
+ // 处理 Body
+ router.route().handler(BodyHandler.create());
+
+ // 设置路由
+ router.post("/sys/:productKey/:deviceName/thing/event/property/post")
+ .handler(new HttpVertxHandler(deviceDataApi));
+
+ // 启动 HTTP 服务器
+ vertx.createHttpServer()
+ .requestHandler(router)
+ .listen(PORT, http -> {
+ if (http.succeeded()) {
+ log.info("HTTP 服务器启动成功,端口为: {}", PORT);
+ } else {
+ log.error("HTTP 服务器启动失败", http.cause());
+ }
+ });
+ }
+
+ @Override
+ public void stop() {
+ log.info("HttpVertxPlugin.stop()");
+ if (vertx != null) {
+ vertx.close(ar -> {
+ if (ar.succeeded()) {
+ log.info("Vert.x 关闭成功");
+ } else {
+ log.error("Vert.x 关闭失败", ar.cause());
+ }
+ });
+ }
+ }
+
+ @Override
+ protected ApplicationContext createApplicationContext() {
+ AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
+ applicationContext.setClassLoader(getWrapper().getPluginClassLoader());
+ applicationContext.refresh();
+
+ return applicationContext;
+ }
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/HttpVertxPluginConfiguration.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/HttpVertxPluginConfiguration.java
new file mode 100644
index 0000000..b5e977e
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/HttpVertxPluginConfiguration.java
@@ -0,0 +1,16 @@
+package cn.iocoder.yudao.module.iot.plugin.http.config;
+
+import org.pf4j.DefaultPluginManager;
+import org.pf4j.PluginWrapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class HttpVertxPluginConfiguration {
+
+ @Bean(initMethod = "start")
+ public HttpVertxPlugin httpVertxPlugin() {
+ PluginWrapper pluginWrapper = new PluginWrapper(new DefaultPluginManager(), null, null, null);
+ return new HttpVertxPlugin(pluginWrapper);
+ }
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/service/HttpVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/service/HttpVertxHandler.java
new file mode 100644
index 0000000..becba2a
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/service/HttpVertxHandler.java
@@ -0,0 +1,105 @@
+package cn.iocoder.yudao.module.iot.plugin.http.service;
+
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi;
+import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO;
+import io.vertx.core.Handler;
+import io.vertx.ext.web.RequestBody;
+import io.vertx.ext.web.RoutingContext;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class HttpVertxHandler implements Handler {
+
+ private final DeviceDataApi deviceDataApi;
+
+ public HttpVertxHandler(DeviceDataApi deviceDataApi) {
+ this.deviceDataApi = deviceDataApi;
+ }
+
+ @Override
+ public void handle(RoutingContext ctx) {
+ String productKey = ctx.pathParam("productKey");
+ String deviceName = ctx.pathParam("deviceName");
+ RequestBody requestBody = ctx.body();
+
+ JSONObject jsonData;
+ try {
+ jsonData = JSONUtil.parseObj(requestBody.asJsonObject());
+ } catch (Exception e) {
+ JSONObject res = createResponseJson(
+ 400,
+ new JSONObject(),
+ null,
+ "请求数据不是合法的 JSON 格式: " + e.getMessage(),
+ "thing.event.property.post",
+ "1.0");
+ ctx.response()
+ .setStatusCode(400)
+ .putHeader("Content-Type", "application/json; charset=UTF-8")
+ .end(res.toString());
+ return;
+ }
+
+ String id = jsonData.getStr("id", null);
+
+ try {
+ // 调用主程序的接口保存数据
+ IotDevicePropertyReportReqDTO createDTO = IotDevicePropertyReportReqDTO.builder()
+ .productKey(productKey)
+ .deviceName(deviceName)
+ .params(jsonData) // TODO 芋艿:这块要优化
+ .build();
+ deviceDataApi.reportDevicePropertyData(createDTO);
+
+ // 构造成功响应内容
+ JSONObject successRes = createResponseJson(
+ 200,
+ new JSONObject(),
+ id,
+ "success",
+ "thing.event.property.post",
+ "1.0");
+ ctx.response()
+ .setStatusCode(200)
+ .putHeader("Content-Type", "application/json; charset=UTF-8")
+ .end(successRes.toString());
+ } catch (Exception e) {
+ JSONObject errorRes = createResponseJson(
+ 500,
+ new JSONObject(),
+ id,
+ "The format of result is error!",
+ "thing.event.property.post",
+ "1.0");
+ ctx.response()
+ .setStatusCode(500)
+ .putHeader("Content-Type", "application/json; charset=UTF-8")
+ .end(errorRes.toString());
+ }
+ }
+
+ /**
+ * 创建标准化的响应 JSON 对象
+ *
+ * @param code 响应状态码(业务层面的)
+ * @param data 返回的数据对象(JSON)
+ * @param id 请求的 id(可选)
+ * @param message 返回的提示信息
+ * @param method 返回的 method 标识
+ * @param version 返回的版本号
+ * @return 构造好的 JSON 对象
+ */
+ private JSONObject createResponseJson(int code, JSONObject data, String id, String message, String method,
+ String version) {
+ JSONObject res = new JSONObject();
+ res.set("code", code);
+ res.set("data", data != null ? data : new JSONObject());
+ res.set("id", id);
+ res.set("message", message);
+ res.set("method", method);
+ res.set("version", version);
+ return res;
+ }
+}
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/resources/application.yml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/resources/application.yml
new file mode 100644
index 0000000..e98d46e
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/resources/application.yml
@@ -0,0 +1,7 @@
+spring:
+ application:
+ name: yudao-module-iot-plugin-http
+
+iot:
+ device-data:
+ url: http://127.0.0.1:48080
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/plugin.properties b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/plugin.properties
new file mode 100644
index 0000000..939e0f6
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/plugin.properties
@@ -0,0 +1,7 @@
+plugin.id=mqtt-plugin
+plugin.description=Vert.x MQTT plugin
+plugin.class=cn.iocoder.yudao.module.iot.plugin.MqttPlugin
+plugin.version=1.0.0
+plugin.requires=
+plugin.provider=ahh
+plugin.license=Apache-2.0
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/pom.xml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/pom.xml
new file mode 100644
index 0000000..e007596
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/pom.xml
@@ -0,0 +1,155 @@
+
+
+
+ yudao-module-iot-plugins
+ cn.iocoder.boot
+ ${revision}
+
+ 4.0.0
+ jar
+
+ yudao-module-iot-plugin-mqtt
+
+ ${project.artifactId}
+
+ 物联网 插件模块 - mqtt 插件
+
+
+
+
+ mqtt-plugin
+ cn.iocoder.yudao.module.iot.plugin.MqttPlugin
+ 0.0.1
+ ahh
+ mqtt-plugin-0.0.1
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 1.6
+
+
+ unzip jar file
+ package
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+ maven-assembly-plugin
+ 2.3
+
+
+
+ src/main/assembly/assembly.xml
+
+
+ false
+
+
+
+ make-assembly
+ package
+
+ attached
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+
+ ${plugin.id}
+ ${plugin.class}
+ ${plugin.version}
+ ${plugin.provider}
+ ${plugin.description}
+ ${plugin.dependencies}
+
+
+
+
+
+
+ maven-deploy-plugin
+
+ true
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.pf4j
+ pf4j-spring
+ provided
+
+
+
+ cn.iocoder.boot
+ yudao-module-iot-api
+ ${revision}
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
+ io.vertx
+ vertx-mqtt
+ 4.5.11
+
+
+
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..daec9e4
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml
@@ -0,0 +1,31 @@
+
+ plugin
+
+ zip
+
+ false
+
+
+ false
+ runtime
+ lib
+
+ *:jar:*
+
+
+
+
+
+
+ target/plugin-classes
+ classes
+
+
+
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java
new file mode 100644
index 0000000..54ff31f
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.iot.plugin;
+
+import lombok.extern.slf4j.Slf4j;
+import org.pf4j.Plugin;
+import org.pf4j.PluginWrapper;
+
+@Slf4j
+public class MqttPlugin extends Plugin {
+
+ private MqttServerExtension mqttServerExtension;
+
+ public MqttPlugin(PluginWrapper wrapper) {
+ super(wrapper);
+ }
+
+ @Override
+ public void start() {
+ log.info("MQTT Plugin started.");
+ mqttServerExtension = new MqttServerExtension();
+ mqttServerExtension.startMqttServer();
+ }
+
+ @Override
+ public void stop() {
+ log.info("MQTT Plugin stopped.");
+ if (mqttServerExtension != null) {
+ mqttServerExtension.stopMqttServer().onComplete(ar -> {
+ if (ar.succeeded()) {
+ log.info("Stopped MQTT Server successfully");
+ } else {
+ log.error("Failed to stop MQTT Server: {}", ar.cause().getMessage());
+ }
+ });
+ }
+ }
+}
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java
new file mode 100644
index 0000000..868d238
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java
@@ -0,0 +1,231 @@
+package cn.iocoder.yudao.module.iot.plugin;
+
+import io.netty.handler.codec.mqtt.MqttProperties;
+import io.netty.handler.codec.mqtt.MqttQoS;
+import io.vertx.core.Future;
+import io.vertx.core.Vertx;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.mqtt.MqttEndpoint;
+import io.vertx.mqtt.MqttServer;
+import io.vertx.mqtt.MqttServerOptions;
+import io.vertx.mqtt.MqttTopicSubscription;
+import io.vertx.mqtt.messages.MqttDisconnectMessage;
+import io.vertx.mqtt.messages.MqttPublishMessage;
+import io.vertx.mqtt.messages.MqttSubscribeMessage;
+import io.vertx.mqtt.messages.MqttUnsubscribeMessage;
+import io.vertx.mqtt.messages.codes.MqttSubAckReasonCode;
+import lombok.extern.slf4j.Slf4j;
+import org.pf4j.Extension;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 根据官方示例,整合常见 MQTT 功能到 PF4J 的 Extension 类中
+ */
+@Slf4j
+@Extension
+public class MqttServerExtension {
+
+ private Vertx vertx;
+ private MqttServer mqttServer;
+
+ /**
+ * 启动 MQTT 服务端
+ * 可根据需要决定是否启用 SSL/TLS、WebSocket、多实例部署等
+ */
+ public void startMqttServer() {
+ // 初始化 Vert.x
+ vertx = Vertx.vertx();
+
+ // ========== 如果需要 SSL/TLS,请参考下面注释,启用注释并替换端口、证书路径等 ==========
+ // MqttServerOptions options = new MqttServerOptions()
+ // .setPort(8883)
+ // .setKeyCertOptions(new PemKeyCertOptions()
+ // .setKeyPath("./src/test/resources/tls/server-key.pem")
+ // .setCertPath("./src/test/resources/tls/server-cert.pem"))
+ // .setSsl(true);
+
+ // ========== 如果需要 WebSocket,请设置 setUseWebSocket(true) ==========
+ // options.setUseWebSocket(true);
+
+ // ========== 默认不启用 SSL 的示例 ==========
+ MqttServerOptions options = new MqttServerOptions()
+ .setPort(1883)
+ .setHost("0.0.0.0")
+ .setUseWebSocket(false); // 如果需要 WebSocket,请改为 true
+
+ mqttServer = MqttServer.create(vertx, options);
+
+ // 指定 endpointHandler,处理客户端连接等
+ mqttServer.endpointHandler(endpoint -> {
+ handleClientConnect(endpoint);
+ handleDisconnect(endpoint);
+ handleSubscribe(endpoint);
+ handleUnsubscribe(endpoint);
+ handlePublish(endpoint);
+ handlePing(endpoint);
+ });
+
+ // 启动监听
+ mqttServer.listen(ar -> {
+ if (ar.succeeded()) {
+ log.info("MQTT server is listening on port {}", mqttServer.actualPort());
+ } else {
+ log.error("Error on starting the server", ar.cause());
+ }
+ });
+ }
+
+ /**
+ * 优雅关闭 MQTT 服务端
+ */
+ public Future stopMqttServer() {
+ if (mqttServer != null) {
+ return mqttServer.close().onComplete(ar -> {
+ if (ar.succeeded()) {
+ log.info("MQTT server closed.");
+ if (vertx != null) {
+ vertx.close();
+ log.info("Vert.x instance closed.");
+ }
+ } else {
+ log.error("Failed to close MQTT server: {}", ar.cause().getMessage());
+ }
+ });
+ }
+ return Future.succeededFuture();
+ }
+
+ // ==================== 以下为官方示例中常见事件的处理封装 ====================
+
+ /**
+ * 处理客户端连接 (CONNECT)
+ */
+ private void handleClientConnect(MqttEndpoint endpoint) {
+ // 打印 CONNECT 的主要信息
+ log.info("MQTT client [{}] request to connect, clean session = {}",
+ endpoint.clientIdentifier(), endpoint.isCleanSession());
+
+ if (endpoint.auth() != null) {
+ log.info("[username = {}, password = {}]", endpoint.auth().getUsername(), endpoint.auth().getPassword());
+ }
+ log.info("[properties = {}]", endpoint.connectProperties());
+
+ if (endpoint.will() != null) {
+ log.info("[will topic = {}, msg = {}, QoS = {}, isRetain = {}]",
+ endpoint.will().getWillTopic(),
+ new String(endpoint.will().getWillMessageBytes()),
+ endpoint.will().getWillQos(),
+ endpoint.will().isWillRetain());
+ }
+
+ log.info("[keep alive timeout = {}]", endpoint.keepAliveTimeSeconds());
+
+ // 接受远程客户端的连接
+ endpoint.accept(false);
+ }
+
+ /**
+ * 处理客户端主动断开 (DISCONNECT)
+ */
+ private void handleDisconnect(MqttEndpoint endpoint) {
+ endpoint.disconnectMessageHandler((MqttDisconnectMessage disconnectMessage) -> {
+ log.info("Received disconnect from client [{}], reason code = {}",
+ endpoint.clientIdentifier(), disconnectMessage.code());
+ });
+ }
+
+ /**
+ * 处理客户端订阅 (SUBSCRIBE)
+ */
+ private void handleSubscribe(MqttEndpoint endpoint) {
+ endpoint.subscribeHandler((MqttSubscribeMessage subscribe) -> {
+ List reasonCodes = new ArrayList<>();
+ for (MqttTopicSubscription s : subscribe.topicSubscriptions()) {
+ log.info("Subscription for {} with QoS {}", s.topicName(), s.qualityOfService());
+ // 将客户端请求的 QoS 转换为返回给客户端的 reason code(可能是错误码或实际 granted QoS)
+ reasonCodes.add(MqttSubAckReasonCode.qosGranted(s.qualityOfService()));
+ }
+ // 回复 SUBACK,MQTT 5.0 时可指定 reasonCodes、properties
+ endpoint.subscribeAcknowledge(subscribe.messageId(), reasonCodes, MqttProperties.NO_PROPERTIES);
+ });
+ }
+
+ /**
+ * 处理客户端取消订阅 (UNSUBSCRIBE)
+ */
+ private void handleUnsubscribe(MqttEndpoint endpoint) {
+ endpoint.unsubscribeHandler((MqttUnsubscribeMessage unsubscribe) -> {
+ for (String topic : unsubscribe.topics()) {
+ log.info("Unsubscription for {}", topic);
+ }
+ // 回复 UNSUBACK,MQTT 5.0 时可指定 reasonCodes、properties
+ endpoint.unsubscribeAcknowledge(unsubscribe.messageId());
+ });
+ }
+
+ /**
+ * 处理客户端发布的消息 (PUBLISH)
+ */
+ private void handlePublish(MqttEndpoint endpoint) {
+ // 接收 PUBLISH 消息
+ endpoint.publishHandler((MqttPublishMessage message) -> {
+ String payload = message.payload().toString(Charset.defaultCharset());
+ log.info("Received message [{}] on topic [{}] with QoS [{}]",
+ payload, message.topicName(), message.qosLevel());
+
+ // 根据不同 QoS,回复客户端
+ if (message.qosLevel() == MqttQoS.AT_LEAST_ONCE) {
+ endpoint.publishAcknowledge(message.messageId());
+ } else if (message.qosLevel() == MqttQoS.EXACTLY_ONCE) {
+ endpoint.publishReceived(message.messageId());
+ }
+ });
+
+ // 如果 QoS = 2,需要处理 PUBREL
+ endpoint.publishReleaseHandler(messageId -> {
+ endpoint.publishComplete(messageId);
+ });
+ }
+
+ /**
+ * 处理客户端 PINGREQ
+ */
+ private void handlePing(MqttEndpoint endpoint) {
+ endpoint.pingHandler(v -> {
+ // 这里仅做日志, PINGRESP 已自动发送
+ log.info("Ping received from client [{}]", endpoint.clientIdentifier());
+ });
+ }
+
+ // ==================== 如果需要服务端向客户端发布消息,可用以下示例 ====================
+
+ /**
+ * 服务端主动向已连接的某个 endpoint 发布消息的示例
+ * 如果使用 MQTT 5.0,可以传递更多消息属性
+ */
+ public void publishToClient(MqttEndpoint endpoint, String topic, String content) {
+ endpoint.publish(topic,
+ Buffer.buffer(content),
+ MqttQoS.AT_LEAST_ONCE, // QoS 自行选择
+ false,
+ false);
+
+ // 处理 QoS 1 和 QoS 2 的 ACK
+ endpoint.publishAcknowledgeHandler(messageId -> {
+ log.info("Received PUBACK from client [{}] for messageId = {}", endpoint.clientIdentifier(), messageId);
+ }).publishReceivedHandler(messageId -> {
+ endpoint.publishRelease(messageId);
+ }).publishCompletionHandler(messageId -> {
+ log.info("Received PUBCOMP from client [{}] for messageId = {}", endpoint.clientIdentifier(), messageId);
+ });
+ }
+
+ // ==================== 如果需要多实例部署,用于多核扩展,可参考以下思路 ====================
+ // 例如,在宿主应用或插件中循环启动多个 MqttServerExtension 实例,或使用 Vert.x 的 deployVerticle:
+ // DeploymentOptions options = new DeploymentOptions().setInstances(10);
+ // vertx.deployVerticle(() -> new MyMqttVerticle(), options);
+
+}
--
libgit2 0.21.4