From 5fbfe49305425ced4fc318daa9f37b6bcfa67507 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 28 Jan 2025 04:56:03 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E3=80=91Bpm=EF=BC=9A=E8=AE=BE=E5=A4=87=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E4=B8=8A=E6=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/api/device/IotDeviceUpstreamApi.java | 4 +- .../module/iot/enums/ErrorCodeConstants.java | 1 - .../device/IotDeviceMessageTypeEnum.java | 12 ++++- .../api/device/IoTDeviceUpstreamApiImpl.java | 8 +-- .../admin/device/IotDeviceController.java | 8 +++ .../admin/device/IotDeviceDataController.java | 16 ++---- .../IotDeviceSimulationReportReqVO.java | 30 +++++++++++ .../IotDeviceDataSimulatorSaveReqVO.java | 44 ---------------- .../plugin/UnifiedConfiguration.java | 6 ++- .../iot/service/device/IotDeviceService.java | 14 +++--- .../service/device/IotDeviceServiceImpl.java | 37 ++++++++++++++ .../device/data/IotDevicePropertyService.java | 8 --- .../data/IotDevicePropertyServiceImpl.java | 32 ------------ .../upstream/IotDeviceUpstreamService.java | 4 +- .../IotDeviceUpstreamServiceImpl.java | 4 +- .../common/api/DeviceDataApiClient.java | 4 +- .../plugin/http/service/HttpVertxHandler.java | 2 +- .../src/main/resources/application-local.yaml | 50 ++++++++++++------- 18 files changed, 147 insertions(+), 137 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSimulationReportReqVO.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataSimulatorSaveReqVO.java diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/IotDeviceUpstreamApi.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/IotDeviceUpstreamApi.java index 996ff1f5a3..a7c28b8cbe 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/IotDeviceUpstreamApi.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/IotDeviceUpstreamApi.java @@ -35,7 +35,7 @@ public interface IotDeviceUpstreamApi { * @param reportReqDTO 上报设备属性数据 DTO */ @PostMapping(PREFIX + "/report-property") - CommonResult reportDevicePropertyData(@Valid @RequestBody IotDevicePropertyReportReqDTO reportReqDTO); + CommonResult reportDeviceProperty(@Valid @RequestBody IotDevicePropertyReportReqDTO reportReqDTO); /** * 上报设备事件数据 @@ -43,6 +43,6 @@ public interface IotDeviceUpstreamApi { * @param reportReqDTO 设备事件 */ @PostMapping(PREFIX + "/report-event") - CommonResult reportDeviceEventData(@Valid @RequestBody IotDeviceEventReportReqDTO reportReqDTO); + CommonResult reportDeviceEvent(@Valid @RequestBody IotDeviceEventReportReqDTO 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/enums/ErrorCodeConstants.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java index 305aa6c7fd..4539f12591 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java @@ -30,7 +30,6 @@ public interface ErrorCodeConstants { ErrorCode DEVICE_GATEWAY_NOT_EXISTS = new ErrorCode(1_050_003_004, "网关设备不存在"); ErrorCode DEVICE_NOT_GATEWAY = new ErrorCode(1_050_003_005, "设备不是网关设备"); ErrorCode DEVICE_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_050_003_006, "导入设备数据不能为空!"); - ErrorCode DEVICE_DATA_CONTENT_JSON_PARSE_ERROR = new ErrorCode(1_050_003_007, "导入设备数据格式错误!"); // ========== 产品分类 1-050-004-000 ========== ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_004_000, "产品分类不存在"); diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageTypeEnum.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageTypeEnum.java index b3f00e8600..20140ead2e 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageTypeEnum.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageTypeEnum.java @@ -1,22 +1,32 @@ package cn.iocoder.yudao.module.iot.enums.device; +import cn.iocoder.yudao.framework.common.core.ArrayValuable; import lombok.Getter; import lombok.RequiredArgsConstructor; +import java.util.Arrays; + /** * IoT 设备消息类型枚举 */ @Getter @RequiredArgsConstructor -public enum IotDeviceMessageTypeEnum { +public enum IotDeviceMessageTypeEnum implements ArrayValuable { STATE("state"), // 设备状态 PROPERTY("property"), // 设备属性 EVENT("event"); // 设备事件 + public static final String[] ARRAYS = Arrays.stream(values()).map(IotDeviceMessageTypeEnum::getType).toArray(String[]::new); + /** * 属性 */ private final String type; + @Override + public String[] array() { + return ARRAYS; + } + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/IoTDeviceUpstreamApiImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/IoTDeviceUpstreamApiImpl.java index 0e6df14804..3ee3ec6a4f 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/IoTDeviceUpstreamApiImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/IoTDeviceUpstreamApiImpl.java @@ -29,14 +29,14 @@ public class IoTDeviceUpstreamApiImpl implements IotDeviceUpstreamApi { } @Override - public CommonResult reportDevicePropertyData(IotDevicePropertyReportReqDTO reportReqDTO) { - deviceUpstreamService.reportDevicePropertyData(reportReqDTO); + public CommonResult reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) { + deviceUpstreamService.reportDeviceProperty(reportReqDTO); return success(true); } @Override - public CommonResult reportDeviceEventData(IotDeviceEventReportReqDTO reportReqDTO) { - deviceUpstreamService.reportDeviceEventData(reportReqDTO); + public CommonResult reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) { + deviceUpstreamService.reportDeviceEvent(reportReqDTO); return success(true); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java index e0c214bc19..5080881acf 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java @@ -159,4 +159,12 @@ public class IotDeviceController { ExcelUtils.write(response, "设备导入模板.xls", "数据", IotDeviceImportExcelVO.class, list); } + @PostMapping("/simulation-report") + @Operation(summary = "模拟设备上报") + @PreAuthorize("@ss.hasPermission('iot:device:simulation-report')") + public CommonResult simulationReportDevice(@Valid @RequestBody IotDeviceSimulationReportReqVO simulatorReqVO) { + deviceService.simulationReportDevice(simulatorReqVO); + 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/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index 8012ec2ec4..6c2ea7a2d2 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.*; -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService; import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService; import io.swagger.v3.oas.annotations.Operation; @@ -13,7 +13,9 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.validation.Valid; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Map; @@ -47,16 +49,6 @@ public class IotDeviceDataController { return success(BeanUtils.toBean(list, IotTimeDataRespVO.class)); } - // TODO:功能权限 - @PostMapping("/simulator") - @Operation(summary = "模拟设备") - public CommonResult simulatorDevice(@Valid @RequestBody IotDeviceDataSimulatorSaveReqVO simulatorReqVO) { - //TODO:先使用 IotDeviceDataSimulatorSaveReqVO 另外content里数据类型的效验前端也没做,后端应该要要效验一下,这块后续看看怎么安排 - // TODO @super:应该 deviceDataService 里面有个 simulatorDevice,然后里面去 insert 日志! - deviceDataService.simulatorSend(simulatorReqVO); - return success(true); - } - // TODO:功能权限 @GetMapping("/log/page") @Operation(summary = "获得设备日志分页") diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSimulationReportReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSimulationReportReqVO.java new file mode 100644 index 0000000000..aea4f9077d --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSimulationReportReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - IoT 模拟设备上报 Request VO") // 属性上报、事件上报、状态变更等 +@Data +public class IotDeviceSimulationReportReqVO { + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177") + @NotNull(message = "设备编号不能为空") + private Long id; + + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property") + @NotEmpty(message = "消息类型不能为空") + @InEnum(IotDeviceMessageTypeEnum.class) + private String type; + + @Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "report") + @NotEmpty(message = "标识符不能为空") + private String identifier; // 参见 IotDeviceMessageIdentifierEnum 枚举类 + + @Schema(description = "请求参数", requiredMode = Schema.RequiredMode.REQUIRED) + private Object data; // 例如说:属性上报的 properties、事件上报的 params + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataSimulatorSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataSimulatorSaveReqVO.java deleted file mode 100644 index efa608e572..0000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataSimulatorSaveReqVO.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; - -// TODO super: SaveReqVO => ReqVO -@Schema(description = "管理后台 - IoT 模拟设备数据 Request VO") -@Data -public class IotDeviceDataSimulatorSaveReqVO { - - // TODO @super:感觉后端随机更合适? - @Schema(description = "消息 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "msg123") - private String id; - - // TODO @super:不用传递 productKey,因为 deviceKey 可以推导出来 - // TODO 讨论: 日志记录的时候要记录一下productKey,目前是前端已经有productKey了,所以前端传入,如果不传入的话,后端要根据deviceKey查询productKey,感觉直传是不是效率高一些 - @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123") - @NotEmpty(message = "产品标识不能为空") - private String productKey; - - @Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123") - @NotEmpty(message = "设备标识不能为空") - private String deviceKey; - - // TODO @super:type、subType,是不是不用传递,因为模拟只有属性??? - // TODO 讨论: 不只模拟属性 - @Schema(description = "消息/日志类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property") - @NotEmpty(message = "消息类型不能为空") - private String type; - - @Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature") - @NotEmpty(message = "标识符不能为空") - private String subType; - - @Schema(description = "数据内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "{\"value\": 25.6}") - @NotEmpty(message = "数据内容不能为空") - private String content; - - // TODO @芋艿:需要讨论下,reportTime 到底以那个为准! - @Schema(description = "上报时间", requiredMode = Schema.RequiredMode.REQUIRED) - private Long reportTime; - -} 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 e27d9b5fb3..150051ce58 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,6 +7,8 @@ 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 @@ -19,8 +21,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/IotDeviceService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java index 3efc4054fe..b5d690e513 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java @@ -1,13 +1,8 @@ package cn.iocoder.yudao.module.iot.service.device; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceUpdateGroupReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceImportRespVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceImportExcelVO; import jakarta.validation.Valid; import javax.annotation.Nullable; @@ -133,4 +128,11 @@ public interface IotDeviceService { */ IotDeviceImportRespVO importDevice(List importDevices, boolean updateSupport); + /** + * 模拟设备上报 + * + * @param reportReqVO 上报信息 + */ + void simulationReportDevice(IotDeviceSimulationReportReqVO reportReqVO); + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index 786e8e0ef0..8799080712 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java @@ -11,14 +11,17 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; +import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper; import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; +import cn.iocoder.yudao.module.iot.service.device.upstream.IotDeviceUpstreamService; import cn.iocoder.yudao.module.iot.service.product.IotProductService; import jakarta.annotation.Resource; import jakarta.validation.ConstraintViolationException; @@ -56,6 +59,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { @Resource @Lazy // 延迟加载,解决循环依赖 private IotDeviceGroupService deviceGroupService; + @Resource + @Lazy // 延迟加载,解决循环依赖 + private IotDeviceUpstreamService deviceUpstreamService; @Override public Long createDevice(IotDeviceSaveReqVO createReqVO) { @@ -84,6 +90,7 @@ public class IotDeviceServiceImpl implements IotDeviceService { // 2.1 转换 VO 为 DO // TODO @芋艿:state 相关的参数。另外,到底叫 state,还是 status 好! + // TODO @芋艿:各种 mqtt 是不是可以简化! IotDeviceDO device = BeanUtils.toBean(createReqVO, IotDeviceDO.class, o -> { o.setProductKey(product.getProductKey()).setDeviceType(product.getDeviceType()); // 生成并设置必要的字段 @@ -392,6 +399,36 @@ public class IotDeviceServiceImpl implements IotDeviceService { return respVO; } + @Override + @SuppressWarnings("unchecked") + public void simulationReportDevice(IotDeviceSimulationReportReqVO reportReqVO) { + // 1. 校验存在 + IotDeviceDO device = validateDeviceExists(reportReqVO.getId()); + + // 2.1 情况一:属性上报 + String requestId = IdUtil.fastSimpleUUID(); + if (Objects.equals(reportReqVO.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType())) { + deviceUpstreamService.reportDeviceProperty(IotDevicePropertyReportReqDTO.builder() + .requestId(requestId).reportTime(LocalDateTime.now()) + .productKey(device.getProductKey()).deviceName(device.getDeviceName()) + .properties((Map) reportReqVO.getData()).build()); + return; + } + // 2.2 情况二:事件上报 + if (Objects.equals(reportReqVO.getType(), IotDeviceMessageTypeEnum.EVENT.getType())) { + // TODO 芋艿:待实现 + return; + } + // 2.3 情况三:状态变更 + if (Objects.equals(reportReqVO.getType(), IotDeviceMessageTypeEnum.STATE.getType())) { + // TODO 芋艿:待实现 + updateDeviceStatus(new IotDeviceStatusUpdateReqVO().setId(device.getId()) + .setStatus((Integer) reportReqVO.getData())); + return; + } + throw new IllegalArgumentException("未知的类型:" + reportReqVO.getType()); + } + private void deleteDeviceCache(IotDeviceDO device) { // 保证在 @CacheEvict 之前,忽略租户 TenantUtils.executeIgnore(() -> getSelf().deleteDeviceCache0(device)); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyService.java index b5fce2bc17..fbbc292cfc 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyService.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.iot.service.device.data; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; import jakarta.validation.Valid; @@ -31,13 +30,6 @@ public interface IotDevicePropertyService { */ void saveDeviceProperty(IotDeviceMessage message); - /** - * 模拟设备 - * - * @param simulatorReqVO 设备数据 - */ - void simulatorSend(IotDeviceDataSimulatorSaveReqVO simulatorReqVO); - /** * 获得设备属性最新数据 * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyServiceImpl.java index 3f4c90b24f..0aa438b136 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyServiceImpl.java @@ -4,12 +4,9 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataSimulatorSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; @@ -34,9 +31,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_DATA_CONTENT_JSON_PARSE_ERROR; /** * IoT 设备【属性】数据 Service 实现类 @@ -155,33 +150,6 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { entry -> IotDevicePropertyDO.builder().value(entry.getValue()).updateTime(message.getReportTime()).build())); } - //TODO @芋艿:copy 了 saveDeviceData 的逻辑,后续看看这块怎么优化 - @Override - public void simulatorSend(IotDeviceDataSimulatorSaveReqVO simulatorReqVO) { - // 1. 根据设备 key ,获得设备信息 - IotDeviceDO device = deviceService.getDeviceByDeviceKey(simulatorReqVO.getDeviceKey()); - - // 2. 解析 content 为 JSON 对象 - JSONObject contentJson; - try { - contentJson = JSONUtil.parseObj(simulatorReqVO.getContent()); - } catch (Exception e) { - throw exception(DEVICE_DATA_CONTENT_JSON_PARSE_ERROR); - } - - // TODO @芋艿:后续优化 - // 3. 构建物模型消息 -// IotDeviceMessage thingModelMessage = IotDeviceMessage.builder() -// .params(contentJson) // 将 content 作为 params -// .time(simulatorReqVO.getReportTime()) // 使用上报时间 -// .productKey(simulatorReqVO.getProductKey()) -// .deviceName(device.getDeviceName()) -// .build(); - - // 4. 发送模拟消息 -// simulateSendProducer.sendDeviceMessage(thingModelMessage); - } - @Override public List getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { // List list = new ArrayList<>(); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/upstream/IotDeviceUpstreamService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/upstream/IotDeviceUpstreamService.java index 16d387d7b0..12fd8a9491 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/upstream/IotDeviceUpstreamService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/upstream/IotDeviceUpstreamService.java @@ -25,13 +25,13 @@ public interface IotDeviceUpstreamService { * * @param reportReqDTO 上报设备属性数据 DTO */ - void reportDevicePropertyData(IotDevicePropertyReportReqDTO reportReqDTO); + void reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO); /** * 上报设备事件数据 * * @param reportReqDTO 设备事件 */ - void reportDeviceEventData(IotDeviceEventReportReqDTO reportReqDTO); + void reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/upstream/IotDeviceUpstreamServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/upstream/IotDeviceUpstreamServiceImpl.java index 4a456406ca..adfb1f83fd 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/upstream/IotDeviceUpstreamServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/upstream/IotDeviceUpstreamServiceImpl.java @@ -43,7 +43,7 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { } @Override - public void reportDevicePropertyData(IotDevicePropertyReportReqDTO reportReqDTO) { + public void reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) { // 1.1 获得设备 log.info("[reportDevicePropertyData][上报设备属性数据: {}]", reportReqDTO); IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceNameFromCache( @@ -65,7 +65,7 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { } @Override - public void reportDeviceEventData(IotDeviceEventReportReqDTO reportReqDTO) { + public void reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) { log.info("[reportDeviceEventData][上报设备事件数据: {}]", reportReqDTO); // TODO 芋艿:待实现 diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/api/DeviceDataApiClient.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/api/DeviceDataApiClient.java index a10e9ec3d5..ee68bf0342 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/api/DeviceDataApiClient.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/api/DeviceDataApiClient.java @@ -35,13 +35,13 @@ public class DeviceDataApiClient implements IotDeviceUpstreamApi { } @Override - public CommonResult reportDeviceEventData(IotDeviceEventReportReqDTO reportReqDTO) { + public CommonResult reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) { String url = deviceDataUrl + URL_PREFIX + "/report-event"; return doPost(url, reportReqDTO, "reportDeviceEventData"); } @Override - public CommonResult reportDevicePropertyData(IotDevicePropertyReportReqDTO reportReqDTO) { + public CommonResult reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) { String url = deviceDataUrl + URL_PREFIX + "/report-property"; return doPost(url, reportReqDTO, "reportDevicePropertyData"); } diff --git a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/service/HttpVertxHandler.java b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/service/HttpVertxHandler.java index ec4431d2d1..4ac85c2208 100644 --- a/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/service/HttpVertxHandler.java +++ b/yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-http/src/main/java/cn/iocoder/yudao/module/iot/plugin/http/service/HttpVertxHandler.java @@ -49,7 +49,7 @@ public class HttpVertxHandler implements Handler { .properties((Map) requestBody.asJsonObject().getMap().get("properties")) .build(); - deviceDataApi.reportDevicePropertyData(reportReqDTO); + deviceDataApi.reportDeviceProperty(reportReqDTO); ctx.response() .setStatusCode(200) diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index d3fb42b061..bbb94772c7 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -45,16 +45,16 @@ spring: primary: master datasource: master: - url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例 - # url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例 + url: jdbc:mysql://chaojiniu.top:23306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai # MySQL Connector/J 5.X 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true;useUnicode=true;characterEncoding=utf-8 # SQLServer 连接的示例 # url: jdbc:dm://127.0.0.1:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 # url: jdbc:kingbase8://127.0.0.1:54321/test # 人大金仓 KingbaseES 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/postgres # OpenGauss 连接的示例 - username: root - password: 123456 + username: ruoyi-vue-pro + password: ruoyi-@h2ju02hebp # username: sa # SQL Server 连接的示例 # password: Yudao@2024 # SQL Server 连接的示例 # username: SYSDBA # DM 连接的示例 @@ -63,17 +63,25 @@ spring: # password: Yudao@2024 # OpenGauss 连接的示例 slave: # 模拟从库,可根据自己需要修改 lazy: true # 开启懒加载,保证启动速度 - url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true + url: jdbc:mysql://chaojiniu.top:23306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true + username: ruoyi-vue-pro + password: ruoyi-@h2ju02hebp + tdengine: # IOT 数据库 + # lazy: true # 开启懒加载,保证启动速度 + url: jdbc:TAOS-RS://chaojiniu.top:6041/ruoyi_vue_pro + driver-class-name: com.taosdata.jdbc.rs.RestfulDriver username: root - password: 123456 + password: taosdata + druid: + validation-query: SELECT SERVER_STATUS() # TDengine 数据源的有效性检查 SQL # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 data: redis: host: 127.0.0.1 # 地址 port: 6379 # 端口 - database: 0 # 数据库索引 -# password: dev # 密码,建议生产环境开启 + database: 1 # 数据库索引 + # password: 123456 # 密码,建议生产环境开启 --- #################### 定时任务相关配置 #################### @@ -175,20 +183,22 @@ logging: cn.iocoder.yudao.module.crm.dal.mysql: debug cn.iocoder.yudao.module.erp.dal.mysql: debug cn.iocoder.yudao.module.iot.dal.mysql: debug + cn.iocoder.yudao.module.iot.dal.tdengine: DEBUG cn.iocoder.yudao.module.ai.dal.mysql: debug org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 + com.taosdata: DEBUG # TDengine 的日志级别 debug: false --- #################### 微信公众号、小程序相关配置 #################### wx: mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 - # app-id: wx041349c6f39b268b # 测试号(牛希尧提供的) - # secret: 5abee519483bc9f8cb37ce280e814bd0 +# app-id: wx041349c6f39b268b # 测试号(牛希尧提供的) +# secret: 5abee519483bc9f8cb37ce280e814bd0 app-id: wx5b23ba7a5589ecbb # 测试号(自己的) secret: 2a7b3b20c537e52e74afd395eb85f61f - # app-id: wxa69ab825b163be19 # 测试号(Kongdy 提供的) - # secret: bd4f9fab889591b62aeac0d7b8d8b4a0 +# app-id: wxa69ab825b163be19 # 测试号(Kongdy 提供的) +# secret: bd4f9fab889591b62aeac0d7b8d8b4a0 # 存储配置,解决 AccessToken 的跨节点的共享 config-storage: type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 @@ -197,10 +207,10 @@ wx: miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 # appid: wx62056c0d5e8db250 # 测试号(牛希尧提供的) # secret: 333ae72f41552af1e998fe1f54e1584a - # appid: wx63c280fe3248a3e7 # wenhualian的接口测试号 - # secret: 6f270509224a7ae1296bbf1c8cb97aed - # appid: wxc4598c446f8a9cb3 # 测试号(Kongdy 提供的) - # secret: 4a1a04e07f6a4a0751b39c3064a92c8b +# appid: wx63c280fe3248a3e7 # wenhualian的接口测试号 +# secret: 6f270509224a7ae1296bbf1c8cb97aed +# appid: wxc4598c446f8a9cb3 # 测试号(Kongdy 提供的) +# secret: 4a1a04e07f6a4a0751b39c3064a92c8b appid: wx66186af0759f47c9 # 测试号(puhui 提供的) secret: 3218bcbd112cbc614c7264ceb20144ac config-storage: @@ -260,7 +270,7 @@ justauth: iot: emq: # 账号 - username: anhaohao + username: haohao # 密码 password: ahh@123456 # 主机地址 @@ -272,4 +282,8 @@ iot: # 保持连接 keepalive: 60 # 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息) - clearSession: true \ No newline at end of file + clearSession: true + +pf4j: +# pluginsDir: /tmp/ + pluginsDir: ../plugins \ No newline at end of file