From 2512f2dde8a0df4fd8f3f4d87bfcc65eaaed69cf Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 31 Jan 2025 19:05:42 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E3=80=91IoT=EF=BC=9A=E4=BC=98=E5=8C=96=20http=20=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=20IotDevicePropertyReportVertxHandler=20=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../IotDevicePropertyGetReqDTO.java | 1 + .../upstream/IotDeviceUpstreamClient.java | 42 ++++----- .../upstream/IotDeviceUpstreamServer.java | 2 +- .../IotDevicePropertyReportVertxHandler.java | 85 +++++++------------ 4 files changed, 51 insertions(+), 79 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDevicePropertyGetReqDTO.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDevicePropertyGetReqDTO.java index 061de5745a..b72d88d974 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDevicePropertyGetReqDTO.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDevicePropertyGetReqDTO.java @@ -5,6 +5,7 @@ import lombok.Data; import java.util.List; +// TODO @芋艿:从 server => plugin => device 是否有必要?从阿里云 iot 来看,没有这个功能?! /** * IoT 设备【属性】获取 Request DTO * 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 index 8310bad5a9..c71606f62d 100644 --- 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 @@ -6,10 +6,11 @@ import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotDeviceEven 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.api.device.dto.control.upstream.IotPluginInstanceHeartbeatReqDTO; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.client.RestTemplate; -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; /** * 设备数据 Upstream 上行客户端 @@ -18,60 +19,51 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; * * @author haohao */ +@RequiredArgsConstructor @Slf4j public class IotDeviceUpstreamClient implements IotDeviceUpstreamApi { public static final String URL_PREFIX = "/rpc-api/iot/device/upstream"; private final RestTemplate restTemplate; + + // TODO @芋艿:改个名字 private final String deviceDataUrl; - // 可以通过构造器把 RestTemplate 和 baseUrl 注入进来 - // TODO @haohao:可以用 lombok 简化 - public IotDeviceUpstreamClient(RestTemplate restTemplate, String deviceDataUrl) { - this.restTemplate = restTemplate; - this.deviceDataUrl = deviceDataUrl; - } - - // TODO @haohao:返回结果,不用 CommonResult 哈。 @Override public CommonResult updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) { String url = deviceDataUrl + URL_PREFIX + "/update-state"; - return doPost(url, updateReqDTO, "updateDeviceState"); + return doPost(url, updateReqDTO); } @Override public CommonResult reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) { String url = deviceDataUrl + URL_PREFIX + "/report-event"; - return doPost(url, reportReqDTO, "reportDeviceEventData"); + return doPost(url, reportReqDTO); } @Override public CommonResult reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) { String url = deviceDataUrl + URL_PREFIX + "/report-property"; - return doPost(url, reportReqDTO, "reportDevicePropertyData"); + return doPost(url, reportReqDTO); } @Override public CommonResult heartbeatPluginInstance(IotPluginInstanceHeartbeatReqDTO heartbeatReqDTO) { String url = deviceDataUrl + URL_PREFIX + "/heartbeat-plugin-instance"; - return doPost(url, heartbeatReqDTO, "heartbeatPluginInstance"); + return doPost(url, heartbeatReqDTO); } - // TODO @haohao:未来可能有 get 类型哈 - /** - * 将与远程服务交互的通用逻辑抽取成一个私有方法 - */ - private CommonResult doPost(String url, T requestBody, String actionName) { - log.info("[{}] Sending request to URL: {}", actionName, url); + @SuppressWarnings("unchecked") + private CommonResult doPost(String url, T requestBody) { try { - // 这里指定返回类型为 CommonResult,根据后台服务返回的实际结构做调整 - restTemplate.postForObject(url, requestBody, CommonResult.class); - // TODO @haohao:check 结果,是否成功 - return success(true); + 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("[{}] Error sending request to URL: {}", actionName, url, e); - return CommonResult.error(400, "Request error: " + e.getMessage()); + 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-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 index e6f4dbb270..87e6a6f85b 100644 --- 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 @@ -31,7 +31,7 @@ public class IotDeviceUpstreamServer { Router router = Router.router(vertx); router.route().handler(BodyHandler.create()); // 处理 Body router.post(IotDevicePropertyReportVertxHandler.PATH) - .handler(new IotDevicePropertyReportVertxHandler(deviceUpstreamApi)); // 处理设备属性上报 + .handler(new IotDevicePropertyReportVertxHandler(deviceUpstreamApi)); // 创建 HttpServer 实例 this.server = vertx.createHttpServer().requestHandler(router); } 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/IotDevicePropertyReportVertxHandler.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/IotDevicePropertyReportVertxHandler.java index 6bf600b145..c75a3a0d51 100644 --- 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/IotDevicePropertyReportVertxHandler.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/IotDevicePropertyReportVertxHandler.java @@ -1,15 +1,15 @@ package cn.iocoder.yudao.module.iot.plugin.http.upstream.router; import cn.hutool.core.util.IdUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; +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.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.util.IotPluginCommonUtils; import io.vertx.core.Handler; -import io.vertx.ext.web.RequestBody; +import io.vertx.core.json.JsonObject; import io.vertx.ext.web.RoutingContext; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -17,8 +17,13 @@ import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; 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 */ @RequiredArgsConstructor @Slf4j @@ -29,69 +34,43 @@ public class IotDevicePropertyReportVertxHandler implements Handler properties = (Map) body.getMap().get("properties"); + reportReqDTO = ((IotDevicePropertyReportReqDTO) + new IotDevicePropertyReportReqDTO().setRequestId(id) + .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) + .setProductKey(productKey).setDeviceName(deviceName)) + .setProperties(properties); } catch (Exception e) { - log.error("[HttpVertxHandler] 请求数据解析失败", e); - ctx.response().setStatusCode(400) - .putHeader("Content-Type", "application/json; charset=UTF-8") - .end(createResponseJson(400, null, null, - "请求数据不是合法的 JSON 格式: " + e.getMessage(), - "thing.event.property.post", "1.0").toString()); + log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e); + IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST)); return; } - String id = jsonData.getStr("id"); - try { - // 设备上线 + // 2. 设备上线 deviceUpstreamApi.updateDeviceState(((IotDeviceStateUpdateReqDTO) new IotDeviceStateUpdateReqDTO().setRequestId(IdUtil.fastSimpleUUID()) .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) - .setProductKey(productKey).setDeviceName(deviceName)) + .setProductKey(reportReqDTO.getProductKey()).setDeviceName(reportReqDTO.getDeviceName())) .setState(IotDeviceStateEnum.ONLINE.getState())); - // 属性上报 - deviceUpstreamApi.reportDeviceProperty(((IotDevicePropertyReportReqDTO) - new IotDevicePropertyReportReqDTO().setRequestId(IdUtil.fastSimpleUUID()) - .setProcessId(IotPluginCommonUtils.getProcessId()).setReportTime(LocalDateTime.now()) - .setProductKey(productKey).setDeviceName(deviceName)) - .setProperties((Map) requestBody.asJsonObject().getMap().get("properties"))); - - ctx.response() - .setStatusCode(200) - .putHeader("Content-Type", "application/json; charset=UTF-8") - .end(createResponseJson(200, new JSONObject(), id, "success", - "thing.event.property.post", "1.0").toString()); + // 3.1 属性上报 + CommonResult result = deviceUpstreamApi.reportDeviceProperty(reportReqDTO); + // 3.2 返回结果 + IotPluginCommonUtils.writeJson(routingContext, result); } catch (Exception e) { - log.error("[HttpVertxHandler] 上报属性数据失败", e); - ctx.response() - .setStatusCode(500) - .putHeader("Content-Type", "application/json; charset=UTF-8") - .end(createResponseJson(500, new JSONObject(), id, - "The format of result is error!", - "thing.event.property.post", "1.0").toString()); + log.error("[handle][请求参数({}) 属性获取异常]", reportReqDTO, e); + IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR)); } } - // TODO @芋艿:抽一个 IotPluginCommonResult 出来?等 mqtt、websocket 出来后,再考虑优化! - private JSONObject createResponseJson(int code, JSONObject data, String id, - String message, String method, String version) { - JSONObject res = new JSONObject(); - res.set("code", code); - res.set("data", data != null ? data : new JSONObject()); - res.set("id", id); - res.set("message", message); - res.set("method", method); - res.set("version", version); - return res; - } - }