From a152f6d98fe7295f8abd6b7096b388f0ca3dee42 Mon Sep 17 00:00:00 2001 From: 安浩浩 <1036606149@qq.com> Date: Tue, 21 Jan 2025 18:18:28 +0800 Subject: [PATCH] 【功能完善】IoT: 删除旧版 HTTP 插件,新增 HTTP 和 MQTT 插件,重构插件管理逻辑,优化代码结构,支持 EMQX 插件,更新相关配置文件。 --- plugins/yudao-module-iot-http-plugin-2.2.0-snapshot.jar | Bin 8535 -> 0 bytes plugins/yudao-module-iot-plugin-http-1.0.0.jar | Bin 0 -> 10643 bytes yudao-module-iot/yudao-module-iot-plugin/pom.xml | 6 +++--- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/plugin.properties | 6 ------ yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/pom.xml | 148 ---------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/src/main/assembly/assembly.xml | 31 ------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/DemoPlugin.java | 77 ----------------------------------------------------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/plugin.properties | 6 ------ yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/pom.xml | 164 -------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/src/main/assembly/assembly.xml | 31 ------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java | 45 --------------------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/dependency-reduced-pom.xml | 81 --------------------------------------------------------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/plugin.properties | 6 ------ yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/pom.xml | 157 ------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/assembly/assembly.xml | 31 ------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java | 13 ------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java | 34 ---------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/HttpVertxHandler.java | 105 --------------------------------------------------------------------------------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/HttpVertxPlugin.java | 82 ---------------------------------------------------------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/resources/application.yml | 12 ------------ yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/plugin.properties | 7 ------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/pom.xml | 155 ----------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/src/main/assembly/assembly.xml | 31 ------------------------------- yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java | 36 ------------------------------------ yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java | 231 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 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 | 13 +++++++++++++ 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 | 33 +++++++++++++++++++++++++++++++++ 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 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 43 files changed, 1164 insertions(+), 1492 deletions(-) delete mode 100644 plugins/yudao-module-iot-http-plugin-2.2.0-snapshot.jar create mode 100644 plugins/yudao-module-iot-plugin-http-1.0.0.jar delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/plugin.properties delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/pom.xml delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/src/main/assembly/assembly.xml delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/DemoPlugin.java delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/plugin.properties delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/pom.xml delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/src/main/assembly/assembly.xml delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/dependency-reduced-pom.xml delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/plugin.properties delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/pom.xml delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/assembly/assembly.xml delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/HttpVertxHandler.java delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/HttpVertxPlugin.java delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/resources/application.yml delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/plugin.properties delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/pom.xml delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/src/main/assembly/assembly.xml delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java delete mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/plugin.properties create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/pom.xml create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/src/main/assembly/assembly.xml create 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 create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/dependency-reduced-pom.xml create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/plugin.properties create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/assembly/assembly.xml create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java create 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 create 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 create 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 create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/resources/application.yml create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/plugin.properties create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/pom.xml create mode 100644 yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/src/main/assembly/assembly.xml create 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 create 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 diff --git a/plugins/yudao-module-iot-http-plugin-2.2.0-snapshot.jar b/plugins/yudao-module-iot-http-plugin-2.2.0-snapshot.jar deleted file mode 100644 index 8b5e72b..0000000 Binary files a/plugins/yudao-module-iot-http-plugin-2.2.0-snapshot.jar and /dev/null differ diff --git a/plugins/yudao-module-iot-plugin-http-1.0.0.jar b/plugins/yudao-module-iot-plugin-http-1.0.0.jar new file mode 100644 index 0000000..a1d4db6 Binary files /dev/null and b/plugins/yudao-module-iot-plugin-http-1.0.0.jar differ diff --git a/yudao-module-iot/yudao-module-iot-plugin/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/pom.xml index 4a46b61..949ff13 100644 --- a/yudao-module-iot/yudao-module-iot-plugin/pom.xml +++ b/yudao-module-iot/yudao-module-iot-plugin/pom.xml @@ -8,9 +8,9 @@ ${revision} - yudao-module-iot-demo-plugin - yudao-module-iot-http-plugin - yudao-module-iot-mqtt-plugin + yudao-module-iot-plugin-http + yudao-module-iot-plugin-mqtt + yudao-module-iot-plugin-emqx 4.0.0 diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/plugin.properties b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/plugin.properties deleted file mode 100644 index 5a67270..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/plugin.properties +++ /dev/null @@ -1,6 +0,0 @@ -plugin.id=demo-plugin -plugin.class=cn.iocoder.yudao.module.iot.plugin.DemoPlugin -plugin.version=0.0.1 -plugin.provider=ahh -plugin.dependencies= -plugin.description=demo-plugin diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/pom.xml deleted file mode 100644 index 3d58a1a..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/pom.xml +++ /dev/null @@ -1,148 +0,0 @@ - - - - yudao-module-iot-plugin - cn.iocoder.boot - ${revision} - - 4.0.0 - jar - - yudao-module-iot-demo-plugin - - ${project.artifactId} - - 物联网 插件模块 - demo 插件 - - - - - demo-plugin - cn.iocoder.yudao.module.iot.plugin.DemoPlugin - 0.0.1 - ahh - - - - - - - - - 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.dependencies} - - - - - - - maven-deploy-plugin - - true - - - - - - - - - org.springframework.boot - spring-boot-starter-web - ${spring.boot.version} - provided - - - - org.pf4j - pf4j-spring - provided - - - - cn.iocoder.boot - yudao-module-iot-api - ${revision} - - - org.projectlombok - lombok - ${lombok.version} - provided - - - \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/src/main/assembly/assembly.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/src/main/assembly/assembly.xml deleted file mode 100644 index daec9e4..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/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-demo-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/DemoPlugin.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/DemoPlugin.java deleted file mode 100644 index c97a5b9..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-demo-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/DemoPlugin.java +++ /dev/null @@ -1,77 +0,0 @@ -package cn.iocoder.yudao.module.iot.plugin; - -import com.sun.net.httpserver.HttpServer; -import lombok.extern.slf4j.Slf4j; -import org.pf4j.Plugin; -import org.pf4j.PluginWrapper; -import org.pf4j.RuntimeMode; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.InetSocketAddress; - -/** - * 一个启动 HTTP 服务器的简单插件。 - */ -@Slf4j -public class DemoPlugin extends Plugin { - - private HttpServer server; - - public DemoPlugin(PluginWrapper wrapper) { - super(wrapper); - } - - @Override - public void start() { - log.info("Demo 插件启动"); - // for testing the development mode - if (RuntimeMode.DEVELOPMENT.equals(wrapper.getRuntimeMode())) { - log.info("DemoPlugin in DEVELOPMENT mode"); - } - startDemoServer(); - } - - @Override - public void stop() { - log.info("Demo 插件停止"); - stopDemoServer(); - } - - private void startDemoServer() { - try { - server = HttpServer.create(new InetSocketAddress(9081), 0); - server.createContext("/", exchange -> { - String response = "Hello from DemoPlugin"; - exchange.sendResponseHeaders(200, response.getBytes().length); - OutputStream os = exchange.getResponseBody(); - os.write(response.getBytes()); - os.close(); - }); - server.setExecutor(null); - server.start(); - log.info("HTTP 服务器启动成功,端口为 9081"); - log.info("访问地址为 http://127.0.0.1:9081/"); - } catch (IOException e) { - log.error("HTTP 服务器启动失败", e); - } - } - - private void stopDemoServer() { - if (server != null) { - server.stop(0); - log.info("HTTP 服务器停止成功"); - } - } - -// @Extension -// public static class WelcomeGreeting implements Greeting { -// -// @Override -// public String getGreeting() { -// return "Welcome to DemoPlugin"; -// } -// -// } - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/plugin.properties b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/plugin.properties deleted file mode 100644 index a23bafc..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/plugin.properties +++ /dev/null @@ -1,6 +0,0 @@ -plugin.id=emqx-plugin -plugin.class=cn.iocoder.yudao.module.iot.plugin.EmqxPlugin -plugin.version=0.0.1 -plugin.provider=ahh -plugin.dependencies= -plugin.description=emqx-plugin-0.0.1 diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/pom.xml deleted file mode 100644 index 43d67f5..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/pom.xml +++ /dev/null @@ -1,164 +0,0 @@ - - - - yudao-module-iot-plugin - cn.iocoder.boot - ${revision} - - 4.0.0 - jar - - yudao-module-iot-emqx-plugin - - ${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-emqx-plugin/src/main/assembly/assembly.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/src/main/assembly/assembly.xml deleted file mode 100644 index daec9e4..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/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-emqx-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java deleted file mode 100644 index e64695b..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-emqx-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/EmqxPlugin.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.iot.plugin; - -import cn.iocoder.yudao.module.iot.api.ServiceRegistry; -import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi; -import lombok.extern.slf4j.Slf4j; -import org.pf4j.Plugin; -import org.pf4j.PluginWrapper; - -import javax.annotation.Resource; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -@Slf4j -public class EmqxPlugin extends Plugin { - - private ExecutorService executorService; - @Resource - private DeviceDataApi deviceDataApi; - - 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 = ServiceRegistry.getService(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-http-plugin/dependency-reduced-pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/dependency-reduced-pom.xml deleted file mode 100644 index f4ec60d..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/dependency-reduced-pom.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - yudao-module-iot-plugin - cn.iocoder.boot - 2.2.0-snapshot - - 4.0.0 - yudao-module-iot-http-plugin - ${project.artifactId} - 2.2.0-snapshot - 物联网 插件模块 - http 插件 - - - - maven-jar-plugin - 2.4 - - - - ${plugin.id} - ${plugin.class} - ${plugin.version} - ${plugin.provider} - ${plugin.description} - ${plugin.dependencies} - - - - - - maven-deploy-plugin - - true - - - - maven-shade-plugin - 3.4.1 - - - package - - shade - - - true - shaded - - - cn.iocoder.yudao.module.iot.HttpPluginSpringbootApplication - - - - - - - - - - - org.pf4j - pf4j-spring - 0.9.0 - provided - - - org.projectlombok - lombok - 1.18.34 - provided - - - - cn.iocoder.yudao.module.iot.plugin.HttpVertxPlugin - 0.0.1 - http-plugin - http-plugin-0.0.1 - ahh - - diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/plugin.properties b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/plugin.properties deleted file mode 100644 index 44f221c..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/plugin.properties +++ /dev/null @@ -1,6 +0,0 @@ -plugin.id=http-plugin -plugin.class=cn.iocoder.yudao.module.iot.plugin.HttpVertxPlugin -plugin.version=0.0.1 -plugin.provider=ahh -plugin.dependencies= -plugin.description=http-plugin-0.0.1 diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/pom.xml deleted file mode 100644 index 4658a1f..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/pom.xml +++ /dev/null @@ -1,157 +0,0 @@ - - - - yudao-module-iot-plugin - cn.iocoder.boot - ${revision} - - 4.0.0 - jar - - yudao-module-iot-http-plugin - - ${project.artifactId} - - 物联网 插件模块 - http 插件 - - - - - http-plugin - cn.iocoder.yudao.module.iot.plugin.HttpVertxPlugin - 0.0.1 - ahh - http-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 - - - - org.pf4j - pf4j-spring - provided - - - - cn.iocoder.boot - yudao-module-iot-api - ${revision} - - - org.projectlombok - lombok - ${lombok.version} - provided - - - - io.vertx - vertx-web - 4.5.11 - - - \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/assembly/assembly.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/assembly/assembly.xml deleted file mode 100644 index daec9e4..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/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-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java deleted file mode 100644 index 2b871ca..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.iot; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class HttpPluginSpringbootApplication { - - public static void main(String[] args) { - SpringApplication.run(HttpPluginSpringbootApplication.class, args); - } - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java deleted file mode 100644 index b32a1f5..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.iot.config; - -import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi; -import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO; -import cn.iocoder.yudao.module.iot.plugin.HttpVertxPlugin; -import org.pf4j.DefaultPluginManager; -import org.pf4j.PluginWrapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -// TODO 芋艿:临时实现; -@Configuration -public class TestConfiguration { - - @Bean - public DeviceDataApi deviceDataApi() { - return new DeviceDataApi() { - - @Override - public void saveDeviceData(DeviceDataCreateReqDTO createDTO) { - System.out.println("saveDeviceData"); - } - - }; - } - - // 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-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/HttpVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/HttpVertxHandler.java deleted file mode 100644 index 335d6c9..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/HttpVertxHandler.java +++ /dev/null @@ -1,105 +0,0 @@ -package cn.iocoder.yudao.module.iot.plugin; - -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.DeviceDataCreateReqDTO; -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 { - // 调用主程序的接口保存数据 - DeviceDataCreateReqDTO createDTO = DeviceDataCreateReqDTO.builder() - .productKey(productKey) - .deviceName(deviceName) - .message(jsonData.toString()) - .build(); - deviceDataApi.saveDeviceData(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-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/HttpVertxPlugin.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/HttpVertxPlugin.java deleted file mode 100644 index 54d9c7c..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/HttpVertxPlugin.java +++ /dev/null @@ -1,82 +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 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; - - private DeviceDataApi deviceDataApi; - - public HttpVertxPlugin(PluginWrapper wrapper) { - super(wrapper); - } - - @Override - public void start() { - log.info("HttpVertxPlugin.start()"); - - // 获取 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-http-plugin/src/main/resources/application.yml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/resources/application.yml deleted file mode 100644 index 9056af4..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-http-plugin/src/main/resources/application.yml +++ /dev/null @@ -1,12 +0,0 @@ -spring: - application: - name: yudao-module-iot-http-plugin - -# MQTT-RPC 配置 -mqtt: - broker: tcp://chaojiniu.top:1883 - username: haohao - password: ahh@123456 - clientId: mqtt-rpc-client-${random.int} - requestTopic: rpc/request - responseTopicPrefix: rpc/response/ diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/plugin.properties b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/plugin.properties deleted file mode 100644 index 939e0f6..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/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-mqtt-plugin/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/pom.xml deleted file mode 100644 index 462fbd0..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/pom.xml +++ /dev/null @@ -1,155 +0,0 @@ - - - - yudao-module-iot-plugin - cn.iocoder.boot - ${revision} - - 4.0.0 - jar - - yudao-module-iot-mqtt-plugin - - ${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-mqtt-plugin/src/main/assembly/assembly.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/src/main/assembly/assembly.xml deleted file mode 100644 index daec9e4..0000000 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/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-mqtt-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/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-mqtt-plugin/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-mqtt-plugin/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-mqtt-plugin/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-mqtt-plugin/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-plugin/yudao-module-iot-plugin-emqx/plugin.properties b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/plugin.properties new file mode 100644 index 0000000..7f565b7 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/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-plugin/yudao-module-iot-plugin-emqx/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/pom.xml new file mode 100644 index 0000000..266e45f --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-emqx/pom.xml @@ -0,0 +1,164 @@ + + + + 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 new file mode 100644 index 0000000..daec9e4 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/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-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 new file mode 100644 index 0000000..27b9042 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/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-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 new file mode 100644 index 0000000..260ef9c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/dependency-reduced-pom.xml @@ -0,0 +1,43 @@ + + + + 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 new file mode 100644 index 0000000..49aef5b --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/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.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 new file mode 100644 index 0000000..40bb303 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml @@ -0,0 +1,150 @@ + + + + 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 + + + + 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 new file mode 100644 index 0000000..9b79e61 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/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-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 new file mode 100644 index 0000000..2b871ca --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.iot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class HttpPluginSpringbootApplication { + + public static void main(String[] args) { + SpringApplication.run(HttpPluginSpringbootApplication.class, args); + } + +} \ 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 new file mode 100644 index 0000000..d77f990 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/HttpVertxPlugin.java @@ -0,0 +1,81 @@ +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 new file mode 100644 index 0000000..1931268 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.iot.config; + +import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi; +import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO; +import org.pf4j.DefaultPluginManager; +import org.pf4j.PluginWrapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +// TODO 芋艿:临时实现; +@Configuration +public class TestConfiguration { + + @Bean + public DeviceDataApi deviceDataApi() { + return new DeviceDataApi() { + + @Override + public void saveDeviceData(DeviceDataCreateReqDTO createDTO) { + System.out.println("saveDeviceData"); + } + + }; + } + + // 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 new file mode 100644 index 0000000..8542cfe --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/service/HttpVertxHandler.java @@ -0,0 +1,105 @@ +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.DeviceDataCreateReqDTO; +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 { + // 调用主程序的接口保存数据 + DeviceDataCreateReqDTO createDTO = DeviceDataCreateReqDTO.builder() + .productKey(productKey) + .deviceName(deviceName) + .message(jsonData.toString()) + .build(); + deviceDataApi.saveDeviceData(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 new file mode 100644 index 0000000..c5a1ee8 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/resources/application.yml @@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000..939e0f6 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/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-plugin/yudao-module-iot-plugin-mqtt/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/pom.xml new file mode 100644 index 0000000..7e4689b --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-mqtt/pom.xml @@ -0,0 +1,155 @@ + + + + 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 new file mode 100644 index 0000000..daec9e4 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/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-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 new file mode 100644 index 0000000..54ff31f --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/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-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 new file mode 100644 index 0000000..868d238 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-plugin/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