Commit f5c2ee2ae5aa1840d130560ada903ae6b361d7b5
1 parent
e9c5464a
feat:【IoT 物联网】设备消息查询时,增加 pair 查询
Showing
16 changed files
with
214 additions
and
25 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceMessageController.http
| ... | ... | @@ -88,4 +88,14 @@ Authorization: Bearer {{token}} |
| 88 | 88 | "fileUrl": "http://example.com/firmware.bin", |
| 89 | 89 | "information": "{\"desc\":\"升级到最新版本\"}" |
| 90 | 90 | } |
| 91 | -} | |
| 92 | 91 | \ No newline at end of file |
| 92 | +} | |
| 93 | + | |
| 94 | +### 查询设备消息对分页 - 基础查询(设备编号25) | |
| 95 | +GET {{baseUrl}}/iot/device/message/pair-page?deviceId=25&pageNo=1&pageSize=10 | |
| 96 | +Authorization: Bearer {{token}} | |
| 97 | +tenant-id: {{adminTenantId}} | |
| 98 | + | |
| 99 | +### 查询设备消息对分页 - 按标识符过滤(identifier=eat) | |
| 100 | +GET {{baseUrl}}/iot/device/message/pair-page?deviceId=25&identifier=eat&pageNo=1&pageSize=10 | |
| 101 | +Authorization: Bearer {{token}} | |
| 102 | +tenant-id: {{adminTenantId}} | |
| 93 | 103 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceMessageController.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.controller.admin.device; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 3 | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 6 | -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessageRespVO; | |
| 7 | 7 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessagePageReqVO; |
| 8 | +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessageRespPairVO; | |
| 9 | +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessageRespVO; | |
| 8 | 10 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessageSendReqVO; |
| 9 | 11 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 10 | 12 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; |
| 13 | +import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceMessageMapper; | |
| 14 | +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; | |
| 11 | 15 | import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService; |
| 16 | +import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; | |
| 12 | 17 | import io.swagger.v3.oas.annotations.Operation; |
| 13 | 18 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 14 | 19 | import jakarta.annotation.Resource; |
| ... | ... | @@ -17,7 +22,12 @@ import org.springframework.security.access.prepost.PreAuthorize; |
| 17 | 22 | import org.springframework.validation.annotation.Validated; |
| 18 | 23 | import org.springframework.web.bind.annotation.*; |
| 19 | 24 | |
| 25 | +import java.util.List; | |
| 26 | +import java.util.Map; | |
| 27 | + | |
| 20 | 28 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 29 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 30 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | |
| 21 | 31 | |
| 22 | 32 | @Tag(name = "管理后台 - IoT 设备消息") |
| 23 | 33 | @RestController |
| ... | ... | @@ -27,19 +37,54 @@ public class IotDeviceMessageController { |
| 27 | 37 | |
| 28 | 38 | @Resource |
| 29 | 39 | private IotDeviceMessageService deviceMessageService; |
| 40 | + @Resource | |
| 41 | + private IotDeviceService deviceService; | |
| 42 | + @Resource | |
| 43 | + private IotThingModelService thingModelService; | |
| 44 | + @Resource | |
| 45 | + private IotDeviceMessageMapper deviceMessageMapper; | |
| 30 | 46 | |
| 31 | 47 | @GetMapping("/page") |
| 32 | 48 | @Operation(summary = "获得设备消息分页") |
| 33 | 49 | @PreAuthorize("@ss.hasPermission('iot:device:message-query')") |
| 34 | - public CommonResult<PageResult<IotDeviceMessageRespVO>> getDeviceLogPage(@Valid IotDeviceMessagePageReqVO pageReqVO) { | |
| 50 | + public CommonResult<PageResult<IotDeviceMessageRespVO>> getDeviceMessagePage( | |
| 51 | + @Valid IotDeviceMessagePageReqVO pageReqVO) { | |
| 35 | 52 | PageResult<IotDeviceMessageDO> pageResult = deviceMessageService.getDeviceMessagePage(pageReqVO); |
| 36 | 53 | return success(BeanUtils.toBean(pageResult, IotDeviceMessageRespVO.class)); |
| 37 | 54 | } |
| 38 | 55 | |
| 56 | + @GetMapping("/pair-page") | |
| 57 | + @Operation(summary = "获得设备消息对分页") | |
| 58 | + @PreAuthorize("@ss.hasPermission('iot:device:message-query')") | |
| 59 | + public CommonResult<PageResult<IotDeviceMessageRespPairVO>> getDeviceMessagePairPage( | |
| 60 | + @Valid IotDeviceMessagePageReqVO pageReqVO) { | |
| 61 | + // 1.1 先按照条件,查询 request 的消息(非 reply) | |
| 62 | + pageReqVO.setReply(false); | |
| 63 | + PageResult<IotDeviceMessageDO> requestMessagePageResult = deviceMessageService.getDeviceMessagePage(pageReqVO); | |
| 64 | + if (CollUtil.isEmpty(requestMessagePageResult.getList())) { | |
| 65 | + return success(PageResult.empty()); | |
| 66 | + } | |
| 67 | + // 1.2 接着按照 requestIds,批量查询 reply 消息 | |
| 68 | + List<String> requestIds = convertList(requestMessagePageResult.getList(), IotDeviceMessageDO::getRequestId); | |
| 69 | + List<IotDeviceMessageDO> replyMessageList = deviceMessageService.getDeviceMessageListByRequestIdsAndReply( | |
| 70 | + pageReqVO.getDeviceId(), requestIds, true); | |
| 71 | + Map<String, IotDeviceMessageDO> replyMessages = convertMap(replyMessageList, IotDeviceMessageDO::getRequestId); | |
| 72 | + | |
| 73 | + // 2. 组装结果 | |
| 74 | + List<IotDeviceMessageRespPairVO> pairMessages = convertList(requestMessagePageResult.getList(), | |
| 75 | + requestMessage -> { | |
| 76 | + IotDeviceMessageDO replyMessage = replyMessages.get(requestMessage.getRequestId()); | |
| 77 | + return new IotDeviceMessageRespPairVO() | |
| 78 | + .setRequest(BeanUtils.toBean(requestMessage, IotDeviceMessageRespVO.class)) | |
| 79 | + .setReply(BeanUtils.toBean(replyMessage, IotDeviceMessageRespVO.class)); | |
| 80 | + }); | |
| 81 | + return success(new PageResult<>(pairMessages, requestMessagePageResult.getTotal())); | |
| 82 | + } | |
| 83 | + | |
| 39 | 84 | @PostMapping("/send") |
| 40 | 85 | @Operation(summary = "发送消息", description = "可用于设备模拟") |
| 41 | 86 | @PreAuthorize("@ss.hasPermission('iot:device:message-end')") |
| 42 | - public CommonResult<Boolean> upstreamDevice(@Valid @RequestBody IotDeviceMessageSendReqVO sendReqVO) { | |
| 87 | + public CommonResult<Boolean> sendDeviceMessage(@Valid @RequestBody IotDeviceMessageSendReqVO sendReqVO) { | |
| 43 | 88 | deviceMessageService.sendDeviceMessage(BeanUtils.toBean(sendReqVO, IotDeviceMessage.class)); |
| 44 | 89 | return success(true); |
| 45 | 90 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/message/IotDeviceMessagePageReqVO.java
| ... | ... | @@ -5,7 +5,13 @@ import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 5 | 5 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; |
| 6 | 6 | import io.swagger.v3.oas.annotations.media.Schema; |
| 7 | 7 | import jakarta.validation.constraints.NotNull; |
| 8 | +import jakarta.validation.constraints.Size; | |
| 8 | 9 | import lombok.Data; |
| 10 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 11 | + | |
| 12 | +import java.time.LocalDateTime; | |
| 13 | + | |
| 14 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 9 | 15 | |
| 10 | 16 | @Schema(description = "管理后台 - IoT 设备消息分页查询 Request VO") |
| 11 | 17 | @Data |
| ... | ... | @@ -22,4 +28,15 @@ public class IotDeviceMessagePageReqVO extends PageParam { |
| 22 | 28 | @Schema(description = "是否上行", example = "true") |
| 23 | 29 | private Boolean upstream; |
| 24 | 30 | |
| 31 | + @Schema(description = "是否回复", example = "true") | |
| 32 | + private Boolean reply; | |
| 33 | + | |
| 34 | + @Schema(description = "标识符", example = "temperature") | |
| 35 | + private String identifier; | |
| 36 | + | |
| 37 | + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.NOT_REQUIRED) | |
| 38 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 39 | + @Size(min = 2, max = 2, message = "请选择时间范围") | |
| 40 | + private LocalDateTime[] times; | |
| 41 | + | |
| 25 | 42 | } |
| 26 | 43 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/message/IotDeviceMessageRespPairVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.message; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +@Schema(description = "管理后台 - IoT 设备消息对 Response VO") | |
| 7 | +@Data | |
| 8 | +public class IotDeviceMessageRespPairVO { | |
| 9 | + | |
| 10 | + @Schema(description = "请求消息", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 11 | + private IotDeviceMessageRespVO request; | |
| 12 | + | |
| 13 | + @Schema(description = "响应消息") | |
| 14 | + private IotDeviceMessageRespVO reply; // 通过 requestId 配对 | |
| 15 | + | |
| 16 | +} | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/message/IotDeviceMessageRespVO.java
| ... | ... | @@ -30,6 +30,9 @@ public class IotDeviceMessageRespVO { |
| 30 | 30 | @Schema(description = "是否回复消息", example = "false", examples = "true") |
| 31 | 31 | private Boolean reply; |
| 32 | 32 | |
| 33 | + @Schema(description = "标识符", example = "temperature") | |
| 34 | + private String identifier; | |
| 35 | + | |
| 33 | 36 | // ========== codec(编解码)字段 ========== |
| 34 | 37 | |
| 35 | 38 | @Schema(description = "请求编号", example = "req_123") | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceMessageDO.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.device; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; |
| 4 | 4 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 5 | +import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; | |
| 5 | 6 | import lombok.AllArgsConstructor; |
| 6 | 7 | import lombok.Builder; |
| 7 | 8 | import lombok.Data; |
| ... | ... | @@ -63,6 +64,13 @@ public class IotDeviceMessageDO { |
| 63 | 64 | * 计算并存储的目的:方便计算多少条请求、多少条回复 |
| 64 | 65 | */ |
| 65 | 66 | private Boolean reply; |
| 67 | + /** | |
| 68 | + * 标识符 | |
| 69 | + * | |
| 70 | + * 例如说:{@link IotThingModelDO#getIdentifier()} | |
| 71 | + * 目前,只有事件上报、服务调用才有!!! | |
| 72 | + */ | |
| 73 | + private String identifier; | |
| 66 | 74 | |
| 67 | 75 | // ========== codec(编解码)字段 ========== |
| 68 | 76 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thingmodel/IotThingModelMapper.java
| ... | ... | @@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelP |
| 8 | 8 | import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; |
| 9 | 9 | import org.apache.ibatis.annotations.Mapper; |
| 10 | 10 | |
| 11 | -import java.time.LocalDateTime; | |
| 11 | +import java.util.Collection; | |
| 12 | 12 | import java.util.List; |
| 13 | 13 | |
| 14 | 14 | /** |
| ... | ... | @@ -50,6 +50,12 @@ public interface IotThingModelMapper extends BaseMapperX<IotThingModelDO> { |
| 50 | 50 | return selectList(IotThingModelDO::getProductId, productId); |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | + default List<IotThingModelDO> selectListByProductIdAndIdentifiers(Long productId, Collection<String> identifiers) { | |
| 54 | + return selectList(new LambdaQueryWrapperX<IotThingModelDO>() | |
| 55 | + .eq(IotThingModelDO::getProductId, productId) | |
| 56 | + .in(IotThingModelDO::getIdentifier, identifiers)); | |
| 57 | + } | |
| 58 | + | |
| 53 | 59 | default List<IotThingModelDO> selectListByProductIdAndType(Long productId, Integer type) { |
| 54 | 60 | return selectList(IotThingModelDO::getProductId, productId, |
| 55 | 61 | IotThingModelDO::getType, type); |
| ... | ... | @@ -69,16 +75,4 @@ public interface IotThingModelMapper extends BaseMapperX<IotThingModelDO> { |
| 69 | 75 | IotThingModelDO::getName, name); |
| 70 | 76 | } |
| 71 | 77 | |
| 72 | - // TODO @super:用不到,删除下; | |
| 73 | - /** | |
| 74 | - * 统计物模型数量 | |
| 75 | - * | |
| 76 | - * @param createTime 创建时间,如果为空,则统计所有物模型数量 | |
| 77 | - * @return 物模型数量 | |
| 78 | - */ | |
| 79 | - default Long selectCountByCreateTime(LocalDateTime createTime) { | |
| 80 | - return selectCount(new LambdaQueryWrapperX<IotThingModelDO>() | |
| 81 | - .geIfPresent(IotThingModelDO::getCreateTime, createTime)); | |
| 82 | - } | |
| 83 | - | |
| 84 | 78 | } |
| 85 | 79 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceMessageMapper.java
| ... | ... | @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; |
| 8 | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 9 | import org.apache.ibatis.annotations.Param; |
| 10 | 10 | |
| 11 | +import java.util.Collection; | |
| 11 | 12 | import java.util.List; |
| 12 | 13 | import java.util.Map; |
| 13 | 14 | |
| ... | ... | @@ -58,6 +59,18 @@ public interface IotDeviceMessageMapper { |
| 58 | 59 | Long selectCountByCreateTime(@Param("createTime") Long createTime); |
| 59 | 60 | |
| 60 | 61 | /** |
| 62 | + * 按照 requestIds 批量查询消息 | |
| 63 | + * | |
| 64 | + * @param deviceId 设备编号 | |
| 65 | + * @param requestIds 请求编号集合 | |
| 66 | + * @param reply 是否回复消息 | |
| 67 | + * @return 消息列表 | |
| 68 | + */ | |
| 69 | + List<IotDeviceMessageDO> selectListByRequestIdsAndReply(@Param("deviceId") Long deviceId, | |
| 70 | + @Param("requestIds") Collection<String> requestIds, | |
| 71 | + @Param("reply") Boolean reply); | |
| 72 | + | |
| 73 | + /** | |
| 61 | 74 | * 按照时间范围(小时),统计设备的消息数量 |
| 62 | 75 | */ |
| 63 | 76 | List<Map<String, Object>> selectDeviceMessageCountGroupByDate(@Param("startTime") Long startTime, | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDevicePropertyMapper.java
| ... | ... | @@ -32,7 +32,7 @@ public interface IotDevicePropertyMapper { |
| 32 | 32 | List<TDengineTableField> oldFields, |
| 33 | 33 | List<TDengineTableField> newFields) { |
| 34 | 34 | oldFields.removeIf(field -> StrUtil.equalsAny(field.getField(), |
| 35 | - TDengineTableField.FIELD_TS, "report_time")); | |
| 35 | + TDengineTableField.FIELD_TS, "report_time", "device_id")); | |
| 36 | 36 | List<TDengineTableField> addFields = newFields.stream().filter( // 新增的字段 |
| 37 | 37 | newField -> oldFields.stream().noneMatch(oldField -> oldField.getField().equals(newField.getField()))) |
| 38 | 38 | .collect(Collectors.toList()); | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageService.java
| ... | ... | @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsD |
| 7 | 7 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 8 | 8 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 9 | 9 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; |
| 10 | +import jakarta.validation.constraints.NotEmpty; | |
| 11 | +import jakarta.validation.constraints.NotNull; | |
| 10 | 12 | |
| 11 | 13 | import javax.annotation.Nullable; |
| 12 | 14 | import java.time.LocalDateTime; |
| ... | ... | @@ -64,6 +66,19 @@ public interface IotDeviceMessageService { |
| 64 | 66 | PageResult<IotDeviceMessageDO> getDeviceMessagePage(IotDeviceMessagePageReqVO pageReqVO); |
| 65 | 67 | |
| 66 | 68 | /** |
| 69 | + * 获得指定 requestId 的设备消息列表 | |
| 70 | + * | |
| 71 | + * @param deviceId 设备编号 | |
| 72 | + * @param requestIds requestId 列表 | |
| 73 | + * @param reply 是否回复 | |
| 74 | + * @return 设备消息列表 | |
| 75 | + */ | |
| 76 | + List<IotDeviceMessageDO> getDeviceMessageListByRequestIdsAndReply( | |
| 77 | + @NotNull(message = "设备编号不能为空") Long deviceId, | |
| 78 | + @NotEmpty(message = "请求编号不能为空") List<String> requestIds, | |
| 79 | + Boolean reply); | |
| 80 | + | |
| 81 | + /** | |
| 67 | 82 | * 获得设备消息数量 |
| 68 | 83 | * |
| 69 | 84 | * @param createTime 创建时间,如果为空,则统计所有消息数量 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImpl.java
| ... | ... | @@ -76,7 +76,8 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { |
| 76 | 76 | void createDeviceLogAsync(IotDeviceMessage message) { |
| 77 | 77 | IotDeviceMessageDO messageDO = BeanUtils.toBean(message, IotDeviceMessageDO.class) |
| 78 | 78 | .setUpstream(IotDeviceMessageUtils.isUpstreamMessage(message)) |
| 79 | - .setReply(IotDeviceMessageUtils.isReplyMessage(message)); | |
| 79 | + .setReply(IotDeviceMessageUtils.isReplyMessage(message)) | |
| 80 | + .setIdentifier(IotDeviceMessageUtils.getIdentifier(message)); | |
| 80 | 81 | if (message.getParams() != null) { |
| 81 | 82 | messageDO.setParams(JsonUtils.toJsonString(messageDO.getParams())); |
| 82 | 83 | } |
| ... | ... | @@ -213,6 +214,13 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { |
| 213 | 214 | } |
| 214 | 215 | |
| 215 | 216 | @Override |
| 217 | + public List<IotDeviceMessageDO> getDeviceMessageListByRequestIdsAndReply(Long deviceId, | |
| 218 | + List<String> requestIds, | |
| 219 | + Boolean reply) { | |
| 220 | + return deviceMessageMapper.selectListByRequestIdsAndReply(deviceId, requestIds, reply); | |
| 221 | + } | |
| 222 | + | |
| 223 | + @Override | |
| 216 | 224 | public Long getDeviceMessageCount(LocalDateTime createTime) { |
| 217 | 225 | return deviceMessageMapper.selectCountByCreateTime(createTime != null ? LocalDateTimeUtil.toEpochMilli(createTime) : null); |
| 218 | 226 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java
| ... | ... | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelS |
| 7 | 7 | import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; |
| 8 | 8 | import jakarta.validation.Valid; |
| 9 | 9 | |
| 10 | +import java.util.Collection; | |
| 10 | 11 | import java.util.List; |
| 11 | 12 | |
| 12 | 13 | /** |
| ... | ... | @@ -58,6 +59,15 @@ public interface IotThingModelService { |
| 58 | 59 | * 获得产品物模型列表 |
| 59 | 60 | * |
| 60 | 61 | * @param productId 产品编号 |
| 62 | + * @param identifiers 功能标识列表 | |
| 63 | + * @return 产品物模型列表 | |
| 64 | + */ | |
| 65 | + List<IotThingModelDO> getThingModelListByProductIdAndIdentifiers(Long productId, Collection<String> identifiers); | |
| 66 | + | |
| 67 | + /** | |
| 68 | + * 获得产品物模型列表 | |
| 69 | + * | |
| 70 | + * @param productId 产品编号 | |
| 61 | 71 | * @param type 物模型类型 |
| 62 | 72 | * @return 产品物模型列表 |
| 63 | 73 | */ | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java
| ... | ... | @@ -132,6 +132,11 @@ public class IotThingModelServiceImpl implements IotThingModelService { |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | 134 | @Override |
| 135 | + public List<IotThingModelDO> getThingModelListByProductIdAndIdentifiers(Long productId, Collection<String> identifiers) { | |
| 136 | + return thingModelMapper.selectListByProductIdAndIdentifiers(productId, identifiers); | |
| 137 | + } | |
| 138 | + | |
| 139 | + @Override | |
| 135 | 140 | public List<IotThingModelDO> getThingModelListByProductIdAndType(Long productId, Integer type) { |
| 136 | 141 | return thingModelMapper.selectListByProductIdAndType(productId, type); |
| 137 | 142 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDeviceMessageMapper.xml
| ... | ... | @@ -13,6 +13,7 @@ |
| 13 | 13 | server_id NCHAR(50), |
| 14 | 14 | upstream BOOL, |
| 15 | 15 | reply BOOL, |
| 16 | + identifier NCHAR(100), | |
| 16 | 17 | request_id NCHAR(50), |
| 17 | 18 | method NCHAR(100), |
| 18 | 19 | params NCHAR(2048), |
| ... | ... | @@ -31,22 +32,22 @@ |
| 31 | 32 | <insert id="insert"> |
| 32 | 33 | INSERT INTO device_message_${deviceId} ( |
| 33 | 34 | ts, id, report_time, tenant_id, server_id, |
| 34 | - upstream, reply, request_id, method, params, | |
| 35 | - data, code, msg | |
| 35 | + upstream, reply, identifier, request_id, method, | |
| 36 | + params, data, code, msg | |
| 36 | 37 | ) |
| 37 | 38 | USING device_message |
| 38 | 39 | TAGS (#{deviceId}) |
| 39 | 40 | VALUES ( |
| 40 | 41 | NOW, #{id}, #{reportTime}, #{tenantId}, #{serverId}, |
| 41 | - #{upstream}, #{reply}, #{requestId}, #{method}, #{params}, | |
| 42 | - #{data}, #{code}, #{msg} | |
| 42 | + #{upstream}, #{reply}, #{identifier}, #{requestId}, #{method}, | |
| 43 | + #{params}, #{data}, #{code}, #{msg} | |
| 43 | 44 | ) |
| 44 | 45 | </insert> |
| 45 | 46 | |
| 46 | 47 | <select id="selectPage" resultType="cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO"> |
| 47 | 48 | SELECT ts, id, report_time, tenant_id, server_id, |
| 48 | - upstream, reply, request_id, method, params, | |
| 49 | - data, code, msg | |
| 49 | + upstream, reply, identifier, request_id, method, | |
| 50 | + params, data, code, msg | |
| 50 | 51 | FROM device_message_${reqVO.deviceId} |
| 51 | 52 | <where> |
| 52 | 53 | <if test="reqVO.method != null and reqVO.method != ''"> |
| ... | ... | @@ -55,10 +56,29 @@ |
| 55 | 56 | <if test="reqVO.upstream != null"> |
| 56 | 57 | AND upstream = #{reqVO.upstream} |
| 57 | 58 | </if> |
| 59 | + <if test="reqVO.reply != null"> | |
| 60 | + AND reply = #{reqVO.reply} | |
| 61 | + </if> | |
| 62 | + <if test="reqVO.identifier != null and reqVO.identifier != ''"> | |
| 63 | + AND identifier = #{reqVO.identifier} | |
| 64 | + </if> | |
| 58 | 65 | </where> |
| 59 | 66 | ORDER BY ts DESC |
| 60 | 67 | </select> |
| 61 | 68 | |
| 69 | + <select id="selectListByRequestIdsAndReply" resultType="cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO"> | |
| 70 | + SELECT ts, id, report_time, tenant_id, server_id, | |
| 71 | + upstream, reply, identifier, request_id, method, | |
| 72 | + params, data, code, msg | |
| 73 | + FROM device_message_${deviceId} | |
| 74 | + WHERE reply = #{reply} | |
| 75 | + AND request_id IN | |
| 76 | + <foreach collection="requestIds" item="requestId" open="(" close=")" separator=","> | |
| 77 | + #{requestId} | |
| 78 | + </foreach> | |
| 79 | + ORDER BY ts DESC | |
| 80 | + </select> | |
| 81 | + | |
| 62 | 82 | <select id="selectCountByCreateTime" resultType="Long"> |
| 63 | 83 | SELECT COUNT(*) |
| 64 | 84 | FROM device_message | ... | ... |
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/enums/IotDeviceMessageMethodEnum.java
| ... | ... | @@ -32,6 +32,10 @@ public enum IotDeviceMessageMethodEnum implements ArrayValuable<String> { |
| 32 | 32 | |
| 33 | 33 | EVENT_POST("thing.event.post", "事件上报", true), |
| 34 | 34 | |
| 35 | + // ========== 设备服务调用 ========== | |
| 36 | + | |
| 37 | + SERVICE_INVOKE("thing.service.invoke", "服务调用", false), | |
| 38 | + | |
| 35 | 39 | ; |
| 36 | 40 | |
| 37 | 41 | public static final String[] ARRAYS = Arrays.stream(values()).map(IotDeviceMessageMethodEnum::getMethod) | ... | ... |
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/util/IotDeviceMessageUtils.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.core.util; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.lang.Assert; |
| 4 | +import cn.hutool.core.map.MapUtil; | |
| 4 | 5 | import cn.hutool.core.util.IdUtil; |
| 6 | +import cn.hutool.core.util.StrUtil; | |
| 5 | 7 | import cn.hutool.system.SystemUtil; |
| 6 | 8 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; |
| 7 | 9 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 8 | 10 | |
| 11 | +import java.util.Map; | |
| 12 | + | |
| 9 | 13 | /** |
| 10 | 14 | * IoT 设备【消息】的工具类 |
| 11 | 15 | * |
| ... | ... | @@ -43,6 +47,23 @@ public class IotDeviceMessageUtils { |
| 43 | 47 | return message.getCode() != null; |
| 44 | 48 | } |
| 45 | 49 | |
| 50 | + /** | |
| 51 | + * 提取消息中的标识符 | |
| 52 | + * | |
| 53 | + * @param message 消息 | |
| 54 | + * @return 标识符 | |
| 55 | + */ | |
| 56 | + @SuppressWarnings("unchecked") | |
| 57 | + public static String getIdentifier(IotDeviceMessage message) { | |
| 58 | + if (StrUtil.equalsAny(message.getMethod(), IotDeviceMessageMethodEnum.EVENT_POST.getMethod(), | |
| 59 | + message.getMethod(), IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod()) | |
| 60 | + && message.getParams() != null) { | |
| 61 | + Map<String, Object> params = (Map<String, Object>) message.getParams(); | |
| 62 | + return MapUtil.getStr(params, "identifier"); | |
| 63 | + } | |
| 64 | + return null; | |
| 65 | + } | |
| 66 | + | |
| 46 | 67 | // ========== Topic 相关 ========== |
| 47 | 68 | |
| 48 | 69 | public static String buildMessageBusGatewayDeviceMessageTopic(String serverId) { | ... | ... |