From 916024b8914482eb6b4e32f52e75b4193aa4e108 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 21 Jan 2025 19:38:41 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E3=80=91IoT=EF=BC=9A=E9=AA=8C=E8=AF=81=E9=80=9A=E8=BF=87?= =?UTF-8?q?=E7=8B=AC=E7=AB=8B=E3=80=81=E5=86=85=E5=B5=8C=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E7=9A=84=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...-module-iot-http-plugin-2.2.0-snapshot.jar | Bin 0 -> 10353 bytes .../framework/common/enums/RpcConstants.java | 17 +++++++ yudao-module-iot/yudao-module-iot-api/pom.xml | 8 ++++ .../module/iot/api/device/DeviceDataApi.java | 41 ++++++++++++++-- .../device/dto/DeviceDataCreateReqDTO.java | 31 ------------ .../dto/IotDeviceEventReportReqDTO.java | 45 ++++++++++++++++++ .../dto/IotDevicePropertyReportReqDTO.java | 39 +++++++++++++++ .../dto/IotDeviceStatusUpdateReqDTO.java | 40 ++++++++++++++++ .../yudao/module/iot/enums/ApiConstants.java | 16 +++++++ .../iot/api/device/DeviceDataApiImpl.java | 26 ++++++++-- .../iot/emq/service/EmqxServiceImpl.java | 6 +-- .../plugin/UnifiedConfiguration.java | 6 +-- .../device/IotDevicePropertyDataService.java | 4 +- .../IotDevicePropertyDataServiceImpl.java | 7 +-- .../yudao-module-iot-plugin-http/pom.xml | 2 +- .../iot/HttpPluginSpringbootApplication.java | 17 ++++++- .../module/iot/config/TestConfiguration.java | 44 +++++++++++++++-- .../module/iot/service/HttpVertxHandler.java | 8 ++-- 18 files changed, 294 insertions(+), 63 deletions(-) create mode 100644 plugins/yudao-module-iot-http-plugin-2.2.0-snapshot.jar create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/RpcConstants.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/DeviceDataCreateReqDTO.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDeviceEventReportReqDTO.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDevicePropertyReportReqDTO.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDeviceStatusUpdateReqDTO.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ApiConstants.java diff --git a/plugins/yudao-module-iot-http-plugin-2.2.0-snapshot.jar b/plugins/yudao-module-iot-http-plugin-2.2.0-snapshot.jar new file mode 100644 index 0000000000000000000000000000000000000000..fef8d5362c38ea47e769e58933c715d492df719f GIT binary patch literal 10353 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.iocoder.boot yudao-common + + + + org.springframework + spring-web + provided + + diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/DeviceDataApi.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/DeviceDataApi.java index 6eed3592b5..c2d36e18c6 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/DeviceDataApi.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/DeviceDataApi.java @@ -1,8 +1,17 @@ package cn.iocoder.yudao.module.iot.api.device; -import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceEventReportReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceStatusUpdateReqDTO; +import cn.iocoder.yudao.module.iot.enums.ApiConstants; +import jakarta.annotation.security.PermitAll; import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +// TODO 芋艿:名字可能看情况改下 /** * 设备数据 API * @@ -10,11 +19,35 @@ import jakarta.validation.Valid; */ public interface DeviceDataApi { + // TODO @芋艿:可能会调整 + String PREFIX = ApiConstants.PREFIX + "/device-data"; + /** - * 保存设备数据 + * 更新设备状态 * - * @param createDTO 设备数据 + * @param updateReqDTO 更新请求 */ - void saveDeviceData(@Valid DeviceDataCreateReqDTO createDTO); + @PutMapping(PREFIX + "/update-status") + @PermitAll // TODO 芋艿:后续看看怎么优化下 + CommonResult updateDeviceStatus(@Valid @RequestBody IotDeviceStatusUpdateReqDTO updateReqDTO); + + /** + * 上报设备事件数据 + * + * @param reportReqDTO 设备事件 + */ + @PostMapping(PREFIX + "/report-event") + @PermitAll // TODO 芋艿:后续看看怎么优化下 + CommonResult reportDeviceEventData(@Valid @RequestBody IotDeviceEventReportReqDTO reportReqDTO); + + /** + * 上报设备属性数据 + * + * @param reportReqDTO 设备数据 + */ + @PostMapping(PREFIX + "/report-property") + @PermitAll // TODO 芋艿:后续看看怎么优化下 + CommonResult reportDevicePropertyData(@Valid @RequestBody IotDevicePropertyReportReqDTO reportReqDTO); + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/DeviceDataCreateReqDTO.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/DeviceDataCreateReqDTO.java deleted file mode 100644 index 94bc84b804..0000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/DeviceDataCreateReqDTO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.iot.api.device.dto; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import jakarta.validation.constraints.NotNull; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class DeviceDataCreateReqDTO { - - /** - * 产品标识 - */ - @NotNull(message = "产品标识不能为空") - private String productKey; - /** - * 设备名称 - */ - @NotNull(message = "设备名称不能为空") - private String deviceName; - /** - * 消息 - */ - @NotNull(message = "消息不能为空") - private String message; - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDeviceEventReportReqDTO.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDeviceEventReportReqDTO.java new file mode 100644 index 0000000000..373905c946 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDeviceEventReportReqDTO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.iot.api.device.dto; + +import jakarta.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Map; + +/** + * IoT 设备【事件】数据上报 Request DTO + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class IotDeviceEventReportReqDTO { + + // TODO 芋艿:要不要 id + // TODO 芋艿:要不要 time + + /** + * 产品标识 + */ + @NotEmpty(message = "产品标识不能为空") + private String productKey; + /** + * 设备名称 + */ + @NotEmpty(message = "设备名称不能为空") + private String deviceName; + + /** + * 事件标识 + */ + @NotEmpty(message = "事件标识不能为空") + private String identifier; + /** + * 事件参数 + */ + @NotEmpty(message = "事件参数不能为空") + private Map params; + +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDevicePropertyReportReqDTO.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDevicePropertyReportReqDTO.java new file mode 100644 index 0000000000..37a4c6c984 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDevicePropertyReportReqDTO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.iot.api.device.dto; + +import jakarta.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Map; + +/** + * IoT 设备【属性】数据上报 Request DTO + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class IotDevicePropertyReportReqDTO { + + // TODO 芋艿:要不要 id + // TODO 芋艿:要不要 time + + /** + * 产品标识 + */ + @NotEmpty(message = "产品标识不能为空") + private String productKey; + /** + * 设备名称 + */ + @NotEmpty(message = "设备名称不能为空") + private String deviceName; + /** + * 属性参数 + */ + @NotEmpty(message = "属性参数不能为空") + private Map params; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDeviceStatusUpdateReqDTO.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDeviceStatusUpdateReqDTO.java new file mode 100644 index 0000000000..0b08f2bd11 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/IotDeviceStatusUpdateReqDTO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.iot.api.device.dto; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; +import jakarta.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * IoT 设备状态更新 Request DTO + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class IotDeviceStatusUpdateReqDTO { + + // TODO 芋艿:要不要 id + // TODO 芋艿:要不要 time + + /** + * 产品标识 + */ + @NotEmpty(message = "产品标识不能为空") + private String productKey; + /** + * 设备名称 + */ + @NotEmpty(message = "设备名称不能为空") + private String deviceName; + /** + * 设备状态 + */ + @NotEmpty(message = "设备状态不能为空") + @InEnum(IotDeviceStatusEnum.class) // 只使用:在线、离线 + private Integer status; + +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ApiConstants.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ApiConstants.java new file mode 100644 index 0000000000..2c4147be1f --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ApiConstants.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.iot.enums; + +import cn.iocoder.yudao.framework.common.enums.RpcConstants; + +/** + * API 相关的枚举 + * + * @author 芋道源码 + */ +public class ApiConstants { + + public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/iot"; + + public static final String VERSION = "1.0.0"; + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/DeviceDataApiImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/DeviceDataApiImpl.java index eea7b2a963..cdcfdfdfd6 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/DeviceDataApiImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/DeviceDataApiImpl.java @@ -1,16 +1,21 @@ package cn.iocoder.yudao.module.iot.api.device; -import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceEventReportReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceStatusUpdateReqDTO; import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService; -import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + /** * 设备数据 API 实现类 */ -@Service +@RestController @Validated public class DeviceDataApiImpl implements DeviceDataApi { @@ -18,8 +23,19 @@ public class DeviceDataApiImpl implements DeviceDataApi { private IotDevicePropertyDataService deviceDataService; @Override - public void saveDeviceData(DeviceDataCreateReqDTO createDTO) { - deviceDataService.saveDeviceData(createDTO); + public CommonResult updateDeviceStatus(IotDeviceStatusUpdateReqDTO updateReqDTO) { + return success(true); + } + + @Override + public CommonResult reportDeviceEventData(IotDeviceEventReportReqDTO reportReqDTO) { + return success(true); + } + + @Override + public CommonResult reportDevicePropertyData(IotDevicePropertyReportReqDTO reportReqDTO) { + deviceDataService.saveDeviceData(reportReqDTO); + return success(true); } } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java index 3c21a55ca8..222d1d50af 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.iot.emq.service; -import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -34,10 +34,10 @@ public class EmqxServiceImpl implements EmqxService { String productKey = topic.split("/")[2]; String deviceName = topic.split("/")[3]; String message = new String(mqttMessage.getPayload()); - DeviceDataCreateReqDTO createDTO = DeviceDataCreateReqDTO.builder() + IotDevicePropertyReportReqDTO createDTO = IotDevicePropertyReportReqDTO.builder() .productKey(productKey) .deviceName(deviceName) - .message(message) +// .properties(message) // TODO 芋艿:临时去掉,看看 .build(); iotDeviceDataService.saveDeviceData(createDTO); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/UnifiedConfiguration.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/UnifiedConfiguration.java index 150051ce58..e27d9b5fb3 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/UnifiedConfiguration.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/plugin/UnifiedConfiguration.java @@ -7,8 +7,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.nio.file.Paths; - // TODO @芋艿:需要 review 下 @Slf4j @Configuration @@ -21,8 +19,8 @@ public class UnifiedConfiguration { // @DependsOn("deviceDataApiImpl") public SpringPluginManager pluginManager() { log.info("[init][实例化 SpringPluginManager]"); - SpringPluginManager springPluginManager = new SpringPluginManager(Paths.get(pluginsDir)) { -// SpringPluginManager springPluginManager = new SpringPluginManager() { +// SpringPluginManager springPluginManager = new SpringPluginManager(Paths.get(pluginsDir)) { + SpringPluginManager springPluginManager = new SpringPluginManager() { @Override public void startPlugins() { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataService.java index a882b5d6cb..396cbf79fd 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.iot.service.device; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import jakarta.validation.Valid; @@ -28,7 +28,7 @@ public interface IotDevicePropertyDataService { * * @param createDTO 设备数据 */ - void saveDeviceData(DeviceDataCreateReqDTO createDTO); + void saveDeviceData(IotDevicePropertyReportReqDTO createDTO); /** * 获得设备属性最新数据 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataServiceImpl.java index 0f9523414e..aefaac6960 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDevicePropertyDataServiceImpl.java @@ -6,7 +6,7 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; @@ -130,11 +130,12 @@ public class IotDevicePropertyDataServiceImpl implements IotDevicePropertyDataSe } @Override - public void saveDeviceData(DeviceDataCreateReqDTO createDTO) { + public void saveDeviceData(IotDevicePropertyReportReqDTO createDTO) { + // TODO 芋艿:这块需要实现 // 1. 根据产品 key 和设备名称,获得设备信息 IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceName(createDTO.getProductKey(), createDTO.getDeviceName()); // 2. 解析消息,保存数据 - JSONObject jsonObject = new JSONObject(createDTO.getMessage()); + JSONObject jsonObject = new JSONObject(createDTO.getParams()); log.info("[saveDeviceData][productKey({}) deviceName({}) data({})]", createDTO.getProductKey(), createDTO.getDeviceName(), jsonObject); ThingModelMessage thingModelMessage = ThingModelMessage.builder() .id(jsonObject.getStr("id")) diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml index 40bb303bc8..cfea78964c 100644 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/pom.xml @@ -124,7 +124,7 @@ org.springframework.boot - spring-boot-starter + spring-boot-starter-web diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java index 2b871cadea..7b29367d21 100644 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/HttpPluginSpringbootApplication.java @@ -1,13 +1,26 @@ package cn.iocoder.yudao.module.iot; import org.springframework.boot.SpringApplication; +import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; +// TODO @haohao:建议包名:cn.iocoder.yudao.module.iot.plugin.${pluginName},例如说 http。然后子包如下: +// config:方配置类,以及 HttpVertxPlugin 初始化 +// service:放 HttpVertxHandler 逻辑; @SpringBootApplication public class HttpPluginSpringbootApplication { public static void main(String[] args) { - SpringApplication.run(HttpPluginSpringbootApplication.class, args); +// SpringApplication.run(HttpPluginSpringbootApplication.class, args); + SpringApplication application = new SpringApplication(HttpPluginSpringbootApplication.class); + application.setWebApplicationType(WebApplicationType.NONE); + application.run(args); } -} \ No newline at end of file +} + +// TODO @haohao:如下是 sdk 的包:cn.iocoder.yudao.module.iot.plugin.sdk +// 1. api 包:实现 DeviceDataApi 接口,通过 resttemplate 调用 +// 2. config 包:初始化 DeviceDataApi 等等 + +// 3. 其中 resttemplate 调用的后端地址,通过每个服务的 application.yaml 进行注入。 \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java index 1931268b60..18f6b285ef 100644 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/config/TestConfiguration.java @@ -1,23 +1,59 @@ package cn.iocoder.yudao.module.iot.config; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi; -import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceEventReportReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceStatusUpdateReqDTO; import org.pf4j.DefaultPluginManager; import org.pf4j.PluginWrapper; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; // TODO 芋艿:临时实现; @Configuration public class TestConfiguration { +// @Resource +// private RestTemplate restTemplate; + + // TODO 芋艿:这里,后续看看怎么创建好点 @Bean - public DeviceDataApi deviceDataApi() { + public RestTemplate restTemplate() { + return new RestTemplateBuilder().build(); + } + + @Bean + public DeviceDataApi deviceDataApi(RestTemplate restTemplate) { return new DeviceDataApi() { @Override - public void saveDeviceData(DeviceDataCreateReqDTO createDTO) { - System.out.println("saveDeviceData"); + public CommonResult updateDeviceStatus(IotDeviceStatusUpdateReqDTO updateReqDTO) { + // TODO haohao:待实现 + return null; + } + + @Override + public CommonResult reportDeviceEventData(IotDeviceEventReportReqDTO reportReqDTO) { + // TODO haohao:待实现 + return null; + } + + @Override + public CommonResult reportDevicePropertyData(IotDevicePropertyReportReqDTO reportReqDTO) { + // TODO haohao:待完整实现 + String url = "http://127.0.0.1:48080/rpc-api/iot/device-data/report-property"; + try { + restTemplate.postForObject(url, reportReqDTO, CommonResult.class); + return success(true); + } catch (Exception e) { + e.printStackTrace(); + return CommonResult.error(400, "error"); + } } }; diff --git a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/service/HttpVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/service/HttpVertxHandler.java index 8542cfefb1..b92b0869b5 100644 --- a/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/service/HttpVertxHandler.java +++ b/yudao-module-iot/yudao-module-iot-plugin/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/service/HttpVertxHandler.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.service; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.module.iot.api.device.DeviceDataApi; -import cn.iocoder.yudao.module.iot.api.device.dto.DeviceDataCreateReqDTO; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; import io.vertx.core.Handler; import io.vertx.ext.web.RequestBody; import io.vertx.ext.web.RoutingContext; @@ -46,12 +46,12 @@ public class HttpVertxHandler implements Handler { try { // 调用主程序的接口保存数据 - DeviceDataCreateReqDTO createDTO = DeviceDataCreateReqDTO.builder() + IotDevicePropertyReportReqDTO createDTO = IotDevicePropertyReportReqDTO.builder() .productKey(productKey) .deviceName(deviceName) - .message(jsonData.toString()) + .params(jsonData) // TODO 芋艿:这块要优化 .build(); - deviceDataApi.saveDeviceData(createDTO); + deviceDataApi.reportDevicePropertyData(createDTO); // 构造成功响应内容 JSONObject successRes = createResponseJson(