result = deviceDownstreamHandler.setDeviceConfig(reqDTO);
-
- // 3. 响应结果
- IotStandardResponse response = result.isSuccess() ?
- IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData())
- : IotStandardResponse.error(reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, response);
- } catch (Exception e) {
- log.error("[handle][请求参数({}) 配置设置异常]", reqDTO, e);
- IotStandardResponse errorResponse = IotStandardResponse.error(
- reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- }
- }
-
-}
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/downstream/router/IotDeviceOtaUpgradeVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDeviceOtaUpgradeVertxHandler.java
deleted file mode 100644
index b417229aae..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDeviceOtaUpgradeVertxHandler.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.common.downstream.router;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceOtaUpgradeReqDTO;
-import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
-import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
-import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
-import io.vertx.core.Handler;
-import io.vertx.core.json.JsonObject;
-import io.vertx.ext.web.RoutingContext;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
-
-/**
- * IoT 设备 OTA 升级 Vertx Handler
- *
- * 芋道源码
- */
-@Slf4j
-@RequiredArgsConstructor
-public class IotDeviceOtaUpgradeVertxHandler implements Handler {
-
- public static final String PATH = "/ota/:productKey/:deviceName/upgrade";
- public static final String METHOD = "ota.device.upgrade";
-
- private final IotDeviceDownstreamHandler deviceDownstreamHandler;
-
- @Override
- public void handle(RoutingContext routingContext) {
- // 1. 解析参数
- IotDeviceOtaUpgradeReqDTO reqDTO;
- try {
- String productKey = routingContext.pathParam("productKey");
- String deviceName = routingContext.pathParam("deviceName");
- JsonObject body = routingContext.body().asJsonObject();
- String requestId = body.getString("requestId");
- Long firmwareId = body.getLong("firmwareId");
- String version = body.getString("version");
- String signMethod = body.getString("signMethod");
- String fileSign = body.getString("fileSign");
- Long fileSize = body.getLong("fileSize");
- String fileUrl = body.getString("fileUrl");
- String information = body.getString("information");
- reqDTO = ((IotDeviceOtaUpgradeReqDTO) new IotDeviceOtaUpgradeReqDTO()
- .setRequestId(requestId).setProductKey(productKey).setDeviceName(deviceName))
- .setFirmwareId(firmwareId).setVersion(version)
- .setSignMethod(signMethod).setFileSign(fileSign).setFileSize(fileSize).setFileUrl(fileUrl)
- .setInformation(information);
- } catch (Exception e) {
- log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
- IotStandardResponse errorResponse = IotStandardResponse.error(
- null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- return;
- }
-
- // 2. 调用处理器
- try {
- CommonResult result = deviceDownstreamHandler.upgradeDeviceOta(reqDTO);
-
- // 3. 响应结果
- // TODO @haohao:可以考虑 IotStandardResponse.of(requestId, method, CommonResult)
- IotStandardResponse response = result.isSuccess() ?
- IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData())
- :IotStandardResponse.error(reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, response);
- } catch (Exception e) {
- log.error("[handle][请求参数({}) OTA 升级异常]", reqDTO, e);
- // TODO @haohao:可以考虑 IotStandardResponse.of(requestId, method, ErrorCode)
- IotStandardResponse errorResponse = IotStandardResponse.error(
- reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- }
- }
-}
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/downstream/router/IotDevicePropertyGetVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDevicePropertyGetVertxHandler.java
deleted file mode 100644
index 3cb4bc941d..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDevicePropertyGetVertxHandler.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.common.downstream.router;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;
-import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
-import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
-import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
-import io.vertx.core.Handler;
-import io.vertx.core.json.JsonObject;
-import io.vertx.ext.web.RoutingContext;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
-
-/**
- * IoT 设备服务获取 Vertx Handler
- *
- * 芋道源码
- */
-@Slf4j
-@RequiredArgsConstructor
-public class IotDevicePropertyGetVertxHandler implements Handler {
-
- public static final String PATH = "/sys/:productKey/:deviceName/thing/service/property/get";
- public static final String METHOD = "thing.service.property.get";
-
- private final IotDeviceDownstreamHandler deviceDownstreamHandler;
-
- @Override
- @SuppressWarnings("unchecked")
- public void handle(RoutingContext routingContext) {
- // 1. 解析参数
- IotDevicePropertyGetReqDTO reqDTO;
- try {
- String productKey = routingContext.pathParam("productKey");
- String deviceName = routingContext.pathParam("deviceName");
- JsonObject body = routingContext.body().asJsonObject();
- String requestId = body.getString("requestId");
- List identifiers = (List) body.getMap().get("identifiers");
- reqDTO = ((IotDevicePropertyGetReqDTO) new IotDevicePropertyGetReqDTO()
- .setRequestId(requestId).setProductKey(productKey).setDeviceName(deviceName))
- .setIdentifiers(identifiers);
- } catch (Exception e) {
- log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
- IotStandardResponse errorResponse = IotStandardResponse.error(
- null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- return;
- }
-
- // 2. 调用处理器
- try {
- CommonResult result = deviceDownstreamHandler.getDeviceProperty(reqDTO);
-
- // 3. 响应结果
- IotStandardResponse response;
- if (result.isSuccess()) {
- response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData());
- } else {
- response = IotStandardResponse.error(reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
- }
- IotPluginCommonUtils.writeJsonResponse(routingContext, response);
- } catch (Exception e) {
- log.error("[handle][请求参数({}) 属性获取异常]", reqDTO, e);
- IotStandardResponse errorResponse = IotStandardResponse.error(
- reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- }
- }
-
-}
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/downstream/router/IotDevicePropertySetVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDevicePropertySetVertxHandler.java
deleted file mode 100644
index 251be1eb9d..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDevicePropertySetVertxHandler.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.common.downstream.router;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO;
-import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
-import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
-import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
-import io.vertx.core.Handler;
-import io.vertx.core.json.JsonObject;
-import io.vertx.ext.web.RoutingContext;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Map;
-
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
-
-/**
- * IoT 设置设备属性 Vertx Handler
- *
- * 芋道源码
- */
-@Slf4j
-@RequiredArgsConstructor
-public class IotDevicePropertySetVertxHandler implements Handler {
-
- public static final String PATH = "/sys/:productKey/:deviceName/thing/service/property/set";
- public static final String METHOD = "thing.service.property.set";
-
- private final IotDeviceDownstreamHandler deviceDownstreamHandler;
-
- @Override
- @SuppressWarnings("unchecked")
- public void handle(RoutingContext routingContext) {
- // 1. 解析参数
- IotDevicePropertySetReqDTO reqDTO;
- try {
- String productKey = routingContext.pathParam("productKey");
- String deviceName = routingContext.pathParam("deviceName");
- JsonObject body = routingContext.body().asJsonObject();
- String requestId = body.getString("requestId");
- Map properties = (Map) body.getMap().get("properties");
- reqDTO = ((IotDevicePropertySetReqDTO) new IotDevicePropertySetReqDTO()
- .setRequestId(requestId).setProductKey(productKey).setDeviceName(deviceName))
- .setProperties(properties);
- } catch (Exception e) {
- log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
- IotStandardResponse errorResponse = IotStandardResponse.error(
- null, METHOD, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- return;
- }
-
- // 2. 调用处理器
- try {
- CommonResult result = deviceDownstreamHandler.setDeviceProperty(reqDTO);
-
- // 3. 响应结果
- IotStandardResponse response;
- if (result.isSuccess()) {
- response = IotStandardResponse.success(reqDTO.getRequestId(), METHOD, result.getData());
- } else {
- response = IotStandardResponse.error(reqDTO.getRequestId(), METHOD, result.getCode(), result.getMsg());
- }
- IotPluginCommonUtils.writeJsonResponse(routingContext, response);
- } catch (Exception e) {
- log.error("[handle][请求参数({}) 属性设置异常]", reqDTO, e);
- IotStandardResponse errorResponse = IotStandardResponse.error(
- reqDTO.getRequestId(), METHOD, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- }
- }
-
-}
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/downstream/router/IotDeviceServiceInvokeVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDeviceServiceInvokeVertxHandler.java
deleted file mode 100644
index 534823f75e..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/downstream/router/IotDeviceServiceInvokeVertxHandler.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.common.downstream.router;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
-import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
-import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
-import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
-import io.vertx.core.Handler;
-import io.vertx.core.json.JsonObject;
-import io.vertx.ext.web.RoutingContext;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Map;
-
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
-
-/**
- * IoT 设备服务调用 Vertx Handler
- *
- * 芋道源码
- */
-@Slf4j
-@RequiredArgsConstructor
-public class IotDeviceServiceInvokeVertxHandler implements Handler {
-
- public static final String PATH = "/sys/:productKey/:deviceName/thing/service/:identifier";
- public static final String METHOD_PREFIX = "thing.service.";
- public static final String METHOD_SUFFIX = "";
-
- private final IotDeviceDownstreamHandler deviceDownstreamHandler;
-
- @Override
- @SuppressWarnings("unchecked")
- public void handle(RoutingContext routingContext) {
- // 1. 解析参数
- IotDeviceServiceInvokeReqDTO reqDTO;
- try {
- String productKey = routingContext.pathParam("productKey");
- String deviceName = routingContext.pathParam("deviceName");
- String identifier = routingContext.pathParam("identifier");
- JsonObject body = routingContext.body().asJsonObject();
- String requestId = body.getString("requestId");
- Map params = (Map) body.getMap().get("params");
- reqDTO = ((IotDeviceServiceInvokeReqDTO) new IotDeviceServiceInvokeReqDTO()
- .setRequestId(requestId).setProductKey(productKey).setDeviceName(deviceName))
- .setIdentifier(identifier).setParams(params);
- } catch (Exception e) {
- log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
- String method = METHOD_PREFIX + routingContext.pathParam("identifier") + METHOD_SUFFIX;
- IotStandardResponse errorResponse = IotStandardResponse.error(
- null, method, BAD_REQUEST.getCode(), BAD_REQUEST.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- return;
- }
-
- // 2. 调用处理器
- try {
- CommonResult result = deviceDownstreamHandler.invokeDeviceService(reqDTO);
-
- // 3. 响应结果
- String method = METHOD_PREFIX + reqDTO.getIdentifier() + METHOD_SUFFIX;
- IotStandardResponse response;
- if (result.isSuccess()) {
- response = IotStandardResponse.success(reqDTO.getRequestId(), method, result.getData());
- } else {
- response = IotStandardResponse.error(reqDTO.getRequestId(), method, result.getCode(), result.getMsg());
- }
- IotPluginCommonUtils.writeJsonResponse(routingContext, response);
- } catch (Exception e) {
- log.error("[handle][请求参数({}) 服务调用异常]", reqDTO, e);
- String method = METHOD_PREFIX + reqDTO.getIdentifier() + METHOD_SUFFIX;
- IotStandardResponse errorResponse = IotStandardResponse.error(
- reqDTO.getRequestId(), method, INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- }
- }
-
-}
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/heartbeat/IotPluginInstanceHeartbeatJob.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/heartbeat/IotPluginInstanceHeartbeatJob.java
deleted file mode 100644
index f272468c56..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/heartbeat/IotPluginInstanceHeartbeatJob.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.common.heartbeat;
-
-import cn.hutool.system.SystemUtil;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotPluginInstanceHeartbeatReqDTO;
-import cn.iocoder.yudao.module.iot.plugin.common.config.IotPluginCommonProperties;
-import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamServer;
-import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.scheduling.annotation.Scheduled;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * IoT 插件实例心跳 Job
- *
- * 用于定时发送心跳给服务端
- */
-@RequiredArgsConstructor
-@Slf4j
-public class IotPluginInstanceHeartbeatJob {
-
- private final IotDeviceUpstreamApi deviceUpstreamApi;
- private final IotDeviceDownstreamServer deviceDownstreamServer;
- private final IotPluginCommonProperties commonProperties;
-
- public void init() {
- CommonResult result = deviceUpstreamApi.heartbeatPluginInstance(buildPluginInstanceHeartbeatReqDTO(true));
- log.info("[init][上线结果:{})]", result);
- }
-
- public void stop() {
- CommonResult result = deviceUpstreamApi.heartbeatPluginInstance(buildPluginInstanceHeartbeatReqDTO(false));
- log.info("[stop][下线结果:{})]", result);
- }
-
- @Scheduled(initialDelay = 3, fixedRate = 3, timeUnit = TimeUnit.MINUTES) // 3 分钟执行一次
- public void execute() {
- CommonResult result = deviceUpstreamApi.heartbeatPluginInstance(buildPluginInstanceHeartbeatReqDTO(true));
- log.info("[execute][心跳结果:{})]", result);
- }
-
- private IotPluginInstanceHeartbeatReqDTO buildPluginInstanceHeartbeatReqDTO(Boolean online) {
- return new IotPluginInstanceHeartbeatReqDTO()
- .setPluginKey(commonProperties.getPluginKey()).setProcessId(IotPluginCommonUtils.getProcessId())
- .setHostIp(SystemUtil.getHostInfo().getAddress()).setDownstreamPort(deviceDownstreamServer.getPort())
- .setOnline(online);
- }
-
-}
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
deleted file mode 100644
index 83b5bb58aa..0000000000
--- 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
+++ /dev/null
@@ -1,2 +0,0 @@
-// TODO @芋艿:注释
-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-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/upstream/IotDeviceUpstreamClient.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/upstream/IotDeviceUpstreamClient.java
deleted file mode 100644
index 1bf4d676c0..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/upstream/IotDeviceUpstreamClient.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.common.upstream;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.*;
-import cn.iocoder.yudao.module.iot.plugin.common.config.IotPluginCommonProperties;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.client.RestTemplate;
-
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
-
-/**
- * 设备数据 Upstream 上行客户端
- *
- * 通过 HTTP 调用远程的 IotDeviceUpstreamApi 接口
- *
- * @author haohao
- */
-@RequiredArgsConstructor
-@Slf4j
-public class IotDeviceUpstreamClient implements IotDeviceUpstreamApi {
-
- public static final String URL_PREFIX = "/rpc-api/iot/device/upstream";
-
- private final IotPluginCommonProperties properties;
-
- private final RestTemplate restTemplate;
-
- @Override
- public CommonResult updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {
- String url = properties.getUpstreamUrl() + URL_PREFIX + "/update-state";
- return doPost(url, updateReqDTO);
- }
-
- @Override
- public CommonResult reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) {
- String url = properties.getUpstreamUrl() + URL_PREFIX + "/report-event";
- return doPost(url, reportReqDTO);
- }
-
- // TODO @芋艿:待实现
- @Override
- public CommonResult registerDevice(IotDeviceRegisterReqDTO registerReqDTO) {
- return null;
- }
-
- // TODO @芋艿:待实现
- @Override
- public CommonResult registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO) {
- return null;
- }
-
- // TODO @芋艿:待实现
- @Override
- public CommonResult addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO) {
- return null;
- }
-
- @Override
- public CommonResult authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) {
- String url = properties.getUpstreamUrl() + URL_PREFIX + "/authenticate-emqx-connection";
- return doPost(url, authReqDTO);
- }
-
- @Override
- public CommonResult reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) {
- String url = properties.getUpstreamUrl() + URL_PREFIX + "/report-property";
- return doPost(url, reportReqDTO);
- }
-
- @Override
- public CommonResult heartbeatPluginInstance(IotPluginInstanceHeartbeatReqDTO heartbeatReqDTO) {
- String url = properties.getUpstreamUrl() + URL_PREFIX + "/heartbeat-plugin-instance";
- return doPost(url, heartbeatReqDTO);
- }
-
- @SuppressWarnings("unchecked")
- private CommonResult doPost(String url, T requestBody) {
- try {
- CommonResult result = restTemplate.postForObject(url, requestBody,
- (Class>) (Class>) CommonResult.class);
- log.info("[doPost][url({}) requestBody({}) result({})]", url, requestBody, result);
- return result;
- } catch (Exception e) {
- log.error("[doPost][url({}) requestBody({}) 发生异常]", url, requestBody, e);
- return CommonResult.error(INTERNAL_SERVER_ERROR);
- }
- }
-
-}
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/util/IotPluginCommonUtils.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/util/IotPluginCommonUtils.java
deleted file mode 100644
index 34c6c0fe2b..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/util/IotPluginCommonUtils.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.common.util;
-
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.system.SystemUtil;
-import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
-import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
-import io.vertx.core.http.HttpHeaders;
-import io.vertx.ext.web.RoutingContext;
-import org.springframework.http.MediaType;
-
-/**
- * IoT 插件的通用工具类
- *
- * @author 芋道源码
- */
-public class IotPluginCommonUtils {
-
- /**
- * 流程实例的进程编号
- */
- private static String processId;
-
- public static String getProcessId() {
- if (StrUtil.isEmpty(processId)) {
- initProcessId();
- }
- return processId;
- }
-
- private synchronized static void initProcessId() {
- processId = String.format("%s@%d@%s", // IP@PID@${uuid}
- SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID(), IdUtil.fastSimpleUUID());
- }
-
- /**
- * 将对象转换为JSON字符串后写入HTTP响应
- *
- * @param routingContext 路由上下文
- * @param data 数据对象
- */
- @SuppressWarnings("deprecation")
- public static void writeJsonResponse(RoutingContext routingContext, Object data) {
- routingContext.response()
- .setStatusCode(200)
- .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
- .end(JsonUtils.toJsonString(data));
- }
-
- /**
- * 生成标准JSON格式的响应并写入HTTP响应(基于IotStandardResponse)
- *
- * 推荐使用此方法,统一MQTT和HTTP的响应格式。使用方式:
- *
- *
- * // 成功响应
- * IotStandardResponse response = IotStandardResponse.success(requestId, method, data);
- * IotPluginCommonUtils.writeJsonResponse(routingContext, response);
- *
- * // 错误响应
- * IotStandardResponse errorResponse = IotStandardResponse.error(requestId, method, code, message);
- * IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- *
- *
- * @param routingContext 路由上下文
- * @param response IotStandardResponse响应对象
- */
- @SuppressWarnings("deprecation")
- public static void writeJsonResponse(RoutingContext routingContext, IotStandardResponse response) {
- routingContext.response()
- .setStatusCode(200)
- .putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
- .end(JsonUtils.toJsonString(response));
- }
-
-}
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index eae9ad8828..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1 +0,0 @@
-cn.iocoder.yudao.module.iot.plugin.common.config.IotPluginCommonAutoConfiguration
\ 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
deleted file mode 100644
index 565e81eb06..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/plugin.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-plugin.id=yudao-module-iot-plugin-emqx
-plugin.class=cn.iocoder.yudao.module.iot.plugin.emqx.config.IotEmqxPlugin
-plugin.version=1.0.0
-plugin.provider=yudao
-plugin.dependencies=
-plugin.description=yudao-module-iot-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
deleted file mode 100644
index 8620ecaa65..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/pom.xml
+++ /dev/null
@@ -1,169 +0,0 @@
-
-
-
- yudao-module-iot-plugins
- cn.iocoder.boot
- ${revision}
-
- 4.0.0
- jar
-
- yudao-module-iot-plugin-emqx
- 1.0.0
-
- ${project.artifactId}
-
-
- 物联网 插件模块 - emqx 插件
-
-
-
-
- emqx-plugin
- cn.iocoder.yudao.module.iot.plugin.emqx.config.IotEmqxPlugin
- ${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
-
-
-
-
-
-
-
-
-
-
- cn.iocoder.boot
- yudao-module-iot-plugin-common
- ${revision}
-
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
-
- io.vertx
- vertx-web
-
-
- io.vertx
- vertx-mqtt
-
-
-
\ 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
deleted file mode 100644
index daec9e4315..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/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-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/IotEmqxPluginApplication.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/IotEmqxPluginApplication.java
deleted file mode 100644
index 1780384175..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/IotEmqxPluginApplication.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.emqx;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.WebApplicationType;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-/**
- * IoT Emqx 插件的独立运行入口
- */
-@Slf4j
-@SpringBootApplication
-public class IotEmqxPluginApplication {
-
- public static void main(String[] args) {
- SpringApplication application = new SpringApplication(IotEmqxPluginApplication.class);
- application.setWebApplicationType(WebApplicationType.NONE);
- application.run(args);
- log.info("[main][独立模式启动完成]");
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotEmqxPlugin.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotEmqxPlugin.java
deleted file mode 100644
index 275c20eb1c..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotEmqxPlugin.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.emqx.config;
-
-import cn.hutool.extra.spring.SpringUtil;
-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;
-
-/**
- * EMQX 插件实现类
- *
- * 基于 PF4J 插件框架,实现 EMQX 消息中间件的集成:负责插件的生命周期管理,包括启动、停止和应用上下文的创建
- *
- * @author haohao
- */
-@Slf4j
-public class IotEmqxPlugin extends SpringPlugin {
-
- public IotEmqxPlugin(PluginWrapper wrapper) {
- super(wrapper);
- }
-
- @Override
- public void start() {
- log.info("[EmqxPlugin][EmqxPlugin 插件启动开始...]");
- try {
- log.info("[EmqxPlugin][EmqxPlugin 插件启动成功...]");
- } catch (Exception e) {
- log.error("[EmqxPlugin][EmqxPlugin 插件开启动异常...]", e);
- }
- }
-
- @Override
- public void stop() {
- log.info("[EmqxPlugin][EmqxPlugin 插件停止开始...]");
- try {
- log.info("[EmqxPlugin][EmqxPlugin 插件停止成功...]");
- } catch (Exception e) {
- log.error("[EmqxPlugin][EmqxPlugin 插件停止异常...]", e);
- }
- }
-
- @Override
- protected ApplicationContext createApplicationContext() {
- // 创建插件自己的 ApplicationContext
- AnnotationConfigApplicationContext pluginContext = new AnnotationConfigApplicationContext();
- // 设置父容器为主应用的 ApplicationContext (确保主应用中提供的类可用)
- pluginContext.setParent(SpringUtil.getApplicationContext());
- // 继续使用插件自己的 ClassLoader 以加载插件内部的类
- pluginContext.setClassLoader(getWrapper().getPluginClassLoader());
- // 扫描当前插件的自动配置包
- // TODO @芋艿:是不是要配置下包
- pluginContext.scan("cn.iocoder.yudao.module.iot.plugin.emqx.config");
- pluginContext.refresh();
- return pluginContext;
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotPluginEmqxAutoConfiguration.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotPluginEmqxAutoConfiguration.java
deleted file mode 100644
index e1d11504cf..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotPluginEmqxAutoConfiguration.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.emqx.config;
-
-import cn.hutool.core.util.IdUtil;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
-import cn.iocoder.yudao.module.iot.plugin.emqx.downstream.IotDeviceDownstreamHandlerImpl;
-import cn.iocoder.yudao.module.iot.plugin.emqx.upstream.IotDeviceUpstreamServer;
-import io.vertx.core.Vertx;
-import io.vertx.mqtt.MqttClient;
-import io.vertx.mqtt.MqttClientOptions;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * IoT 插件 EMQX 的专用自动配置类
- *
- * @author haohao
- */
-@Slf4j
-@Configuration
-@EnableConfigurationProperties(IotPluginEmqxProperties.class)
-public class IotPluginEmqxAutoConfiguration {
-
- @Bean
- public Vertx vertx() {
- return Vertx.vertx();
- }
-
- @Bean
- public MqttClient mqttClient(Vertx vertx, IotPluginEmqxProperties emqxProperties) {
- MqttClientOptions options = new MqttClientOptions()
- .setClientId("yudao-iot-downstream-" + IdUtil.fastSimpleUUID())
- .setUsername(emqxProperties.getMqttUsername())
- .setPassword(emqxProperties.getMqttPassword())
- .setSsl(emqxProperties.getMqttSsl());
- return MqttClient.create(vertx, options);
- }
-
- @Bean(initMethod = "start", destroyMethod = "stop")
- public IotDeviceUpstreamServer deviceUpstreamServer(IotDeviceUpstreamApi deviceUpstreamApi,
- IotPluginEmqxProperties emqxProperties,
- Vertx vertx,
- MqttClient mqttClient) {
- return new IotDeviceUpstreamServer(emqxProperties, deviceUpstreamApi, vertx, mqttClient);
- }
-
- @Bean
- public IotDeviceDownstreamHandler deviceDownstreamHandler(MqttClient mqttClient) {
- return new IotDeviceDownstreamHandlerImpl(mqttClient);
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotPluginEmqxProperties.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotPluginEmqxProperties.java
deleted file mode 100644
index 219fe0360f..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/config/IotPluginEmqxProperties.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.emqx.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-
-/**
- * 物联网插件 - EMQX 配置
- *
- * @author 芋道源码
- */
-@ConfigurationProperties(prefix = "yudao.iot.plugin.emqx")
-@Validated
-@Data
-public class IotPluginEmqxProperties {
-
- // TODO @haohao:参数校验,加下,啊哈
-
- /**
- * 服务主机
- */
- private String mqttHost;
- /**
- * 服务端口
- */
- private Integer mqttPort;
- /**
- * 服务用户名
- */
- private String mqttUsername;
- /**
- * 服务密码
- */
- private String mqttPassword;
- /**
- * 是否启用 SSL
- */
- private Boolean mqttSsl;
-
- /**
- * 订阅的主题列表
- */
- private String[] mqttTopics;
-
- /**
- * 认证端口
- */
- private Integer authPort;
-
-}
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/downstream/IotDeviceDownstreamHandlerImpl.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/downstream/IotDeviceDownstreamHandlerImpl.java
deleted file mode 100644
index f5c19224af..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/downstream/IotDeviceDownstreamHandlerImpl.java
+++ /dev/null
@@ -1,176 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.emqx.downstream;
-
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.*;
-import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
-import io.netty.handler.codec.mqtt.MqttQoS;
-import io.vertx.core.buffer.Buffer;
-import io.vertx.mqtt.MqttClient;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Map;
-
-import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.MQTT_TOPIC_ILLEGAL;
-
-/**
- * EMQX 插件的 {@link IotDeviceDownstreamHandler} 实现类
- *
- * @author 芋道源码
- */
-@Slf4j
-public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandler {
-
- private static final String SYS_TOPIC_PREFIX = "/sys/";
-
- // TODO @haohao:是不是可以类似 IotDeviceConfigSetVertxHandler 的建议,抽到统一的枚举类
- // TODO @haohao:讨论,感觉 mqtt 和 http,可以做个相对统一的格式哈。;回复 都使用 Alink 格式,方便后续扩展。
- // 设备服务调用 标准 JSON
- // 请求Topic:/sys/${productKey}/${deviceName}/thing/service/${tsl.service.identifier}
- // 响应Topic:/sys/${productKey}/${deviceName}/thing/service/${tsl.service.identifier}_reply
- private static final String SERVICE_TOPIC_PREFIX = "/thing/service/";
-
- // 设置设备属性 标准 JSON
- // 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/set
- // 响应Topic:/sys/${productKey}/${deviceName}/thing/service/property/set_reply
- private static final String PROPERTY_SET_TOPIC = "/thing/service/property/set";
-
- private final MqttClient mqttClient;
-
- /**
- * 构造函数
- *
- * @param mqttClient MQTT客户端
- */
- public IotDeviceDownstreamHandlerImpl(MqttClient mqttClient) {
- this.mqttClient = mqttClient;
- }
-
- @Override
- public CommonResult invokeDeviceService(IotDeviceServiceInvokeReqDTO reqDTO) {
- log.info("[invokeService][开始调用设备服务][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO));
-
- // 验证参数
- if (reqDTO.getProductKey() == null || reqDTO.getDeviceName() == null || reqDTO.getIdentifier() == null) {
- log.error("[invokeService][参数不完整][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO));
- return CommonResult.error(MQTT_TOPIC_ILLEGAL.getCode(), MQTT_TOPIC_ILLEGAL.getMsg());
- }
-
- try {
- // 构建请求主题
- String topic = buildServiceTopic(reqDTO.getProductKey(), reqDTO.getDeviceName(), reqDTO.getIdentifier());
- // 构建请求消息
- String requestId = reqDTO.getRequestId() != null ? reqDTO.getRequestId() : generateRequestId();
- JSONObject request = buildServiceRequest(requestId, reqDTO.getIdentifier(), reqDTO.getParams());
- // 发送消息
- publishMessage(topic, request);
-
- log.info("[invokeService][调用设备服务成功][requestId: {}][topic: {}]", requestId, topic);
- return CommonResult.success(true);
- } catch (Exception e) {
- log.error("[invokeService][调用设备服务异常][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO), e);
- return CommonResult.error(MQTT_TOPIC_ILLEGAL.getCode(), MQTT_TOPIC_ILLEGAL.getMsg());
- }
- }
-
- @Override
- public CommonResult getDeviceProperty(IotDevicePropertyGetReqDTO getReqDTO) {
- return CommonResult.success(true);
- }
-
- @Override
- public CommonResult setDeviceProperty(IotDevicePropertySetReqDTO reqDTO) {
- // 验证参数
- log.info("[setProperty][开始设置设备属性][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO));
- if (reqDTO.getProductKey() == null || reqDTO.getDeviceName() == null) {
- log.error("[setProperty][参数不完整][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO));
- return CommonResult.error(MQTT_TOPIC_ILLEGAL.getCode(), MQTT_TOPIC_ILLEGAL.getMsg());
- }
-
- try {
- // 构建请求主题
- String topic = buildPropertySetTopic(reqDTO.getProductKey(), reqDTO.getDeviceName());
- // 构建请求消息
- String requestId = reqDTO.getRequestId() != null ? reqDTO.getRequestId() : generateRequestId();
- JSONObject request = buildPropertySetRequest(requestId, reqDTO.getProperties());
- // 发送消息
- publishMessage(topic, request);
-
- log.info("[setProperty][设置设备属性成功][requestId: {}][topic: {}]", requestId, topic);
- return CommonResult.success(true);
- } catch (Exception e) {
- log.error("[setProperty][设置设备属性异常][reqDTO: {}]", JSONUtil.toJsonStr(reqDTO), e);
- return CommonResult.error(MQTT_TOPIC_ILLEGAL.getCode(), MQTT_TOPIC_ILLEGAL.getMsg());
- }
- }
-
- @Override
- public CommonResult setDeviceConfig(IotDeviceConfigSetReqDTO setReqDTO) {
- return CommonResult.success(true);
- }
-
- @Override
- public CommonResult upgradeDeviceOta(IotDeviceOtaUpgradeReqDTO upgradeReqDTO) {
- return CommonResult.success(true);
- }
-
- /**
- * 构建服务调用主题
- */
- private String buildServiceTopic(String productKey, String deviceName, String serviceIdentifier) {
- return SYS_TOPIC_PREFIX + productKey + "/" + deviceName + SERVICE_TOPIC_PREFIX + serviceIdentifier;
- }
-
- /**
- * 构建属性设置主题
- */
- private String buildPropertySetTopic(String productKey, String deviceName) {
- return SYS_TOPIC_PREFIX + productKey + "/" + deviceName + PROPERTY_SET_TOPIC;
- }
-
- // TODO @haohao:这个,后面搞个对象,会不会好点哈?
- /**
- * 构建服务调用请求
- */
- private JSONObject buildServiceRequest(String requestId, String serviceIdentifier, Map params) {
- return new JSONObject()
- .set("id", requestId)
- .set("version", "1.0")
- .set("method", "thing.service." + serviceIdentifier)
- .set("params", params != null ? params : new JSONObject());
- }
-
- /**
- * 构建属性设置请求
- */
- private JSONObject buildPropertySetRequest(String requestId, Map properties) {
- return new JSONObject()
- .set("id", requestId)
- .set("version", "1.0")
- .set("method", "thing.service.property.set")
- .set("params", properties);
- }
-
- /**
- * 发布 MQTT 消息
- */
- private void publishMessage(String topic, JSONObject payload) {
- mqttClient.publish(
- topic,
- Buffer.buffer(payload.toString()),
- MqttQoS.AT_LEAST_ONCE,
- false,
- false);
- log.info("[publishMessage][发送消息成功][topic: {}][payload: {}]", topic, payload);
- }
-
- /**
- * 生成请求 ID
- */
- private String generateRequestId() {
- return IdUtil.fastSimpleUUID();
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/IotDeviceUpstreamServer.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/IotDeviceUpstreamServer.java
deleted file mode 100644
index 00792ebcf9..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/IotDeviceUpstreamServer.java
+++ /dev/null
@@ -1,236 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.emqx.upstream;
-
-import cn.hutool.core.util.ArrayUtil;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.plugin.emqx.config.IotPluginEmqxProperties;
-import cn.iocoder.yudao.module.iot.plugin.emqx.upstream.router.IotDeviceAuthVertxHandler;
-import cn.iocoder.yudao.module.iot.plugin.emqx.upstream.router.IotDeviceMqttMessageHandler;
-import cn.iocoder.yudao.module.iot.plugin.emqx.upstream.router.IotDeviceWebhookVertxHandler;
-import io.netty.handler.codec.mqtt.MqttQoS;
-import io.vertx.core.Future;
-import io.vertx.core.Vertx;
-import io.vertx.core.http.HttpServer;
-import io.vertx.ext.web.Router;
-import io.vertx.ext.web.handler.BodyHandler;
-import io.vertx.mqtt.MqttClient;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-
-/**
- * IoT 设备下行服务端,接收来自 device 设备的请求,转发给 server 服务器
- *
- * 协议:HTTP、MQTT
- *
- * @author haohao
- */
-@Slf4j
-public class IotDeviceUpstreamServer {
-
- /**
- * 重连延迟时间(毫秒)
- */
- private static final int RECONNECT_DELAY_MS = 5000;
- /**
- * 连接超时时间(毫秒)
- */
- private static final int CONNECTION_TIMEOUT_MS = 10000;
- /**
- * 默认 QoS 级别
- */
- private static final MqttQoS DEFAULT_QOS = MqttQoS.AT_LEAST_ONCE;
-
- private final Vertx vertx;
- private final HttpServer server;
- private final MqttClient client;
- private final IotPluginEmqxProperties emqxProperties;
- private final IotDeviceMqttMessageHandler mqttMessageHandler;
-
- /**
- * 服务运行状态标志
- */
- private volatile boolean isRunning = false;
-
- public IotDeviceUpstreamServer(IotPluginEmqxProperties emqxProperties,
- IotDeviceUpstreamApi deviceUpstreamApi,
- Vertx vertx,
- MqttClient client) {
- this.vertx = vertx;
- this.emqxProperties = emqxProperties;
- this.client = client;
-
- // 创建 Router 实例
- Router router = Router.router(vertx);
- router.route().handler(BodyHandler.create()); // 处理 Body
- router.post(IotDeviceAuthVertxHandler.PATH)
- // TODO @haohao:疑问,mqtt 的认证,需要通过 http 呀?
- // 回复:MQTT 认证不必须通过 HTTP 进行,但 HTTP 认证是 EMQX 等 MQTT 服务器支持的一种灵活的认证方式
- .handler(new IotDeviceAuthVertxHandler(deviceUpstreamApi));
- // 添加 Webhook 处理器,用于处理设备连接和断开连接事件
- router.post(IotDeviceWebhookVertxHandler.PATH)
- .handler(new IotDeviceWebhookVertxHandler(deviceUpstreamApi));
- // 创建 HttpServer 实例
- this.server = vertx.createHttpServer().requestHandler(router);
- this.mqttMessageHandler = new IotDeviceMqttMessageHandler(deviceUpstreamApi, client);
- }
-
- /**
- * 启动 HTTP 服务器、MQTT 客户端
- */
- public void start() {
- if (isRunning) {
- log.warn("[start][服务已经在运行中,请勿重复启动]");
- return;
- }
- log.info("[start][开始启动服务]");
-
- // TODO @haohao:建议先启动 MQTT Broker,再启动 HTTP Server。类似 jdbc 先连接了,在启动 tomcat 的味道
- // 1. 启动 HTTP 服务器
- CompletableFuture httpFuture = server.listen(emqxProperties.getAuthPort())
- .toCompletionStage()
- .toCompletableFuture()
- .thenAccept(v -> log.info("[start][HTTP 服务器启动完成,端口: {}]", server.actualPort()));
-
- // 2. 连接 MQTT Broker
- CompletableFuture mqttFuture = connectMqtt()
- .toCompletionStage()
- .toCompletableFuture()
- .thenAccept(v -> {
- // 2.1 添加 MQTT 断开重连监听器
- client.closeHandler(closeEvent -> {
- log.warn("[closeHandler][MQTT 连接已断开,准备重连]");
- reconnectWithDelay();
- });
- // 2.2 设置 MQTT 消息处理器
- setupMessageHandler();
- });
-
- // 3. 等待所有服务启动完成
- CompletableFuture.allOf(httpFuture, mqttFuture)
- .orTimeout(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS) // TODO @芋艿:JDK8 不兼容
- .whenComplete((result, error) -> {
- if (error != null) {
- log.error("[start][服务启动失败]", error);
- } else {
- isRunning = true;
- log.info("[start][所有服务启动完成]");
- }
- });
- }
-
- /**
- * 设置 MQTT 消息处理器
- */
- private void setupMessageHandler() {
- client.publishHandler(mqttMessageHandler::handle);
- log.debug("[setupMessageHandler][MQTT 消息处理器设置完成]");
- }
-
- /**
- * 重连 MQTT 客户端
- */
- private void reconnectWithDelay() {
- if (!isRunning) {
- log.info("[reconnectWithDelay][服务已停止,不再尝试重连]");
- return;
- }
-
- vertx.setTimer(RECONNECT_DELAY_MS, id -> {
- log.info("[reconnectWithDelay][开始重新连接 MQTT]");
- connectMqtt();
- });
- }
-
- /**
- * 连接 MQTT Broker 并订阅主题
- *
- * @return 连接结果的Future
- */
- private Future connectMqtt() {
- return client.connect(emqxProperties.getMqttPort(), emqxProperties.getMqttHost())
- .compose(connAck -> {
- log.info("[connectMqtt][MQTT客户端连接成功]");
- return subscribeToTopics();
- })
- .recover(error -> {
- log.error("[connectMqtt][连接MQTT Broker失败:]", error);
- reconnectWithDelay();
- return Future.failedFuture(error);
- });
- }
-
- /**
- * 订阅设备上行消息主题
- *
- * @return 订阅结果的 Future
- */
- private Future subscribeToTopics() {
- String[] topics = emqxProperties.getMqttTopics();
- if (ArrayUtil.isEmpty(topics)) {
- log.warn("[subscribeToTopics][未配置MQTT主题,跳过订阅]");
- return Future.succeededFuture();
- }
- log.info("[subscribeToTopics][开始订阅设备上行消息主题]");
-
- Future compositeFuture = Future.succeededFuture();
- for (String topic : topics) {
- String trimmedTopic = topic.trim();
- if (trimmedTopic.isEmpty()) {
- continue;
- }
- compositeFuture = compositeFuture.compose(v -> client.subscribe(trimmedTopic, DEFAULT_QOS.value())
- .map(ack -> {
- log.info("[subscribeToTopics][成功订阅主题: {}]", trimmedTopic);
- return null;
- })
- .recover(error -> {
- log.error("[subscribeToTopics][订阅主题失败: {}]", trimmedTopic, error);
- return Future.succeededFuture(); // 继续订阅其他主题
- }));
- }
- return compositeFuture;
- }
-
- /**
- * 停止所有服务
- */
- public void stop() {
- if (!isRunning) {
- log.warn("[stop][服务未运行,无需停止]");
- return;
- }
- log.info("[stop][开始关闭服务]");
- isRunning = false;
-
- try {
- // 关闭 HTTP 服务器
- if (server != null) {
- server.close()
- .toCompletionStage()
- .toCompletableFuture()
- .join();
- }
-
- // 关闭 MQTT 客户端
- if (client != null) {
- client.disconnect()
- .toCompletionStage()
- .toCompletableFuture()
- .join();
- }
-
- // 关闭 Vertx 实例
- if (vertx!= null) {
- vertx.close()
- .toCompletionStage()
- .toCompletableFuture()
- .join();
- }
- log.info("[stop][关闭完成]");
- } catch (Exception e) {
- log.error("[stop][关闭服务异常]", e);
- throw new RuntimeException("关闭 IoT 设备上行服务失败", e);
- }
- }
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceAuthVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceAuthVertxHandler.java
deleted file mode 100644
index e9206d5b64..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceAuthVertxHandler.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.emqx.upstream.router;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEmqxAuthReqDTO;
-import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
-import io.vertx.core.Handler;
-import io.vertx.core.json.JsonObject;
-import io.vertx.ext.web.RoutingContext;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Collections;
-
-/**
- * IoT EMQX 连接认证的 Vert.x Handler
- *
- * 参考:EMQX HTTP
- *
- * 注意:该处理器需要返回特定格式:{"result": "allow"} 或 {"result": "deny"},
- * 以符合 EMQX 认证插件的要求,因此不使用 IotStandardResponse 实体类
- *
- * @author haohao
- */
-@RequiredArgsConstructor
-@Slf4j
-public class IotDeviceAuthVertxHandler implements Handler {
-
- public static final String PATH = "/mqtt/auth";
-
- private final IotDeviceUpstreamApi deviceUpstreamApi;
-
- @Override
- public void handle(RoutingContext routingContext) {
- try {
- // 构建认证请求 DTO
- JsonObject json = routingContext.body().asJsonObject();
- String clientId = json.getString("clientid");
- String username = json.getString("username");
- String password = json.getString("password");
- IotDeviceEmqxAuthReqDTO authReqDTO = new IotDeviceEmqxAuthReqDTO()
- .setClientId(clientId)
- .setUsername(username)
- .setPassword(password);
-
- // 调用认证 API
- CommonResult authResult = deviceUpstreamApi.authenticateEmqxConnection(authReqDTO);
- if (authResult.getCode() != 0 || !authResult.getData()) {
- // 注意:这里必须返回 {"result": "deny"} 格式,以符合 EMQX 认证插件的要求
- IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "deny"));
- return;
- }
-
- // 响应结果
- // 注意:这里必须返回 {"result": "allow"} 格式,以符合 EMQX 认证插件的要求
- IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "allow"));
- } catch (Exception e) {
- log.error("[handle][EMQX 认证异常]", e);
- // 注意:这里必须返回 {"result": "deny"} 格式,以符合 EMQX 认证插件的要求
- IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "deny"));
- }
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceMqttMessageHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceMqttMessageHandler.java
deleted file mode 100644
index 00fa1b96d7..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceMqttMessageHandler.java
+++ /dev/null
@@ -1,296 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.emqx.upstream.router;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO;
-import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
-import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
-import io.netty.handler.codec.mqtt.MqttQoS;
-import io.vertx.core.buffer.Buffer;
-import io.vertx.mqtt.MqttClient;
-import io.vertx.mqtt.messages.MqttPublishMessage;
-import lombok.extern.slf4j.Slf4j;
-
-import java.time.LocalDateTime;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * IoT 设备 MQTT 消息处理器
- *
- * 参考:设备属性、事件、服务
- */
-@Slf4j
-public class IotDeviceMqttMessageHandler {
-
- // TODO @haohao:讨论,感觉 mqtt 和 http,可以做个相对统一的格式哈;回复 都使用 Alink 格式,方便后续扩展。
- // 设备上报属性 标准 JSON
- // 请求 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post
- // 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply
-
- // 设备上报事件 标准 JSON
- // 请求 Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post
- // 响应 Topic:/sys/${productKey}/${deviceName}/thing/event/${tsl.event.identifier}/post_reply
-
- private static final String SYS_TOPIC_PREFIX = "/sys/";
- private static final String PROPERTY_POST_TOPIC = "/thing/event/property/post";
- private static final String EVENT_POST_TOPIC_PREFIX = "/thing/event/";
- private static final String EVENT_POST_TOPIC_SUFFIX = "/post";
- private static final String REPLY_SUFFIX = "_reply";
- private static final String PROPERTY_METHOD = "thing.event.property.post";
- private static final String EVENT_METHOD_PREFIX = "thing.event.";
- private static final String EVENT_METHOD_SUFFIX = ".post";
-
- private final IotDeviceUpstreamApi deviceUpstreamApi;
- private final MqttClient mqttClient;
-
- public IotDeviceMqttMessageHandler(IotDeviceUpstreamApi deviceUpstreamApi, MqttClient mqttClient) {
- this.deviceUpstreamApi = deviceUpstreamApi;
- this.mqttClient = mqttClient;
- }
-
- /**
- * 处理MQTT消息
- *
- * @param message MQTT发布消息
- */
- public void handle(MqttPublishMessage message) {
- String topic = message.topicName();
- String payload = message.payload().toString();
- log.info("[messageHandler][接收到消息][topic: {}][payload: {}]", topic, payload);
-
- try {
- if (StrUtil.isEmpty(payload)) {
- log.warn("[messageHandler][消息内容为空][topic: {}]", topic);
- return;
- }
- handleMessage(topic, payload);
- } catch (Exception e) {
- log.error("[messageHandler][处理消息失败][topic: {}][payload: {}]", topic, payload, e);
- }
- }
-
- /**
- * 根据主题类型处理消息
- *
- * @param topic 主题
- * @param payload 消息内容
- */
- private void handleMessage(String topic, String payload) {
- // 校验前缀
- if (!topic.startsWith(SYS_TOPIC_PREFIX)) {
- log.warn("[handleMessage][未知的消息类型][topic: {}]", topic);
- return;
- }
-
- // 处理设备属性上报消息
- if (topic.endsWith(PROPERTY_POST_TOPIC)) {
- log.info("[handleMessage][接收到设备属性上报][topic: {}]", topic);
- handlePropertyPost(topic, payload);
- return;
- }
-
- // 处理设备事件上报消息
- if (topic.contains(EVENT_POST_TOPIC_PREFIX) && topic.endsWith(EVENT_POST_TOPIC_SUFFIX)) {
- log.info("[handleMessage][接收到设备事件上报][topic: {}]", topic);
- handleEventPost(topic, payload);
- return;
- }
-
- // 未知消息类型
- log.warn("[handleMessage][未知的消息类型][topic: {}]", topic);
- }
-
- /**
- * 处理设备属性上报消息
- *
- * @param topic 主题
- * @param payload 消息内容
- */
- private void handlePropertyPost(String topic, String payload) {
- try {
- // 解析消息内容
- JSONObject jsonObject = JSONUtil.parseObj(payload);
- String[] topicParts = parseTopic(topic);
- if (topicParts == null) {
- return;
- }
-
- // 构建设备属性上报请求对象
- IotDevicePropertyReportReqDTO reportReqDTO = buildPropertyReportDTO(jsonObject, topicParts);
-
- // 调用上游 API 处理设备上报数据
- deviceUpstreamApi.reportDeviceProperty(reportReqDTO);
- log.info("[handlePropertyPost][处理设备属性上报成功][topic: {}]", topic);
-
- // 发送响应消息
- sendResponse(topic, jsonObject, PROPERTY_METHOD, null);
- } catch (Exception e) {
- log.error("[handlePropertyPost][处理设备属性上报失败][topic: {}][payload: {}]", topic, payload, e);
- }
- }
-
- /**
- * 处理设备事件上报消息
- *
- * @param topic 主题
- * @param payload 消息内容
- */
- private void handleEventPost(String topic, String payload) {
- try {
- // 解析消息内容
- JSONObject jsonObject = JSONUtil.parseObj(payload);
- String[] topicParts = parseTopic(topic);
- if (topicParts == null) {
- return;
- }
-
- // 构建设备事件上报请求对象
- IotDeviceEventReportReqDTO reportReqDTO = buildEventReportDTO(jsonObject, topicParts);
-
- // 调用上游 API 处理设备上报数据
- deviceUpstreamApi.reportDeviceEvent(reportReqDTO);
- log.info("[handleEventPost][处理设备事件上报成功][topic: {}]", topic);
-
- // 从 topic 中获取事件标识符
- String eventIdentifier = getEventIdentifier(topicParts, topic);
- if (eventIdentifier == null) {
- return;
- }
-
- // 发送响应消息
- String method = EVENT_METHOD_PREFIX + eventIdentifier + EVENT_METHOD_SUFFIX;
- sendResponse(topic, jsonObject, method, null);
- } catch (Exception e) {
- log.error("[handleEventPost][处理设备事件上报失败][topic: {}][payload: {}]", topic, payload, e);
- }
- }
-
- /**
- * 解析主题,获取主题各部分
- *
- * @param topic 主题
- * @return 主题各部分数组,如果解析失败返回null
- */
- private String[] parseTopic(String topic) {
- String[] topicParts = topic.split("/");
- if (topicParts.length < 7) {
- log.warn("[parseTopic][主题格式不正确][topic: {}]", topic);
- return null;
- }
- return topicParts;
- }
-
- /**
- * 从主题部分中获取事件标识符
- *
- * @param topicParts 主题各部分
- * @param topic 原始主题,用于日志
- * @return 事件标识符,如果获取失败返回null
- */
- private String getEventIdentifier(String[] topicParts, String topic) {
- try {
- return topicParts[6];
- } catch (ArrayIndexOutOfBoundsException e) {
- log.warn("[getEventIdentifier][无法从主题中获取事件标识符][topic: {}][topicParts: {}]",
- topic, Arrays.toString(topicParts));
- return null;
- }
- }
-
- /**
- * 发送响应消息
- *
- * @param topic 原始主题
- * @param jsonObject 原始消息JSON对象
- * @param method 响应方法
- * @param customData 自定义数据,可为 null
- */
- private void sendResponse(String topic, JSONObject jsonObject, String method, Object customData) {
- String replyTopic = topic + REPLY_SUFFIX;
-
- // 响应结果
- IotStandardResponse response = IotStandardResponse.success(
- jsonObject.getStr("id"), method, customData);
- try {
- mqttClient.publish(replyTopic, Buffer.buffer(JsonUtils.toJsonString(response)),
- MqttQoS.AT_LEAST_ONCE, false, false);
- log.info("[sendResponse][发送响应消息成功][topic: {}]", replyTopic);
- } catch (Exception e) {
- log.error("[sendResponse][发送响应消息失败][topic: {}][response: {}]", replyTopic, response, e);
- }
- }
-
- /**
- * 构建设备属性上报请求对象
- *
- * @param jsonObject 消息内容
- * @param topicParts 主题部分
- * @return 设备属性上报请求对象
- */
- private IotDevicePropertyReportReqDTO buildPropertyReportDTO(JSONObject jsonObject, String[] topicParts) {
- IotDevicePropertyReportReqDTO reportReqDTO = new IotDevicePropertyReportReqDTO();
- reportReqDTO.setRequestId(jsonObject.getStr("id"));
- reportReqDTO.setProcessId(IotPluginCommonUtils.getProcessId());
- reportReqDTO.setReportTime(LocalDateTime.now());
- reportReqDTO.setProductKey(topicParts[2]);
- reportReqDTO.setDeviceName(topicParts[3]);
-
- // 只使用标准JSON格式处理属性数据
- JSONObject params = jsonObject.getJSONObject("params");
- if (params == null) {
- log.warn("[buildPropertyReportDTO][消息格式不正确,缺少params字段][jsonObject: {}]", jsonObject);
- params = new JSONObject();
- }
-
- // 将标准格式的params转换为平台需要的properties格式
- Map properties = new HashMap<>();
- for (Map.Entry entry : params.entrySet()) {
- String key = entry.getKey();
- Object valueObj = entry.getValue();
-
- // 如果是复杂结构(包含value和time)
- if (valueObj instanceof JSONObject valueJson) {
- properties.put(key, valueJson.getOrDefault("value", valueObj));
- } else {
- properties.put(key, valueObj);
- }
- }
- reportReqDTO.setProperties(properties);
-
- return reportReqDTO;
- }
-
- /**
- * 构建设备事件上报请求对象
- *
- * @param jsonObject 消息内容
- * @param topicParts 主题部分
- * @return 设备事件上报请求对象
- */
- private IotDeviceEventReportReqDTO buildEventReportDTO(JSONObject jsonObject, String[] topicParts) {
- IotDeviceEventReportReqDTO reportReqDTO = new IotDeviceEventReportReqDTO();
- reportReqDTO.setRequestId(jsonObject.getStr("id"));
- reportReqDTO.setProcessId(IotPluginCommonUtils.getProcessId());
- reportReqDTO.setReportTime(LocalDateTime.now());
- reportReqDTO.setProductKey(topicParts[2]);
- reportReqDTO.setDeviceName(topicParts[3]);
- reportReqDTO.setIdentifier(topicParts[6]);
-
- // 只使用标准JSON格式处理事件参数
- JSONObject params = jsonObject.getJSONObject("params");
- if (params == null) {
- log.warn("[buildEventReportDTO][消息格式不正确,缺少params字段][jsonObject: {}]", jsonObject);
- params = new JSONObject();
- }
- reportReqDTO.setParams(params);
-
- return reportReqDTO;
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceWebhookVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceWebhookVertxHandler.java
deleted file mode 100644
index 21b49e097c..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceWebhookVertxHandler.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.emqx.upstream.router;
-
-import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO;
-import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;
-import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
-import io.vertx.core.Handler;
-import io.vertx.core.json.JsonObject;
-import io.vertx.ext.web.RoutingContext;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
-import java.time.LocalDateTime;
-import java.util.Collections;
-
-/**
- * IoT EMQX Webhook 事件处理的 Vert.x Handler
- *
- * 参考:EMQX Webhook
- *
- * 注意:该处理器需要返回特定格式:{"result": "success"} 或 {"result": "error"},
- * 以符合 EMQX Webhook 插件的要求,因此不使用 IotStandardResponse 实体类。
- *
- * @author haohao
- */
-@RequiredArgsConstructor
-@Slf4j
-public class IotDeviceWebhookVertxHandler implements Handler {
-
- public static final String PATH = "/mqtt/webhook";
-
- private final IotDeviceUpstreamApi deviceUpstreamApi;
-
- @Override
- public void handle(RoutingContext routingContext) {
- try {
- // 解析请求体
- JsonObject json = routingContext.body().asJsonObject();
- String event = json.getString("event");
- String clientId = json.getString("clientid");
- String username = json.getString("username");
-
- // 处理不同的事件类型
- switch (event) {
- case "client.connected":
- handleClientConnected(clientId, username);
- break;
- case "client.disconnected":
- handleClientDisconnected(clientId, username);
- break;
- default:
- log.info("[handle][未处理的 Webhook 事件] event={}, clientId={}, username={}", event, clientId, username);
- break;
- }
-
- // 返回成功响应
- // 注意:这里必须返回 {"result": "success"} 格式,以符合 EMQX Webhook 插件的要求
- IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "success"));
- } catch (Exception e) {
- log.error("[handle][处理 Webhook 事件异常]", e);
- // 注意:这里必须返回 {"result": "error"} 格式,以符合 EMQX Webhook 插件的要求
- IotPluginCommonUtils.writeJsonResponse(routingContext, Collections.singletonMap("result", "error"));
- }
- }
-
- /**
- * 处理客户端连接事件
- *
- * @param clientId 客户端ID
- * @param username 用户名
- */
- private void handleClientConnected(String clientId, String username) {
- // 解析产品标识和设备名称
- if (StrUtil.isEmpty(username) || "undefined".equals(username)) {
- log.warn("[handleClientConnected][客户端连接事件,但用户名为空] clientId={}", clientId);
- return;
- }
- String[] parts = parseUsername(username);
- if (parts == null) {
- return;
- }
-
- // 更新设备状态为在线
- IotDeviceStateUpdateReqDTO updateReqDTO = new IotDeviceStateUpdateReqDTO();
- updateReqDTO.setProductKey(parts[1]);
- updateReqDTO.setDeviceName(parts[0]);
- updateReqDTO.setState(IotDeviceStateEnum.ONLINE.getState());
- updateReqDTO.setProcessId(IotPluginCommonUtils.getProcessId());
- updateReqDTO.setReportTime(LocalDateTime.now());
- CommonResult result = deviceUpstreamApi.updateDeviceState(updateReqDTO);
- if (result.getCode() != 0 || !result.getData()) {
- log.error("[handleClientConnected][更新设备状态为在线失败] clientId={}, username={}, code={}, msg={}",
- clientId, username, result.getCode(), result.getMsg());
- } else {
- log.info("[handleClientConnected][更新设备状态为在线成功] clientId={}, username={}", clientId, username);
- }
- }
-
- /**
- * 处理客户端断开连接事件
- *
- * @param clientId 客户端ID
- * @param username 用户名
- */
- private void handleClientDisconnected(String clientId, String username) {
- // 解析产品标识和设备名称
- if (StrUtil.isEmpty(username) || "undefined".equals(username)) {
- log.warn("[handleClientDisconnected][客户端断开连接事件,但用户名为空] clientId={}", clientId);
- return;
- }
- String[] parts = parseUsername(username);
- if (parts == null) {
- return;
- }
-
- // 更新设备状态为离线
- IotDeviceStateUpdateReqDTO offlineReqDTO = new IotDeviceStateUpdateReqDTO();
- offlineReqDTO.setProductKey(parts[1]);
- offlineReqDTO.setDeviceName(parts[0]);
- offlineReqDTO.setState(IotDeviceStateEnum.OFFLINE.getState());
- offlineReqDTO.setProcessId(IotPluginCommonUtils.getProcessId());
- offlineReqDTO.setReportTime(LocalDateTime.now());
- CommonResult offlineResult = deviceUpstreamApi.updateDeviceState(offlineReqDTO);
- if (offlineResult.getCode() != 0 || !offlineResult.getData()) {
- log.error("[handleClientDisconnected][更新设备状态为离线失败] clientId={}, username={}, code={}, msg={}",
- clientId, username, offlineResult.getCode(), offlineResult.getMsg());
- } else {
- log.info("[handleClientDisconnected][更新设备状态为离线成功] clientId={}, username={}", clientId, username);
- }
- }
-
- /**
- * 解析用户名,格式为 deviceName&productKey
- *
- * @param username 用户名
- * @return 解析结果,[0] 为 deviceName,[1] 为 productKey,解析失败返回 null
- */
- private String[] parseUsername(String username) {
- if (StrUtil.isEmpty(username)) {
- return null;
- }
- String[] parts = username.split("&");
- if (parts.length != 2) {
- log.warn("[parseUsername][用户名格式({})不正确,无法解析产品标识和设备名称]", username);
- return null;
- }
- return parts;
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/resources/application.yml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/resources/application.yml
deleted file mode 100644
index c00621c82a..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/resources/application.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-spring:
- application:
- name: yudao-module-iot-plugin-emqx
-
-yudao:
- iot:
- plugin:
- common:
- upstream-url: http://127.0.0.1:48080
- downstream-port: 8100
- plugin-key: yudao-module-iot-plugin-emqx
- emqx:
- mqtt-host: 127.0.0.1
- mqtt-port: 1883
- mqtt-ssl: false
- mqtt-username: yudao
- mqtt-password: 123456
- mqtt-topics:
- - "/sys/#"
- auth-port: 8101
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
deleted file mode 100644
index 647d551558..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/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.plugin.http.config.IotHttpVertxPlugin
-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
deleted file mode 100644
index a8e599654c..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/pom.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-
-
-
- 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.IotHttpVertxPlugin
- ${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
-
-
-
-
-
-
-
-
-
-
- cn.iocoder.boot
- yudao-module-iot-plugin-common
- ${revision}
-
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
-
- io.vertx
- vertx-web
-
-
-
-
- cn.iocoder.boot
- yudao-module-iot-plugin-script
- ${revision}
-
-
-
\ 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
deleted file mode 100644
index 9b79e6152f..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/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-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/IotHttpPluginApplication.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/IotHttpPluginApplication.java
deleted file mode 100644
index 07d4a4790e..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/IotHttpPluginApplication.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.http;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.WebApplicationType;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-// TODO @芋艿:是不是搞成 cn.iocoder.yudao.module.iot.plugin?或者 common、script 要自动配置
-/**
- * 独立运行入口
- */
-@Slf4j
-@SpringBootApplication(scanBasePackages = {
- "cn.iocoder.yudao.module.iot.plugin.common", // common 的包
- "cn.iocoder.yudao.module.iot.plugin.http", // http 的包
- "cn.iocoder.yudao.module.iot.plugin.script" // script 的包
-})
-public class IotHttpPluginApplication {
-
- public static void main(String[] args) {
- SpringApplication application = new SpringApplication(IotHttpPluginApplication.class);
- application.setWebApplicationType(WebApplicationType.NONE);
- application.run(args);
- log.info("[main][独立模式启动完成]");
- }
-
-}
\ 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/IotHttpVertxPlugin.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/IotHttpVertxPlugin.java
deleted file mode 100644
index f704c18443..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/IotHttpVertxPlugin.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.http.config;
-
-import cn.hutool.core.lang.Assert;
-import cn.hutool.extra.spring.SpringUtil;
-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;
-
-// TODO @芋艿:完善注释
-/**
- * 负责插件的启动和停止,与 Vert.x 的生命周期管理
- */
-@Slf4j
-public class IotHttpVertxPlugin extends SpringPlugin {
-
- public IotHttpVertxPlugin(PluginWrapper wrapper) {
- super(wrapper);
- }
-
- @Override
- public void start() {
- log.info("[HttpVertxPlugin][HttpVertxPlugin 插件启动开始...]");
- try {
- ApplicationContext pluginContext = getApplicationContext();
- Assert.notNull(pluginContext, "pluginContext 不能为空");
- log.info("[HttpVertxPlugin][HttpVertxPlugin 插件启动成功...]");
- } catch (Exception e) {
- log.error("[HttpVertxPlugin][HttpVertxPlugin 插件开启动异常...]", e);
- }
- }
-
- @Override
- public void stop() {
- log.info("[HttpVertxPlugin][HttpVertxPlugin 插件停止开始...]");
- try {
- log.info("[HttpVertxPlugin][HttpVertxPlugin 插件停止成功...]");
- } catch (Exception e) {
- log.error("[HttpVertxPlugin][HttpVertxPlugin 插件停止异常...]", e);
- }
- }
-
- // TODO @芋艿:思考下,未来要不要。。。
- @Override
- protected ApplicationContext createApplicationContext() {
- // 创建插件自己的 ApplicationContext
- AnnotationConfigApplicationContext pluginContext = new AnnotationConfigApplicationContext();
- // 设置父容器为主应用的 ApplicationContext (确保主应用中提供的类可用)
- pluginContext.setParent(SpringUtil.getApplicationContext());
- // 继续使用插件自己的 ClassLoader 以加载插件内部的类
- pluginContext.setClassLoader(getWrapper().getPluginClassLoader());
- // 扫描当前插件的自动配置包
- // TODO @芋艿:后续看看,怎么配置类包
- pluginContext.scan("cn.iocoder.yudao.module.iot.plugin.http.config");
- pluginContext.refresh();
- return pluginContext;
- }
-
-}
\ 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/IotPluginHttpAutoConfiguration.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/IotPluginHttpAutoConfiguration.java
deleted file mode 100644
index 133d463344..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/IotPluginHttpAutoConfiguration.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.http.config;
-
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
-import cn.iocoder.yudao.module.iot.plugin.http.downstream.IotDeviceDownstreamHandlerImpl;
-import cn.iocoder.yudao.module.iot.plugin.http.upstream.IotDeviceUpstreamServer;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * IoT 插件 HTTP 的专用自动配置类
- *
- * @author haohao
- */
-@Configuration
-@EnableConfigurationProperties(IotPluginHttpProperties.class)
-public class IotPluginHttpAutoConfiguration {
-
- @Bean(initMethod = "start", destroyMethod = "stop")
- public IotDeviceUpstreamServer deviceUpstreamServer(IotDeviceUpstreamApi deviceUpstreamApi,
- IotPluginHttpProperties properties,
- ApplicationContext applicationContext) {
- return new IotDeviceUpstreamServer(properties, deviceUpstreamApi, applicationContext);
- }
-
- @Bean
- public IotDeviceDownstreamHandler deviceDownstreamHandler() {
- return new IotDeviceDownstreamHandlerImpl();
- }
-
-}
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/IotPluginHttpProperties.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/IotPluginHttpProperties.java
deleted file mode 100644
index 49dca81261..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/config/IotPluginHttpProperties.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.http.config;
-
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.validation.annotation.Validated;
-
-@ConfigurationProperties(prefix = "yudao.iot.plugin.http")
-@Validated
-@Data
-public class IotPluginHttpProperties {
-
- /**
- * HTTP 服务端口
- */
- private Integer serverPort;
-
-}
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/downstream/IotDeviceDownstreamHandlerImpl.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/downstream/IotDeviceDownstreamHandlerImpl.java
deleted file mode 100644
index 869fe72345..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/downstream/IotDeviceDownstreamHandlerImpl.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.http.downstream;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.*;
-import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
-
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED;
-
-/**
- * HTTP 插件的 {@link IotDeviceDownstreamHandler} 实现类
- *
- * 但是:由于设备通过 HTTP 短链接接入,导致其实无法下行指导给 device 设备,所以基本都是直接返回失败!!!
- * 类似 MQTT、WebSocket、TCP 插件,是可以实现下行指令的。
- *
- * @author 芋道源码
- */
-public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandler {
-
- @Override
- public CommonResult invokeDeviceService(IotDeviceServiceInvokeReqDTO invokeReqDTO) {
- return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持调用设备服务");
- }
-
- @Override
- public CommonResult getDeviceProperty(IotDevicePropertyGetReqDTO getReqDTO) {
- return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持获取设备属性");
- }
-
- @Override
- public CommonResult setDeviceProperty(IotDevicePropertySetReqDTO setReqDTO) {
- return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
- }
-
- @Override
- public CommonResult setDeviceConfig(IotDeviceConfigSetReqDTO setReqDTO) {
- return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
- }
-
- @Override
- public CommonResult upgradeDeviceOta(IotDeviceOtaUpgradeReqDTO upgradeReqDTO) {
- return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
- }
-
-}
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/script/HttpScriptService.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/script/HttpScriptService.java
deleted file mode 100644
index 0312cba22f..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/script/HttpScriptService.java
+++ /dev/null
@@ -1,236 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.http.script;
-
-import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.module.iot.plugin.script.context.PluginScriptContext;
-import cn.iocoder.yudao.module.iot.plugin.script.service.ScriptService;
-import io.vertx.core.json.JsonObject;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * HTTP 协议脚本处理服务
- * 用于管理和执行设备数据解析脚本
- *
- * @author haohao
- */
-@Service
-@RequiredArgsConstructor
-@Slf4j
-public class HttpScriptService {
-
- private final ScriptService scriptService;
-
- // TODO @haohao:后续可以考虑放到 guava 缓存
- // TODO @haohao:可能要抽一个 script factory 之类的?方便多个 emqx、http 之类复用?
- /**
- * 脚本缓存,按产品 Key 缓存脚本内容
- */
- private final Map scriptCache = new ConcurrentHashMap<>();
-
- /**
- * 解析设备属性数据
- *
- * @param productKey 产品Key
- * @param deviceName 设备名称
- * @param payload 设备上报的原始数据
- * @return 解析后的属性数据
- */
- @SuppressWarnings("unchecked")
- public Map parsePropertyData(String productKey, String deviceName, JsonObject payload) {
- // 如果没有脚本,直接返回原始数据
- String script = getScriptByProductKey(productKey);
- if (StrUtil.isBlank(script)) {
- if (payload != null && payload.containsKey("params")) {
- return payload.getJsonObject("params").getMap();
- }
- return new HashMap<>();
- }
-
- try {
- // 创建脚本上下文
- PluginScriptContext context = new PluginScriptContext();
- context.withDeviceContext(productKey + ":" + deviceName, null);
- context.withParameter("payload", payload.toString());
- context.withParameter("method", "property");
-
- // 执行脚本
- Object result = scriptService.executeJavaScript(script, context);
- log.debug("[parsePropertyData][产品:{} 设备:{} 原始数据:{} 解析结果:{}]",
- productKey, deviceName, payload, result);
-
- // 处理结果
- if (result instanceof Map) {
- return (Map) result;
- } else if (result instanceof String) {
- try {
- return new JsonObject((String) result).getMap();
- } catch (Exception e) {
- log.warn("[parsePropertyData][脚本返回的字符串不是有效的JSON] result:{}", result);
- }
- }
- } catch (Exception e) {
- log.error("[parsePropertyData][执行脚本解析属性数据异常] productKey:{} deviceName:{}",
- productKey, deviceName, e);
- }
-
- // TODO @芋艿:解析失败,是不是不能返回空?!
- // 解析失败,返回空数据
- return new HashMap<>();
- }
-
- /**
- * 解析设备事件数据
- *
- * @param productKey 产品Key
- * @param deviceName 设备名称
- * @param identifier 事件标识符
- * @param payload 设备上报的原始数据
- * @return 解析后的事件数据
- */
- @SuppressWarnings("unchecked")
- public Map parseEventData(String productKey, String deviceName, String identifier,
- JsonObject payload) {
- // 如果没有脚本,直接返回原始数据
- String script = getScriptByProductKey(productKey);
- if (StrUtil.isBlank(script)) {
- if (payload != null && payload.containsKey("params")) {
- return payload.getJsonObject("params").getMap();
- }
- return new HashMap<>();
- }
-
- try {
- // 创建脚本上下文
- PluginScriptContext context = new PluginScriptContext();
- context.withDeviceContext(productKey + ":" + deviceName, null);
- context.withParameter("payload", payload.toString());
- context.withParameter("method", "event");
- context.withParameter("identifier", identifier);
-
- // 执行脚本
- Object result = scriptService.executeJavaScript(script, context);
- log.debug("[parseEventData][产品:{} 设备:{} 事件:{} 原始数据:{} 解析结果:{}]",
- productKey, deviceName, identifier, payload, result);
-
- // 处理结果
- // TODO @haohao:处理结果,可以复用么?
- if (result instanceof Map) {
- return (Map) result;
- } else if (result instanceof String) {
- try {
- return new JsonObject((String) result).getMap();
- } catch (Exception e) {
- log.warn("[parseEventData][脚本返回的字符串不是有效的 JSON] result:{}", result);
- }
- }
- } catch (Exception e) {
- log.error("[parseEventData][执行脚本解析事件数据异常] productKey:{} deviceName:{} identifier:{}",
- productKey, deviceName, identifier, e);
- }
-
- // TODO @芋艿:解析失败,是不是不能返回空?!
- // 解析失败,返回空数据
- return new HashMap<>();
- }
-
- /**
- * 根据产品Key获取脚本
- *
- * @param productKey 产品Key
- * @return 脚本内容
- */
- private String getScriptByProductKey(String productKey) {
- // 从缓存中获取脚本
- String script = scriptCache.get(productKey);
- if (script != null) {
- return script;
- }
-
- // TODO: 实际应用中,这里应从数据库或配置中心获取产品对应的脚本
- // 此处仅为示例,提供一个默认脚本
- if ("example_product".equals(productKey)) {
- script = "/**\n" +
- " * 设备数据解析脚本示例\n" +
- " * @param payload 设备上报的原始数据\n" +
- " * @param method 方法类型:property(属性)或event(事件)\n" +
- " * @param identifier 事件标识符(仅当method为event时有值)\n" +
- " * @return 解析后的数据\n" +
- " */\n" +
- "function parse() {\n" +
- " // 解析JSON数据\n" +
- " var data = JSON.parse(payload);\n" +
- " var result = {};\n" +
- " \n" +
- " // 根据方法类型处理\n" +
- " if (method === 'property') {\n" +
- " // 属性数据解析\n" +
- " if (data.params) {\n" +
- " // 直接返回params中的数据\n" +
- " return data.params;\n" +
- " }\n" +
- " } else if (method === 'event') {\n" +
- " // 事件数据解析\n" +
- " if (data.params) {\n" +
- " return data.params;\n" +
- " }\n" +
- " }\n" +
- " \n" +
- " return result;\n" +
- "}\n" +
- "\n" +
- "// 执行解析\n" +
- "parse();";
-
- // 缓存脚本
- scriptCache.put(productKey, script);
- }
-
- return script;
- }
-
- /**
- * 设置产品解析脚本
- *
- * @param productKey 产品 Key
- * @param script 脚本内容
- */
- public void setScript(String productKey, String script) {
- // TODO @haohao:if return 会好点哈
- if (StrUtil.isNotBlank(productKey) && StrUtil.isNotBlank(script)) {
- // 验证脚本是否有效
- if (scriptService.validateScript("js", script)) {
- scriptCache.put(productKey, script);
- log.info("[setScript][设置产品:{}的解析脚本成功]", productKey);
- } else {
- log.warn("[setScript][脚本验证失败,不更新缓存] productKey:{}", productKey);
- }
- }
- }
-
- /**
- * 清除产品解析脚本
- *
- * @param productKey 产品 Key
- */
- public void clearScript(String productKey) {
- if (StrUtil.isBlank(productKey)) {
- return;
- }
- scriptCache.remove(productKey);
- log.info("[clearScript][清除产品({})的解析脚本]", productKey);
- }
-
- /**
- * 清除所有脚本缓存
- */
- public void clearAllScripts() {
- scriptCache.clear();
- log.info("[clearAllScripts][清除所有脚本缓存]");
- }
-
-}
\ 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/upstream/IotDeviceUpstreamServer.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/IotDeviceUpstreamServer.java
deleted file mode 100644
index 5a0257cac6..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/IotDeviceUpstreamServer.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.http.upstream;
-
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.plugin.http.config.IotPluginHttpProperties;
-import cn.iocoder.yudao.module.iot.plugin.http.upstream.router.IotDeviceUpstreamVertxHandler;
-import io.vertx.core.Vertx;
-import io.vertx.core.http.HttpServer;
-import io.vertx.ext.web.Router;
-import io.vertx.ext.web.handler.BodyHandler;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.ApplicationContext;
-
-/**
- * IoT 设备下行服务端,接收来自 device 设备的请求,转发给 server 服务器
- *
- * 协议:HTTP
- *
- * @author haohao
- */
-@Slf4j
-public class IotDeviceUpstreamServer {
-
- private final Vertx vertx;
- private final HttpServer server;
- private final IotPluginHttpProperties properties;
-
- public IotDeviceUpstreamServer(IotPluginHttpProperties properties,
- IotDeviceUpstreamApi deviceUpstreamApi,
- ApplicationContext applicationContext) {
- this.properties = properties;
- // 创建 Vertx 实例
- this.vertx = Vertx.vertx();
- // 创建 Router 实例
- Router router = Router.router(vertx);
- router.route().handler(BodyHandler.create()); // 处理 Body
-
- // 使用统一的 Handler 处理所有上行请求
- IotDeviceUpstreamVertxHandler upstreamHandler = new IotDeviceUpstreamVertxHandler(deviceUpstreamApi, applicationContext);
- router.post(IotDeviceUpstreamVertxHandler.PROPERTY_PATH).handler(upstreamHandler);
- router.post(IotDeviceUpstreamVertxHandler.EVENT_PATH).handler(upstreamHandler);
-
- // 创建 HttpServer 实例
- this.server = vertx.createHttpServer().requestHandler(router);
- }
-
- /**
- * 启动 HTTP 服务器
- */
- public void start() {
- log.info("[start][开始启动]");
- server.listen(properties.getServerPort())
- .toCompletionStage()
- .toCompletableFuture()
- .join();
- log.info("[start][启动完成,端口({})]", this.server.actualPort());
- }
-
- /**
- * 停止所有
- */
- public void stop() {
- log.info("[stop][开始关闭]");
- try {
- // 关闭 HTTP 服务器
- if (server != null) {
- server.close()
- .toCompletionStage()
- .toCompletableFuture()
- .join();
- }
-
- // 关闭 Vertx 实例
- if (vertx != null) {
- vertx.close()
- .toCompletionStage()
- .toCompletableFuture()
- .join();
- }
- log.info("[stop][关闭完成]");
- } catch (Exception e) {
- log.error("[stop][关闭异常]", e);
- throw new RuntimeException(e);
- }
- }
-}
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/upstream/router/IotDeviceUpstreamVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDeviceUpstreamVertxHandler.java
deleted file mode 100644
index 2aec09425b..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/upstream/router/IotDeviceUpstreamVertxHandler.java
+++ /dev/null
@@ -1,212 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.http.upstream.router;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.core.util.ObjUtil;
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEventReportReqDTO;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDevicePropertyReportReqDTO;
-import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceStateUpdateReqDTO;
-import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;
-import cn.iocoder.yudao.module.iot.plugin.common.pojo.IotStandardResponse;
-import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
-import cn.iocoder.yudao.module.iot.plugin.http.script.HttpScriptService;
-import io.vertx.core.Handler;
-import io.vertx.core.json.JsonObject;
-import io.vertx.ext.web.RoutingContext;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.ApplicationContext;
-
-import java.time.LocalDateTime;
-import java.util.HashMap;
-import java.util.Map;
-
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
-import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
-
-/**
- * IoT 设备上行统一处理的 Vert.x Handler
- *
- * 统一处理设备属性上报和事件上报的请求
- *
- * @author haohao
- */
-@Slf4j
-public class IotDeviceUpstreamVertxHandler implements Handler {
-
- /**
- * 属性上报路径
- */
- public static final String PROPERTY_PATH = "/sys/:productKey/:deviceName/thing/event/property/post";
- /**
- * 事件上报路径
- */
- public static final String EVENT_PATH = "/sys/:productKey/:deviceName/thing/event/:identifier/post";
-
- private static final String PROPERTY_METHOD = "thing.event.property.post";
- private static final String EVENT_METHOD_PREFIX = "thing.event.";
- private static final String EVENT_METHOD_SUFFIX = ".post";
-
- private final IotDeviceUpstreamApi deviceUpstreamApi;
- private final HttpScriptService scriptService;
-
- public IotDeviceUpstreamVertxHandler(IotDeviceUpstreamApi deviceUpstreamApi,
- ApplicationContext applicationContext) {
- this.deviceUpstreamApi = deviceUpstreamApi;
- this.scriptService = applicationContext.getBean(HttpScriptService.class);
- }
-
- @Override
- public void handle(RoutingContext routingContext) {
- String path = routingContext.request().path();
- String requestId = IdUtil.fastSimpleUUID();
-
- try {
- // 1. 解析通用参数
- String productKey = routingContext.pathParam("productKey");
- String deviceName = routingContext.pathParam("deviceName");
- JsonObject body = routingContext.body().asJsonObject();
- requestId = ObjUtil.defaultIfBlank(body.getString("id"), requestId);
-
- // 2. 根据路径模式处理不同类型的请求
- CommonResult result;
- String method;
- if (path.matches(".*/thing/event/property/post")) {
- // 处理属性上报
- IotDevicePropertyReportReqDTO reportReqDTO = parsePropertyReportRequest(productKey, deviceName,
- requestId, body);
-
- // 设备上线
- updateDeviceState(reportReqDTO.getProductKey(), reportReqDTO.getDeviceName());
-
- // 属性上报
- result = deviceUpstreamApi.reportDeviceProperty(reportReqDTO);
- method = PROPERTY_METHOD;
- } else if (path.matches(".*/thing/event/.+/post")) {
- // 处理事件上报
- String identifier = routingContext.pathParam("identifier");
- IotDeviceEventReportReqDTO reportReqDTO = parseEventReportRequest(productKey, deviceName, identifier,
- requestId, body);
-
- // 设备上线
- updateDeviceState(reportReqDTO.getProductKey(), reportReqDTO.getDeviceName());
-
- // 事件上报
- result = deviceUpstreamApi.reportDeviceEvent(reportReqDTO);
- method = EVENT_METHOD_PREFIX + identifier + EVENT_METHOD_SUFFIX;
- } else {
- // 不支持的请求路径
- IotStandardResponse errorResponse = IotStandardResponse.error(requestId, "unknown",
- BAD_REQUEST.getCode(), "不支持的请求路径");
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- return;
- }
-
- // 3. 返回标准响应
- IotStandardResponse response;
- if (result.isSuccess()) {
- response = IotStandardResponse.success(requestId, method, result.getData());
- } else {
- response = IotStandardResponse.error(requestId, method, result.getCode(), result.getMsg());
- }
- IotPluginCommonUtils.writeJsonResponse(routingContext, response);
- } catch (Exception e) {
- log.error("[handle][处理上行请求异常] path={}", path, e);
- String method = path.contains("/property/") ? PROPERTY_METHOD
- : EVENT_METHOD_PREFIX + (routingContext.pathParams().containsKey("identifier")
- ? routingContext.pathParam("identifier")
- : "unknown") + EVENT_METHOD_SUFFIX;
- IotStandardResponse errorResponse = IotStandardResponse.error(requestId, method,
- INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
- IotPluginCommonUtils.writeJsonResponse(routingContext, errorResponse);
- }
- }
-
- /**
- * 更新设备状态
- *
- * @param productKey 产品 Key
- * @param deviceName 设备名称
- */
- private void updateDeviceState(String productKey, String deviceName) {
- deviceUpstreamApi.updateDeviceState(((IotDeviceStateUpdateReqDTO) new IotDeviceStateUpdateReqDTO()
- .setRequestId(IdUtil.fastSimpleUUID()).setProcessId(IotPluginCommonUtils.getProcessId())
- .setReportTime(LocalDateTime.now())
- .setProductKey(productKey).setDeviceName(deviceName)).setState(IotDeviceStateEnum.ONLINE.getState()));
- }
-
- /**
- * 解析属性上报请求
- *
- * @param productKey 产品 Key
- * @param deviceName 设备名称
- * @param requestId 请求 ID
- * @param body 请求体
- * @return 属性上报请求 DTO
- */
- private IotDevicePropertyReportReqDTO parsePropertyReportRequest(String productKey, String deviceName,
- String requestId, JsonObject body) {
- // 使用脚本解析数据
- Map properties = scriptService.parsePropertyData(productKey, deviceName, body);
-
- // 如果脚本解析结果为空,使用默认解析逻辑
- // TODO @芋艿:注释说明一下,为什么要这么处理?
- if (CollUtil.isNotEmpty(properties)) {
- properties = new HashMap<>();
- Map params = body.getJsonObject("params") != null ?
- body.getJsonObject("params").getMap() : null;
- if (params != null) {
- // 将标准格式的 params 转换为平台需要的 properties 格式
- for (Map.Entry entry : params.entrySet()) {
- String key = entry.getKey();
- Object valueObj = entry.getValue();
- // 如果是复杂结构(包含 value 和 time)
- if (valueObj instanceof Map) {
- @SuppressWarnings("unchecked")
- Map valueMap = (Map) valueObj;
- properties.put(key, valueMap.getOrDefault("value", valueObj));
- } else {
- properties.put(key, valueObj);
- }
- }
- }
- }
-
- // 构建属性上报请求 DTO
- return ((IotDevicePropertyReportReqDTO) new IotDevicePropertyReportReqDTO().setRequestId(requestId)
- .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
- .setProductKey(productKey).setDeviceName(deviceName)).setProperties(properties);
- }
-
- /**
- * 解析事件上报请求
- *
- * @param productKey 产品K ey
- * @param deviceName 设备名称
- * @param identifier 事件标识符
- * @param requestId 请求 ID
- * @param body 请求体
- * @return 事件上报请求 DTO
- */
- private IotDeviceEventReportReqDTO parseEventReportRequest(String productKey, String deviceName, String identifier,
- String requestId, JsonObject body) {
- // 使用脚本解析事件数据
- Map params = scriptService.parseEventData(productKey, deviceName, identifier, body);
-
- // 如果脚本解析结果为空,使用默认解析逻辑
- if (CollUtil.isNotEmpty(params)) {
- if (body.containsKey("params")) {
- params = body.getJsonObject("params").getMap();
- } else {
- // 兼容旧格式
- params = new HashMap<>();
- }
- }
-
- // 构建事件上报请求 DTO
- return ((IotDeviceEventReportReqDTO) new IotDeviceEventReportReqDTO().setRequestId(requestId)
- .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now())
- .setProductKey(productKey).setDeviceName(deviceName)).setIdentifier(identifier).setParams(params);
- }
-}
\ No newline at end of file
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
deleted file mode 100644
index f195628a6a..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/resources/application.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-spring:
- application:
- name: yudao-module-iot-plugin-http
-
-yudao:
- iot:
- plugin:
- common:
- upstream-url: http://127.0.0.1:48080
- downstream-port: 8093
- plugin-key: yudao-module-iot-plugin-http
- http:
- server-port: 8092
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
deleted file mode 100644
index 939e0f6929..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/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-plugins/yudao-module-iot-plugin-mqtt/pom.xml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/pom.xml
deleted file mode 100644
index f1fba50590..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/pom.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-
-
-
- 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
deleted file mode 100644
index daec9e4315..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/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-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
deleted file mode 100644
index 7883fa8b12..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttPlugin.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin;
-
-import lombok.extern.slf4j.Slf4j;
-import org.pf4j.Plugin;
-import org.pf4j.PluginWrapper;
-
-// TODO @芋艿:暂未实现
-@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
deleted file mode 100644
index dd0c5da372..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-mqtt/src/main/java/cn/iocoder/yudao/module/iot/plugin/MqttServerExtension.java
+++ /dev/null
@@ -1,232 +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;
-
-// TODO @芋艿:暂未实现
-/**
- * 根据官方示例,整合常见 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/yudao-module-iot-plugin-script/pom.xml b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/pom.xml
deleted file mode 100644
index 917441e88d..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/pom.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
- yudao-module-iot-plugins
- cn.iocoder.boot
- ${revision}
-
- 4.0.0
-
- yudao-module-iot-plugin-script
- jar
-
- ${project.artifactId}
- IoT 插件脚本模块,提供JS引擎解析等功能
-
-
-
-
- cn.iocoder.boot
- yudao-module-iot-api
- ${revision}
-
-
-
-
- org.springframework
- spring-context
-
-
-
-
- cn.hutool
- hutool-all
-
-
- org.projectlombok
- lombok
- true
-
-
- org.slf4j
- slf4j-api
-
-
-
-
- org.openjdk.nashorn
- nashorn-core
- 15.4
-
-
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
-
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/ScriptExample.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/ScriptExample.java
deleted file mode 100644
index b72165cc70..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/ScriptExample.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.script;
-
-import cn.iocoder.yudao.module.iot.plugin.script.context.PluginScriptContext;
-import cn.iocoder.yudao.module.iot.plugin.script.service.ScriptService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.HashMap;
-import java.util.Map;
-
-// TODO @haohao:写到单测类里;
-/**
- * 脚本使用示例类
- */
-@Component
-@Slf4j
-public class ScriptExample {
-
- @Autowired
- private ScriptService scriptService;
-
- /**
- * 示例:执行简单的JavaScript脚本
- */
- public void executeSimpleScript() {
- String script = "var result = a + b; result;";
-
- Map params = new HashMap<>();
- params.put("a", 10);
- params.put("b", 20);
-
- Object result = scriptService.executeJavaScript(script, params);
- log.info("脚本执行结果: {}", result);
- }
-
- /**
- * 示例:使用脚本处理设备数据
- *
- * @param deviceId 设备ID
- * @param payload 设备原始数据
- * @return 处理后的数据
- */
- @SuppressWarnings("unchecked")
- public Map processDeviceData(String deviceId, String payload) {
- // 设备数据处理脚本
- String script = "function process() {\n" +
- " var data = JSON.parse(payload);\n" +
- " var result = {};\n" +
- " // 提取温度信息\n" +
- " if (data.temp) {\n" +
- " result.temperature = data.temp;\n" +
- " }\n" +
- " // 提取湿度信息\n" +
- " if (data.hum) {\n" +
- " result.humidity = data.hum;\n" +
- " }\n" +
- " // 计算额外信息\n" +
- " if (data.temp && data.temp > 30) {\n" +
- " result.alert = true;\n" +
- " result.alertMessage = '温度过高警告';\n" +
- " }\n" +
- " return result;\n" +
- "}\n" +
- "process();";
-
- // 创建脚本上下文
- PluginScriptContext context = new PluginScriptContext();
- context.withDeviceContext(deviceId, null);
- context.withParameter("payload", payload);
-
- try {
- Object result = scriptService.executeJavaScript(script, context);
- if (result != null) {
- // 处理结果
- log.info("设备数据处理结果: {}", result);
-
- // 安全地将结果转换为Map
- if (result instanceof Map) {
- return (Map) result;
- } else {
- log.warn("脚本返回结果类型不是Map: {}", result.getClass().getName());
- }
- }
- } catch (Exception e) {
- log.error("处理设备数据失败: {}", e.getMessage());
- }
-
- return new HashMap<>();
- }
-
- /**
- * 示例:生成设备命令
- *
- * @param deviceId 设备ID
- * @param command 命令名称
- * @param params 命令参数
- * @return 格式化的命令字符串
- */
- public String generateDeviceCommand(String deviceId, String command, Map params) {
- // 命令生成脚本
- String script = "function generateCommand(cmd, params) {\n" +
- " var result = { 'cmd': cmd };\n" +
- " if (params) {\n" +
- " result.params = params;\n" +
- " }\n" +
- " result.timestamp = new Date().getTime();\n" +
- " result.deviceId = deviceId;\n" +
- " return JSON.stringify(result);\n" +
- "}\n" +
- "generateCommand(command, commandParams);";
-
- // 创建脚本上下文
- PluginScriptContext context = new PluginScriptContext();
- context.setParameter("deviceId", deviceId);
- context.setParameter("command", command);
- context.setParameter("commandParams", params);
-
- try {
- Object result = scriptService.executeJavaScript(script, context);
- if (result instanceof String) {
- return (String) result;
- } else if (result != null) {
- log.warn("脚本返回结果类型不是String: {}", result.getClass().getName());
- }
- } catch (Exception e) {
- log.error("生成设备命令失败: {}", e.getMessage());
- }
-
- return null;
- }
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/config/ScriptConfiguration.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/config/ScriptConfiguration.java
deleted file mode 100644
index 511ca8bc54..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/config/ScriptConfiguration.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.script.config;
-
-import cn.iocoder.yudao.module.iot.plugin.script.engine.ScriptEngineFactory;
-import cn.iocoder.yudao.module.iot.plugin.script.service.ScriptService;
-import cn.iocoder.yudao.module.iot.plugin.script.service.ScriptServiceImpl;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-// TODO @haohao:这个模块,是不是融合到 plugin-common 里哈?
-/**
- * 脚本模块配置类
- */
-@Configuration
-public class ScriptConfiguration {
-
- /**
- * 创建脚本引擎工厂
- *
- * @return 脚本引擎工厂
- */
- @Bean
- public ScriptEngineFactory scriptEngineFactory() {
- return new ScriptEngineFactory();
- }
-
- /**
- * 创建脚本服务
- *
- * @param engineFactory 脚本引擎工厂
- * @return 脚本服务
- */
- @Bean
- public ScriptService scriptService(ScriptEngineFactory engineFactory) {
- ScriptServiceImpl service = new ScriptServiceImpl();
- // TODO @haohao:如果有其他配置可以在这里设置
- return service;
- }
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/PluginScriptContext.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/PluginScriptContext.java
deleted file mode 100644
index 27956453d8..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/PluginScriptContext.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.script.context;
-
-import lombok.Getter;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 插件脚本上下文,提供插件执行脚本的上下文环境
- */
-public class PluginScriptContext implements ScriptContext {
-
- /**
- * 上下文参数
- */
- @Getter
- private final Map parameters = new HashMap<>();
-
- /**
- * 上下文函数
- */
- @Getter
- private final Map functions = new HashMap<>();
-
- /**
- * 日志函数接口
- */
- public interface LogFunction {
-
- void log(String message);
-
- }
-
- /**
- * 构建插件脚本上下文
- */
- public PluginScriptContext() {
- // 初始化上下文,注册一些基础函数
- LogFunction logFunction = message -> System.out.println("[Plugin Script] " + message);
- registerFunction("log", logFunction);
- }
-
- /**
- * 构建插件脚本上下文
- *
- * @param parameters 初始参数
- */
- public PluginScriptContext(Map parameters) {
- this();
- if (parameters != null) {
- this.parameters.putAll(parameters);
- }
- }
-
- @Override
- public void setParameter(String key, Object value) {
- parameters.put(key, value);
- }
-
- @Override
- public Object getParameter(String key) {
- return parameters.get(key);
- }
-
- @Override
- public void registerFunction(String name, Object function) {
- functions.put(name, function);
- }
-
- // TODO @haohao:setParameters?这样的话,with 都是一些比较个性的参数
- /**
- * 批量设置参数
- *
- * @param params 参数Map
- * @return 当前上下文对象
- */
- public PluginScriptContext withParameters(Map params) {
- if (params != null) {
- parameters.putAll(params);
- }
- return this;
- }
-
- /**
- * 添加设备相关的上下文参数
- *
- * @param deviceId 设备 ID
- * @param deviceData 设备数据
- * @return 当前上下文对象
- */
- // TODO @haohao:是不是加个 (String productKey, String deviceName, Map deviceData) {
- public PluginScriptContext withDeviceContext(String deviceId, Map deviceData) {
- // TODO @haohao:deviceId 一般是分开,还是合并哈?
- parameters.put("deviceId", deviceId);
- parameters.put("deviceData", deviceData);
- return this;
- }
-
- /**
- * 添加消息相关的上下文参数
- *
- * @param topic 消息主题
- * @param payload 消息内容
- * @return 当前上下文对象
- */
- public PluginScriptContext withMessageContext(String topic, Object payload) {
- parameters.put("topic", topic);
- parameters.put("payload", payload);
- return this;
- }
-
- // TODO @haohao:setParameter 可以融合哈?
- /**
- * 设置单个参数
- *
- * @param key 参数名
- * @param value 参数值
- * @return 当前上下文对象
- */
- public PluginScriptContext withParameter(String key, Object value) {
- parameters.put(key, value);
- return this;
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/ScriptContext.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/ScriptContext.java
deleted file mode 100644
index e165bf5afa..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/context/ScriptContext.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.script.context;
-
-import java.util.Map;
-
-/**
- * 脚本上下文接口,定义脚本执行所需的上下文环境
- */
-public interface ScriptContext {
-
- /**
- * 获取上下文参数
- *
- * @return 上下文参数
- */
- Map getParameters();
-
- /**
- * 获取上下文函数
- *
- * @return 上下文函数
- */
- Map getFunctions();
-
- /**
- * 设置上下文参数
- *
- * @param key 参数名
- * @param value 参数值
- */
- void setParameter(String key, Object value);
-
- /**
- * 获取上下文参数
- *
- * @param key 参数名
- * @return 参数值
- */
- Object getParameter(String key);
-
- // TODO @haohao:这个要不也是 setFunction
- /**
- * 注册函数
- *
- * @param name 函数名称
- * @param function 函数对象
- */
- void registerFunction(String name, Object function);
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/AbstractScriptEngine.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/AbstractScriptEngine.java
deleted file mode 100644
index 4549242eef..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/AbstractScriptEngine.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.script.engine;
-
-import cn.iocoder.yudao.module.iot.plugin.script.context.ScriptContext;
-import cn.iocoder.yudao.module.iot.plugin.script.sandbox.ScriptSandbox;
-
-import java.util.Map;
-
-/**
- * 抽象脚本引擎基类,定义脚本引擎的基本功能
- */
-public abstract class AbstractScriptEngine {
-
- protected ScriptSandbox sandbox;
-
- /**
- * 初始化脚本引擎
- */
- public abstract void init();
-
- /**
- * 执行脚本
- *
- * @param script 脚本内容
- * @param context 脚本上下文
- * @return 脚本执行结果
- */
- public abstract Object execute(String script, ScriptContext context);
-
- /**
- * 执行脚本
- *
- * @param script 脚本内容
- * @param params 脚本参数
- * @return 脚本执行结果
- */
- public abstract Object execute(String script, Map params);
-
- /**
- * 销毁脚本引擎,释放资源
- */
- public abstract void destroy();
-
- /**
- * 设置脚本沙箱
- *
- * @param sandbox 脚本沙箱
- */
- public void setSandbox(ScriptSandbox sandbox) {
- this.sandbox = sandbox;
- }
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/JsScriptEngine.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/JsScriptEngine.java
deleted file mode 100644
index 69ec5cfc20..0000000000
--- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-script/src/main/java/cn/iocoder/yudao/module/iot/plugin/script/engine/JsScriptEngine.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package cn.iocoder.yudao.module.iot.plugin.script.engine;
-
-import cn.hutool.core.map.MapUtil;
-import cn.iocoder.yudao.module.iot.plugin.script.context.ScriptContext;
-import cn.iocoder.yudao.module.iot.plugin.script.sandbox.JsSandbox;
-import cn.iocoder.yudao.module.iot.plugin.script.util.ScriptUtils;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.script.*;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * JavaScript 脚本引擎实现
- * 使用 JSR-223 Nashorn 脚本引擎
- */
-@Slf4j
-public class JsScriptEngine extends AbstractScriptEngine {
-
- /**
- * 默认脚本执行超时时间(毫秒)
- */
- private static final long DEFAULT_TIMEOUT_MS = 5000;
-
- /**
- * JavaScript 引擎名称
- */
- private static final String JS_ENGINE_NAME = "nashorn";
-
- /**
- * 脚本引擎管理器
- */
- private ScriptEngineManager engineManager;
-
- /**
- * 脚本引擎实例
- */
- private ScriptEngine engine;
-
- /**
- * 脚本缓存
- */
- private final Map cachedScripts = new ConcurrentHashMap<>();
-
- @Override
- public void init() {
- log.info("初始化 JavaScript 脚本引擎");
-
- // 创建脚本引擎管理器
- engineManager = new ScriptEngineManager();
-
- // 获取 JavaScript 引擎
- engine = engineManager.getEngineByName(JS_ENGINE_NAME);
- if (engine == null) {
- log.error("无法创建JavaScript引擎,尝试使用 JavaScript 名称获取");
- engine = engineManager.getEngineByName("JavaScript");
- }
- if (engine == null) {
- throw new IllegalStateException("无法创建 JavaScript 引擎,请检查环境配置");
- }
-
- log.info("成功创建JavaScript引擎: {}", engine.getClass().getName());
-
- // 默认使用 JS 沙箱
- if (sandbox == null) {
- setSandbox(new JsSandbox());
- }
- }
-
- @Override
- public Object execute(String script, ScriptContext context) {
- if (engine == null) {
- init();
- }
-
- // 创建可超时执行的任务
- Callable