Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/yudao-cloud
# Conflicts: # yudao-dependencies/pom.xml # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/IotDeviceUpstreamApi.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDeviceConfigSetReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDeviceDownstreamAbstractReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDevicePropertyGetReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDevicePropertySetReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/downstream/IotDeviceServiceInvokeReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceEventReportReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDevicePropertyReportReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceRegisterSubReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceStateUpdateReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceTopologyAddReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotDeviceUpstreamAbstractReqDTO.java # yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/api/device/dto/control/upstream/IotPluginInstanceHeartbeatReqDTO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/api/device/IoTDeviceUpstreamApiImpl.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceLogController.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDevicePropertyController.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/control/IotDeviceDownstreamReqVO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/control/IotDeviceUpstreamReqVO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/data/IotDeviceLogPageReqVO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaUpgradeRecordController.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaUpgradeTaskController.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/firmware/IotOtaFirmwareCreateReqVO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/upgrade/record/IotOtaUpgradeRecordPageReqVO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/upgrade/task/IotOtaUpgradeTaskPageReqVO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/upgrade/task/IotOtaUpgradeTaskSaveReqVO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/PluginConfigController.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/plugin/vo/config/PluginConfigImportReqVO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/IotDataBridgeController.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/IotRuleSceneController.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/IotDataBridgeSaveReqVO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/vo/IotStatisticsReqVO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/plugin/DevicePluginProcessIdRedisDAO.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/job/device/IotDeviceOfflineCheckJob.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/job/plugin/IotPluginInstancesJob.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/job/rule/IotRuleSceneJob.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceLogMessageConsumer.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDeviceOnlineMessageConsumer.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/device/IotDevicePropertyMessageConsumer.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/rule/IotRuleSceneMessageHandler.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/producer/device/IotDeviceProducer.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamService.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceDownstreamServiceImpl.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceUpstreamService.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/control/IotDeviceUpstreamServiceImpl.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDeviceLogServiceImpl.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyService.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaFirmwareService.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaUpgradeRecordService.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaUpgradeRecordServiceImpl.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaUpgradeTaskService.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaUpgradeTaskServiceImpl.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginConfigService.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginConfigServiceImpl.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/plugin/IotPluginInstanceServiceImpl.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeService.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeServiceImpl.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotRuleSceneServiceImpl.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDeviceControlAction.java # yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java # yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/biz/dto/IotDeviceAuthReqDTO.java # yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/config/IotPluginCommonAutoConfiguration.java # yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-common/src/main/java/cn/iocoder/yudao/module/iot/plugin/common/config/IotPluginCommonProperties.java # yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/IotDeviceUpstreamServer.java # yudao-module-iot/yudao-module-iot-plugins/yudao-module-iot-plugin-emqx/src/main/java/cn/iocoder/yudao/module/iot/plugin/emqx/upstream/router/IotDeviceMqttMessageHandler.java # yudao-module-iot/yudao-module-iot-server/pom.xml # yudao-module-iot/yudao-module-iot-server/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceImportExcelVO.java # yudao-module-iot/yudao-module-iot-server/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSaveReqVO.java # yudao-module-iot/yudao-module-iot-server/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/firmware/IotOtaFirmwareUpdateReqVO.java # yudao-module-iot/yudao-module-iot-server/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java # yudao-module-iot/yudao-module-iot-server/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java # yudao-module-iot/yudao-module-iot-server/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImpl.java # yudao-module-iot/yudao-module-iot-server/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaFirmwareServiceImpl.java # yudao-module-iot/yudao-module-iot-server/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java # yudao-module-iot/yudao-module-iot-server/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotHttpDataSinkAction.java # yudao-module-iot/yudao-module-iot-server/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.javapull/208/head
commit
78dea8a9cc
|
@ -82,8 +82,8 @@
|
|||
<awssdk.version>2.30.14</awssdk.version>
|
||||
<justauth.version>1.16.7</justauth.version>
|
||||
<justauth-starter.version>1.4.0</justauth-starter.version>
|
||||
<jimureport.version>2.1.0</jimureport.version>
|
||||
<jimubi.version>1.9.5</jimubi.version>
|
||||
<jimureport.version>2.1.1</jimureport.version>
|
||||
<jimubi.version>2.1.0</jimubi.version>
|
||||
<weixin-java.version>4.7.7-20250808.182223</weixin-java.version>
|
||||
<!-- 专属于 JDK8 安全漏洞升级 -->
|
||||
<logback.version>1.2.13</logback.version> <!-- 无法使用 1.3.X 版本,启动会报错 -->
|
||||
|
@ -675,6 +675,10 @@
|
|||
<groupId>com.github.jsqlparser</groupId>
|
||||
<artifactId>jsqlparser</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.Arrays;
|
|||
@AllArgsConstructor
|
||||
public enum DateIntervalEnum implements ArrayValuable<Integer> {
|
||||
|
||||
HOUR(0, "小时"), // 特殊:字典里,暂时不会有这个枚举!!!因为大多数情况下,用不到这个间隔
|
||||
DAY(1, "天"),
|
||||
WEEK(2, "周"),
|
||||
MONTH(3, "月"),
|
||||
|
|
|
@ -8,6 +8,7 @@ import cn.hutool.core.lang.Assert;
|
|||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
@ -16,8 +17,7 @@ import java.time.temporal.TemporalAdjusters;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.hutool.core.date.DatePattern.UTC_MS_WITH_XXX_OFFSET_PATTERN;
|
||||
import static cn.hutool.core.date.DatePattern.createFormatter;
|
||||
import static cn.hutool.core.date.DatePattern.*;
|
||||
|
||||
/**
|
||||
* 时间工具类,用于 {@link LocalDateTime}
|
||||
|
@ -82,6 +82,21 @@ public class LocalDateTimeUtils {
|
|||
return new LocalDateTime[]{buildTime(year1, month1, day1), buildTime(year2, month2, day2)};
|
||||
}
|
||||
|
||||
/**
|
||||
* 判指定断时间,是否在该时间范围内
|
||||
*
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param time 指定时间
|
||||
* @return 是否
|
||||
*/
|
||||
public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime, Timestamp time) {
|
||||
if (startTime == null || endTime == null || time == null) {
|
||||
return false;
|
||||
}
|
||||
return LocalDateTimeUtil.isIn(LocalDateTimeUtil.of(time), startTime, endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判指定断时间,是否在该时间范围内
|
||||
*
|
||||
|
@ -234,6 +249,11 @@ public class LocalDateTimeUtils {
|
|||
// 2. 循环,生成时间范围
|
||||
List<LocalDateTime[]> timeRanges = new ArrayList<>();
|
||||
switch (intervalEnum) {
|
||||
case HOUR:
|
||||
while (startTime.isBefore(endTime)) {
|
||||
timeRanges.add(new LocalDateTime[]{startTime, startTime.plusHours(1).minusNanos(1)});
|
||||
startTime = startTime.plusHours(1);
|
||||
}
|
||||
case DAY:
|
||||
while (startTime.isBefore(endTime)) {
|
||||
timeRanges.add(new LocalDateTime[]{startTime, startTime.plusDays(1).minusNanos(1)});
|
||||
|
@ -297,6 +317,8 @@ public class LocalDateTimeUtils {
|
|||
|
||||
// 2. 循环,生成时间范围
|
||||
switch (intervalEnum) {
|
||||
case HOUR:
|
||||
return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATETIME_MINUTE_PATTERN);
|
||||
case DAY:
|
||||
return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATE_PATTERN);
|
||||
case WEEK:
|
||||
|
|
|
@ -3,18 +3,23 @@ package cn.iocoder.yudao.framework.common.util.json;
|
|||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -26,13 +31,18 @@ import java.util.List;
|
|||
@Slf4j
|
||||
public class JsonUtils {
|
||||
|
||||
@Getter
|
||||
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
static {
|
||||
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null 值
|
||||
objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化
|
||||
// 解决 LocalDateTime 的序列化
|
||||
SimpleModule simpleModule = new JavaTimeModule()
|
||||
.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
|
||||
.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
|
||||
objectMapper.registerModules(simpleModule);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,6 +109,18 @@ public class JsonUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static <T> T parseObject(byte[] text, Type type) {
|
||||
if (ArrayUtil.isEmpty(text)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.readValue(text, objectMapper.getTypeFactory().constructType(type));
|
||||
} catch (IOException e) {
|
||||
log.error("json parse err,json:{}", text, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串解析成指定类型的对象
|
||||
* 使用 {@link #parseObject(String, Class)} 时,在@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 的场景下,
|
||||
|
|
|
@ -60,4 +60,8 @@ public class ObjectUtils {
|
|||
return Arrays.asList(array).contains(obj);
|
||||
}
|
||||
|
||||
public static boolean isNotAllEmpty(Object... objs) {
|
||||
return !ObjectUtil.isAllEmpty(objs);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -69,9 +69,8 @@ public class YudaoRedisMQConsumerAutoConfiguration {
|
|||
@ConditionalOnBean(AbstractRedisStreamMessageListener.class) // 只有 AbstractStreamMessageListener 存在的时候,才需要注册 Redis pubsub 监听
|
||||
public RedisPendingMessageResendJob redisPendingMessageResendJob(List<AbstractRedisStreamMessageListener<?>> listeners,
|
||||
RedisMQTemplate redisTemplate,
|
||||
@Value("${spring.application.name}") String groupName,
|
||||
RedissonClient redissonClient) {
|
||||
return new RedisPendingMessageResendJob(listeners, redisTemplate, groupName, redissonClient);
|
||||
return new RedisPendingMessageResendJob(listeners, redisTemplate, redissonClient);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,14 +140,14 @@ public class YudaoRedisMQConsumerAutoConfiguration {
|
|||
*
|
||||
* @return 消费者名字
|
||||
*/
|
||||
private static String buildConsumerName() {
|
||||
public static String buildConsumerName() {
|
||||
return String.format("%s@%d", SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID());
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验 Redis 版本号,是否满足最低的版本号要求!
|
||||
*/
|
||||
private static void checkRedisVersion(RedisTemplate<String, ?> redisTemplate) {
|
||||
public static void checkRedisVersion(RedisTemplate<String, ?> redisTemplate) {
|
||||
// 获得 Redis 版本
|
||||
Properties info = redisTemplate.execute((RedisCallback<Properties>) RedisServerCommands::info);
|
||||
String version = MapUtil.getStr(info, "redis_version");
|
||||
|
|
|
@ -35,7 +35,6 @@ public class RedisPendingMessageResendJob {
|
|||
|
||||
private final List<AbstractRedisStreamMessageListener<?>> listeners;
|
||||
private final RedisMQTemplate redisTemplate;
|
||||
private final String groupName;
|
||||
private final RedissonClient redissonClient;
|
||||
|
||||
/**
|
||||
|
@ -64,13 +63,13 @@ public class RedisPendingMessageResendJob {
|
|||
private void execute() {
|
||||
StreamOperations<String, Object, Object> ops = redisTemplate.getRedisTemplate().opsForStream();
|
||||
listeners.forEach(listener -> {
|
||||
PendingMessagesSummary pendingMessagesSummary = Objects.requireNonNull(ops.pending(listener.getStreamKey(), groupName));
|
||||
PendingMessagesSummary pendingMessagesSummary = Objects.requireNonNull(ops.pending(listener.getStreamKey(), listener.getGroup()));
|
||||
// 每个消费者的 pending 队列消息数量
|
||||
Map<String, Long> pendingMessagesPerConsumer = pendingMessagesSummary.getPendingMessagesPerConsumer();
|
||||
pendingMessagesPerConsumer.forEach((consumerName, pendingMessageCount) -> {
|
||||
log.info("[processPendingMessage][消费者({}) 消息数量({})]", consumerName, pendingMessageCount);
|
||||
// 每个消费者的 pending消息的详情信息
|
||||
PendingMessages pendingMessages = ops.pending(listener.getStreamKey(), Consumer.from(groupName, consumerName), Range.unbounded(), pendingMessageCount);
|
||||
PendingMessages pendingMessages = ops.pending(listener.getStreamKey(), Consumer.from(listener.getGroup(), consumerName), Range.unbounded(), pendingMessageCount);
|
||||
if (pendingMessages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -91,7 +90,7 @@ public class RedisPendingMessageResendJob {
|
|||
.ofObject(records.get(0).getValue()) // 设置内容
|
||||
.withStreamKey(listener.getStreamKey()));
|
||||
// ack 消息消费完成
|
||||
redisTemplate.getRedisTemplate().opsForStream().acknowledge(groupName, records.get(0));
|
||||
redisTemplate.getRedisTemplate().opsForStream().acknowledge(listener.getGroup(), records.get(0));
|
||||
log.info("[processPendingMessage][消息({})重新投递成功]", records.get(0).getId());
|
||||
});
|
||||
});
|
||||
|
|
|
@ -53,6 +53,12 @@ public abstract class AbstractRedisStreamMessageListener<T extends AbstractRedis
|
|||
this.streamKey = messageType.getDeclaredConstructor().newInstance().getStreamKey();
|
||||
}
|
||||
|
||||
protected AbstractRedisStreamMessageListener(String streamKey, String group) {
|
||||
this.messageType = null;
|
||||
this.streamKey = streamKey;
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(ObjectRecord<String, String> message) {
|
||||
// 消费消息
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package cn.iocoder.yudao.framework.mybatis.config;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.handler.DefaultDBFieldHandler;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import com.baomidou.mybatisplus.extension.incrementer.*;
|
||||
import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
|
||||
import com.baomidou.mybatisplus.extension.parser.cache.JdkSerialCaffeineJsqlParseCache;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
|
@ -18,6 +22,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -75,4 +80,15 @@ public class YudaoMybatisAutoConfiguration {
|
|||
throw new IllegalArgumentException(StrUtil.format("DbType{} 找不到合适的 IKeyGenerator 实现类", dbType));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JacksonTypeHandler jacksonTypeHandler(List<ObjectMapper> objectMappers) {
|
||||
// 特殊:设置 JacksonTypeHandler 的 ObjectMapper!
|
||||
ObjectMapper objectMapper = CollUtil.getFirst(objectMappers);
|
||||
if (objectMapper == null) {
|
||||
objectMapper = JsonUtils.getObjectMapper();
|
||||
}
|
||||
JacksonTypeHandler.setObjectMapper(objectMapper);
|
||||
return new JacksonTypeHandler(Object.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public class RateLimiterAspect {
|
|||
|
||||
@Before("@annotation(rateLimiter)")
|
||||
public void beforePointCut(JoinPoint joinPoint, RateLimiter rateLimiter) {
|
||||
// 获得 IdempotentKeyResolver 对象
|
||||
// 获得 RateLimiterKeyResolver 对象
|
||||
RateLimiterKeyResolver keyResolver = keyResolvers.get(rateLimiter.keyResolver());
|
||||
Assert.notNull(keyResolver, "找不到对应的 RateLimiterKeyResolver");
|
||||
// 解析 Key
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
# AiBoChaWebSearchClient 使用指南
|
||||
|
||||
## 概述
|
||||
|
||||
`AiBoChaWebSearchClient` 是基于博查AI开放平台提供的网页搜索服务的Java客户端,实现了符合项目架构风格的HTTP客户端封装。
|
||||
|
||||
## 特性
|
||||
|
||||
- **统一的API调用风格**:参考 SunoApi 和 XunFeiPptApi 的实现方式
|
||||
- **Record 类型数据结构**:使用 Record 类型定义请求和响应数据
|
||||
- **简洁的响应数据模型**:包含网页搜索结果
|
||||
- **灵活的搜索配置**:支持时间范围、域名过滤、结果数量等参数
|
||||
- **错误处理机制**:统一的异常处理和日志记录
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 创建客户端实例
|
||||
|
||||
```java
|
||||
// 使用默认base URL
|
||||
AiBoChaWebSearchClient client = new AiBoChaWebSearchClient("your-api-key");
|
||||
|
||||
// 使用自定义base URL
|
||||
AiBoChaWebSearchClient client = new AiBoChaWebSearchClient("https://custom.api.com", "your-api-key");
|
||||
```
|
||||
|
||||
### 2. 基本搜索
|
||||
|
||||
```java
|
||||
// 基本搜索
|
||||
WebSearchRequest request = new WebSearchRequest(
|
||||
"Spring Boot 教程",
|
||||
null, null, null, null, null
|
||||
);
|
||||
AiWebSearchResponse result = client.search(request);
|
||||
```
|
||||
|
||||
### 3. 高级搜索
|
||||
|
||||
```java
|
||||
// 构建详细的搜索请求
|
||||
WebSearchRequest request = new WebSearchRequest(
|
||||
"人工智能最新进展",
|
||||
FreshnessType.ONE_WEEK.getValue(), // 搜索一周内的内容
|
||||
true, // 显示摘要
|
||||
"zhihu.com|csdn.net", // 只搜索指定域名
|
||||
"spam.com", // 排除指定域名
|
||||
20 // 返回20条结果
|
||||
);
|
||||
|
||||
AiWebSearchResponse result = client.search(request);
|
||||
```
|
||||
|
||||
## API参数说明
|
||||
|
||||
### 请求参数
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| query | String | 是 | 用户的搜索词 |
|
||||
| freshness | String | 否 | 搜索时间范围,默认为 noLimit |
|
||||
| summary | Boolean | 否 | 是否显示文本摘要,默认为 false |
|
||||
| include | String | 否 | 指定搜索的网站范围,多个域名使用\|或,分隔 |
|
||||
| exclude | String | 否 | 排除搜索的网站范围,多个域名使用\|或,分隔 |
|
||||
| count | Integer | 否 | 返回结果条数,范围1-50,默认为10 |
|
||||
|
||||
### 时间范围选项
|
||||
|
||||
使用 `FreshnessType` 枚举:
|
||||
|
||||
```java
|
||||
FreshnessType.NO_LIMIT // 不限(默认)
|
||||
FreshnessType.ONE_DAY // 一天内
|
||||
FreshnessType.ONE_WEEK // 一周内
|
||||
FreshnessType.ONE_MONTH // 一个月内
|
||||
FreshnessType.ONE_YEAR // 一年内
|
||||
```
|
||||
|
||||
也可以使用自定义日期范围:
|
||||
- 日期范围:`"2025-01-01..2025-04-06"`
|
||||
- 指定日期:`"2025-04-06"`
|
||||
|
||||
### 响应数据结构
|
||||
|
||||
```java
|
||||
// 主要响应数据
|
||||
AiWebSearchResponse result = client.search(request);
|
||||
|
||||
// 网页搜索结果
|
||||
List<AiWebSearchResponse.WebPage> webPages = result.webPages();
|
||||
for (AiWebSearchResponse.WebPage page : webPages) {
|
||||
String title = page.title(); // 网页标题
|
||||
String url = page.url(); // 网页URL
|
||||
String snippet = page.snippet(); // 内容描述
|
||||
String summary = page.summary(); // 文本摘要(如果请求了summary)
|
||||
String siteName = page.siteName(); // 网站名称
|
||||
}
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 示例1:搜索技术文档
|
||||
|
||||
```java
|
||||
WebSearchRequest request = new WebSearchRequest(
|
||||
"Spring Boot 3.x 新特性",
|
||||
FreshnessType.ONE_MONTH.getValue(),
|
||||
true,
|
||||
"spring.io|baeldung.com|github.com",
|
||||
null,
|
||||
15
|
||||
);
|
||||
|
||||
AiWebSearchResponse result = client.search(request);
|
||||
```
|
||||
|
||||
### 示例2:搜索新闻资讯
|
||||
|
||||
```java
|
||||
WebSearchRequest request = new WebSearchRequest(
|
||||
"AI大模型发展趋势",
|
||||
FreshnessType.ONE_WEEK.getValue(),
|
||||
null,
|
||||
null,
|
||||
"advertisement.com|spam.net",
|
||||
30
|
||||
);
|
||||
|
||||
AiWebSearchResponse result = client.search(request);
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **API密钥**:需要先到博查AI开放平台(https://open.bochaai.com)获取API KEY
|
||||
2. **请求频率**:注意遵守平台的API调用频率限制
|
||||
3. **时间范围**:建议使用 `noLimit` 以获得更好的搜索效果
|
||||
4. **域名过滤**:include和exclude参数最多支持20个域名
|
||||
5. **结果数量**:单次搜索最多返回50条结果
|
||||
|
||||
## 集成建议
|
||||
|
||||
在Spring Boot项目中,建议将客户端配置为Bean:
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
public class AiConfiguration {
|
||||
|
||||
@Value("${ai.bocha.api-key}")
|
||||
private String apiKey;
|
||||
|
||||
@Value("${ai.bocha.base-url:https://open.bochaai.com}")
|
||||
private String baseUrl;
|
||||
|
||||
@Bean
|
||||
public AiBoChaWebSearchClient boChaWebSearchClient() {
|
||||
return new AiBoChaWebSearchClient(baseUrl, apiKey);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 故障排查
|
||||
|
||||
1. **网络连接问题**:检查网络连接和防火墙设置
|
||||
2. **API密钥错误**:确认API KEY正确且有效
|
||||
3. **请求参数错误**:检查必填参数是否正确填写
|
||||
4. **服务器响应错误**:查看日志中的详细错误信息
|
||||
|
||||
## 更新日志
|
||||
|
||||
- v2.0.0:重大重构,统一 Record 类型,简化 API 调用,支持新的响应结构
|
||||
- v1.3.0:统一使用 Record 类型,移除 Lombok 注解,保持代码风格一致性
|
||||
- v1.2.0:进一步简化,移除视频搜索功能,专注于网页搜索
|
||||
- v1.1.0:使用 Lombok 简化代码,移除图片搜索功能
|
||||
- v1.0.0:初始版本,实现基本的网页搜索功能
|
|
@ -155,13 +155,13 @@ spring:
|
|||
rerank: false # 是否开启“通义千问”的 Rerank 模型,填写 dashscope 开启
|
||||
mcp:
|
||||
server:
|
||||
enabled: true
|
||||
enabled: false
|
||||
name: yudao-mcp-server
|
||||
version: 1.0.0
|
||||
instructions: 一个 MCP 示例服务
|
||||
sse-endpoint: /sse
|
||||
client:
|
||||
enabled: true
|
||||
enabled: false
|
||||
name: mcp
|
||||
sse:
|
||||
connections:
|
||||
|
|
|
@ -19,6 +19,7 @@ public enum BpmReasonEnum {
|
|||
CANCEL_PROCESS_INSTANCE_BY_START_USER("用户主动取消流程,原因:{}"), // 场景:用户主动取消流程
|
||||
CANCEL_PROCESS_INSTANCE_BY_ADMIN("管理员【{}】取消流程,原因:{}"), // 场景:管理员取消流程
|
||||
CANCEL_CHILD_PROCESS_INSTANCE_BY_MAIN_PROCESS("子流程自动取消,原因:主流程已取消"),
|
||||
REJECT_CHILD_PROCESS("子流程审批不通过"),
|
||||
|
||||
// ========== 流程任务的独有原因 ==========
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.flowable.engine.history.HistoricActivityInstance;
|
|||
import org.flowable.engine.history.HistoricProcessInstance;
|
||||
import org.flowable.engine.history.HistoricProcessInstanceQuery;
|
||||
import org.flowable.engine.repository.ProcessDefinition;
|
||||
import org.flowable.engine.runtime.Execution;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.flowable.engine.runtime.ProcessInstanceBuilder;
|
||||
import org.flowable.task.api.Task;
|
||||
|
@ -949,6 +950,29 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||
status);
|
||||
}
|
||||
|
||||
// 1.3 如果子流程拒绝,设置其父流程也为拒绝状态,且结束父流程
|
||||
// 相关问题链接:https://t.zsxq.com/kZhyb
|
||||
if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())
|
||||
&& StrUtil.isNotBlank(instance.getSuperExecutionId())) {
|
||||
// 1.3.1 获取父流程实例 并标记为不通过
|
||||
Execution execution = runtimeService.createExecutionQuery().executionId(instance.getSuperExecutionId()).singleResult();
|
||||
ProcessInstance parentProcessInstance = getProcessInstance(execution.getProcessInstanceId());
|
||||
updateProcessInstanceReject(parentProcessInstance, BpmReasonEnum.REJECT_CHILD_PROCESS.getReason());
|
||||
|
||||
// 1.3.2 结束父流程。需要在子流程结束事务提交后执行
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
|
||||
@Override
|
||||
public void afterCompletion(int transactionStatus) {
|
||||
// 回滚情况,直接返回
|
||||
if (ObjectUtil.equal(transactionStatus, TransactionSynchronization.STATUS_ROLLED_BACK)) {
|
||||
return;
|
||||
}
|
||||
taskService.moveTaskToEnd(parentProcessInstance.getId(), BpmReasonEnum.REJECT_CHILD_PROCESS.getReason());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 发送对应的消息通知
|
||||
if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
|
||||
messageService.sendMessageWhenProcessInstanceApprove(
|
||||
|
@ -996,17 +1020,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
|
|||
if (ObjUtil.notEqual(instance.getName(), name)) {
|
||||
runtimeService.setProcessInstanceName(instance.getProcessInstanceId(), name);
|
||||
}
|
||||
|
||||
// 流程前置通知:需要在流程启动后(事务提交后),保证 variables 已设置
|
||||
// 相关问题链接:https://t.zsxq.com/DF7Kq
|
||||
if (ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) {
|
||||
return;
|
||||
}
|
||||
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting();
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
|
||||
setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// 流程前置通知
|
||||
if (ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) {
|
||||
return;
|
||||
}
|
||||
BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting();
|
||||
BpmHttpRequestUtils.executeBpmHttpRequest(instance,
|
||||
setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -804,7 +804,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
.setTargetTaskDefinitionKey(returnTaskId).setReason(reqVO.getReason()));
|
||||
return;
|
||||
}
|
||||
// 3.2 情况二:直接结束,审批不通过
|
||||
|
||||
// 3.2 情况二: 标记流程为不通过并结束流程
|
||||
processInstanceService.updateProcessInstanceReject(instance, reqVO.getReason()); // 标记不通过
|
||||
moveTaskToEnd(task.getProcessInstanceId(), BpmCommentTypeEnum.REJECT.formatComment(reqVO.getReason())); // 结束流程
|
||||
}
|
||||
|
@ -986,6 +987,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void moveTaskToEnd(String processInstanceId, String reason) {
|
||||
List<Task> taskList = getRunningTaskListByProcessInstanceId(processInstanceId, null, null);
|
||||
if (CollUtil.isEmpty(taskList)) {
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
</parent>
|
||||
<modules>
|
||||
<module>yudao-module-iot-api</module>
|
||||
<module>yudao-module-iot-biz</module>
|
||||
<module>yudao-module-iot-plugins</module>
|
||||
<module>yudao-module-iot-core</module>
|
||||
<module>yudao-module-iot-server</module>
|
||||
<module>yudao-module-iot-gateway</module>
|
||||
</modules>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.*;
|
||||
import cn.iocoder.yudao.module.iot.enums.ApiConstants;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 设备数据 Upstream 上行 API
|
||||
*
|
||||
* 目的:设备 -> 插件 -> 服务端
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
public interface IotDeviceUpstreamApi {
|
||||
|
||||
String PREFIX = ApiConstants.PREFIX + "/device/upstream";
|
||||
|
||||
// ========== 设备相关 ==========
|
||||
|
||||
/**
|
||||
* 更新设备状态
|
||||
*
|
||||
* @param updateReqDTO 更新设备状态 DTO
|
||||
*/
|
||||
@PostMapping(PREFIX + "/update-state")
|
||||
CommonResult<Boolean> updateDeviceState(@Valid @RequestBody IotDeviceStateUpdateReqDTO updateReqDTO);
|
||||
|
||||
/**
|
||||
* 上报设备属性数据
|
||||
*
|
||||
* @param reportReqDTO 上报设备属性数据 DTO
|
||||
*/
|
||||
@PostMapping(PREFIX + "/report-property")
|
||||
CommonResult<Boolean> reportDeviceProperty(@Valid @RequestBody IotDevicePropertyReportReqDTO reportReqDTO);
|
||||
|
||||
/**
|
||||
* 上报设备事件数据
|
||||
*
|
||||
* @param reportReqDTO 设备事件
|
||||
*/
|
||||
@PostMapping(PREFIX + "/report-event")
|
||||
CommonResult<Boolean> reportDeviceEvent(@Valid @RequestBody IotDeviceEventReportReqDTO reportReqDTO);
|
||||
|
||||
// TODO @芋艿:这个需要 plugins 接入下
|
||||
/**
|
||||
* 注册设备
|
||||
*
|
||||
* @param registerReqDTO 注册设备 DTO
|
||||
*/
|
||||
@PostMapping(PREFIX + "/register")
|
||||
CommonResult<Boolean> registerDevice(@Valid @RequestBody IotDeviceRegisterReqDTO registerReqDTO);
|
||||
|
||||
// TODO @芋艿:这个需要 plugins 接入下
|
||||
/**
|
||||
* 注册子设备
|
||||
*
|
||||
* @param registerReqDTO 注册子设备 DTO
|
||||
*/
|
||||
@PostMapping(PREFIX + "/register-sub")
|
||||
CommonResult<Boolean> registerSubDevice(@Valid @RequestBody IotDeviceRegisterSubReqDTO registerReqDTO);
|
||||
|
||||
// TODO @芋艿:这个需要 plugins 接入下
|
||||
/**
|
||||
* 注册设备拓扑
|
||||
*
|
||||
* @param addReqDTO 注册设备拓扑 DTO
|
||||
*/
|
||||
@PostMapping(PREFIX + "/add-topology")
|
||||
CommonResult<Boolean> addDeviceTopology(@Valid @RequestBody IotDeviceTopologyAddReqDTO addReqDTO);
|
||||
|
||||
// TODO @芋艿:考虑 http 认证
|
||||
/**
|
||||
* 认证 Emqx 连接
|
||||
*
|
||||
* @param authReqDTO 认证 Emqx 连接 DTO
|
||||
*/
|
||||
@PostMapping(PREFIX + "/authenticate-emqx-connection")
|
||||
CommonResult<Boolean> authenticateEmqxConnection(@Valid @RequestBody IotDeviceEmqxAuthReqDTO authReqDTO);
|
||||
|
||||
// ========== 插件相关 ==========
|
||||
|
||||
/**
|
||||
* 心跳插件实例
|
||||
*
|
||||
* @param heartbeatReqDTO 心跳插件实例 DTO
|
||||
*/
|
||||
@PostMapping(PREFIX + "/heartbeat-plugin-instance")
|
||||
CommonResult<Boolean> heartbeatPluginInstance(@Valid @RequestBody IotPluginInstanceHeartbeatReqDTO heartbeatReqDTO);
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* IoT 设备【配置】设置 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDeviceConfigSetReqDTO extends IotDeviceDownstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 配置
|
||||
*/
|
||||
@NotNull(message = "配置不能为空")
|
||||
private Map<String, Object> config;
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* IoT 设备下行的抽象 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public abstract class IotDeviceDownstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 请求编号
|
||||
*/
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 产品标识
|
||||
*/
|
||||
@NotEmpty(message = "产品标识不能为空")
|
||||
private String productKey;
|
||||
/**
|
||||
* 设备名称
|
||||
*/
|
||||
@NotEmpty(message = "设备名称不能为空")
|
||||
private String deviceName;
|
||||
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* IoT 设备【OTA】升级下发 Request DTO(更新固件消息)
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDeviceOtaUpgradeReqDTO extends IotDeviceDownstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
*/
|
||||
private Long firmwareId;
|
||||
/**
|
||||
* 固件版本
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 签名方式
|
||||
*
|
||||
* 例如说:MD5、SHA256
|
||||
*/
|
||||
private String signMethod;
|
||||
/**
|
||||
* 固件文件签名
|
||||
*/
|
||||
private String fileSign;
|
||||
/**
|
||||
* 固件文件大小
|
||||
*/
|
||||
private Long fileSize;
|
||||
/**
|
||||
* 固件文件 URL
|
||||
*/
|
||||
private String fileUrl;
|
||||
|
||||
/**
|
||||
* 自定义信息,建议使用 JSON 格式
|
||||
*/
|
||||
private String information;
|
||||
|
||||
public static IotDeviceOtaUpgradeReqDTO build(Map<?, ?> map) {
|
||||
return new IotDeviceOtaUpgradeReqDTO()
|
||||
.setFirmwareId(MapUtil.getLong(map, "firmwareId")).setVersion((String) map.get("version"))
|
||||
.setSignMethod((String) map.get("signMethod")).setFileSign((String) map.get("fileSign"))
|
||||
.setFileSize(MapUtil.getLong(map, "fileSize")).setFileUrl((String) map.get("fileUrl"))
|
||||
.setInformation((String) map.get("information"));
|
||||
}
|
||||
|
||||
public static Map<?, ?> build(IotDeviceOtaUpgradeReqDTO dto) {
|
||||
return MapUtil.builder()
|
||||
.put("firmwareId", dto.getFirmwareId()).put("version", dto.getVersion())
|
||||
.put("signMethod", dto.getSignMethod()).put("fileSign", dto.getFileSign())
|
||||
.put("fileSize", dto.getFileSize()).put("fileUrl", dto.getFileUrl())
|
||||
.put("information", dto.getInformation())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
// TODO @芋艿:从 server => plugin => device 是否有必要?从阿里云 iot 来看,没有这个功能?!
|
||||
// TODO @芋艿:是不是改成 read 更好?在看看阿里云的 topic 设计
|
||||
/**
|
||||
* IoT 设备【属性】获取 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDevicePropertyGetReqDTO extends IotDeviceDownstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 属性标识数组
|
||||
*/
|
||||
@NotEmpty(message = "属性标识数组不能为空")
|
||||
private List<String> identifiers;
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* IoT 设备【属性】设置 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDevicePropertySetReqDTO extends IotDeviceDownstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 属性参数
|
||||
*/
|
||||
@NotEmpty(message = "属性参数不能为空")
|
||||
private Map<String, Object> properties;
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* IoT 设备【服务】调用 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDeviceServiceInvokeReqDTO extends IotDeviceDownstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 服务标识
|
||||
*/
|
||||
@NotEmpty(message = "服务标识不能为空")
|
||||
private String identifier;
|
||||
/**
|
||||
* 调用参数
|
||||
*/
|
||||
private Map<String, Object> params;
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* IoT 设备【事件】上报 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDeviceEventReportReqDTO extends IotDeviceUpstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 事件标识
|
||||
*/
|
||||
@NotEmpty(message = "事件标识不能为空")
|
||||
private String identifier;
|
||||
/**
|
||||
* 事件参数
|
||||
*/
|
||||
private Map<String, Object> params;
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
// TODO @芋艿:待实现:/ota/${productKey}/${deviceName}/progress
|
||||
/**
|
||||
* IoT 设备【OTA】升级进度 Request DTO(上报更新固件进度)
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDeviceOtaProgressReqDTO extends IotDeviceUpstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
*/
|
||||
private Long firmwareId;
|
||||
|
||||
/**
|
||||
* 升级状态
|
||||
*
|
||||
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.ota.IotOtaUpgradeRecordStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 升级进度,百分比
|
||||
*/
|
||||
private Integer progress;
|
||||
|
||||
/**
|
||||
* 升级进度描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
// TODO @芋艿:待实现:/ota/${productKey}/${deviceName}/pull
|
||||
/**
|
||||
* IoT 设备【OTA】升级下拉 Request DTO(拉取固件更新)
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class IotDeviceOtaPullReqDTO {
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
*/
|
||||
private Long firmwareId;
|
||||
|
||||
/**
|
||||
* 固件版本
|
||||
*/
|
||||
private String version;
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
// TODO @芋艿:待实现:/ota/${productKey}/${deviceName}/report
|
||||
/**
|
||||
* IoT 设备【OTA】上报 Request DTO(上报固件版本)
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class IotDeviceOtaReportReqDTO {
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
*/
|
||||
private Long firmwareId;
|
||||
|
||||
/**
|
||||
* 固件版本
|
||||
*/
|
||||
private String version;
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* IoT 设备【属性】上报 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDevicePropertyReportReqDTO extends IotDeviceUpstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 属性参数
|
||||
*/
|
||||
@NotEmpty(message = "属性参数不能为空")
|
||||
private Map<String, Object> properties;
|
||||
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* IoT 设备【注册】自己 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDeviceRegisterReqDTO extends IotDeviceUpstreamAbstractReqDTO {
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* IoT 设备【注册】子设备 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDeviceRegisterSubReqDTO extends IotDeviceUpstreamAbstractReqDTO {
|
||||
|
||||
// TODO @芋艿:看看要不要优化命名
|
||||
/**
|
||||
* 子设备数组
|
||||
*/
|
||||
@NotEmpty(message = "子设备不能为空")
|
||||
private List<Device> params;
|
||||
|
||||
/**
|
||||
* 设备信息
|
||||
*/
|
||||
@Data
|
||||
public static class Device {
|
||||
|
||||
/**
|
||||
* 产品标识
|
||||
*/
|
||||
@NotEmpty(message = "产品标识不能为空")
|
||||
private String productKey;
|
||||
|
||||
/**
|
||||
* 设备名称
|
||||
*/
|
||||
@NotEmpty(message = "设备名称不能为空")
|
||||
private String deviceName;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* IoT 设备【状态】更新 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotDeviceStateUpdateReqDTO extends IotDeviceUpstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 设备状态
|
||||
*/
|
||||
@NotNull(message = "设备状态不能为空")
|
||||
@InEnum(IotDeviceStateEnum.class) // 只使用:在线、离线
|
||||
private Integer state;
|
||||
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
// TODO @芋艿:要写清楚,是来自设备网关,还是设备。
|
||||
/**
|
||||
* IoT 设备【拓扑】添加 Request DTO
|
||||
*/
|
||||
@Data
|
||||
public class IotDeviceTopologyAddReqDTO extends IotDeviceUpstreamAbstractReqDTO {
|
||||
|
||||
// TODO @芋艿:看看要不要优化命名
|
||||
/**
|
||||
* 子设备数组
|
||||
*/
|
||||
@NotEmpty(message = "子设备不能为空")
|
||||
private List<IotDeviceRegisterSubReqDTO.Device> params;
|
||||
|
||||
/**
|
||||
* 设备信息
|
||||
*/
|
||||
@Data
|
||||
public static class Device {
|
||||
|
||||
/**
|
||||
* 产品标识
|
||||
*/
|
||||
@NotEmpty(message = "产品标识不能为空")
|
||||
private String productKey;
|
||||
|
||||
/**
|
||||
* 设备名称
|
||||
*/
|
||||
@NotEmpty(message = "设备名称不能为空")
|
||||
private String deviceName;
|
||||
|
||||
// TODO @芋艿:阿里云还有 sign 签名
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* IoT 设备上行的抽象 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public abstract class IotDeviceUpstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 请求编号
|
||||
*/
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 插件实例的进程编号
|
||||
*/
|
||||
private String processId;
|
||||
|
||||
/**
|
||||
* 产品标识
|
||||
*/
|
||||
@NotEmpty(message = "产品标识不能为空")
|
||||
private String productKey;
|
||||
/**
|
||||
* 设备名称
|
||||
*/
|
||||
@NotEmpty(message = "设备名称不能为空")
|
||||
private String deviceName;
|
||||
|
||||
/**
|
||||
* 上报时间
|
||||
*/
|
||||
@JsonSerialize(using = TimestampLocalDateTimeSerializer.class) // 解决 iot plugins 序列化 LocalDateTime 是数组,导致无法解析的问题
|
||||
private LocalDateTime reportTime;
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.upstream;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* IoT 插件实例心跳 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class IotPluginInstanceHeartbeatReqDTO {
|
||||
|
||||
/**
|
||||
* 请求编号
|
||||
*/
|
||||
@NotEmpty(message = "请求编号不能为空")
|
||||
private String processId;
|
||||
|
||||
/**
|
||||
* 插件包标识符
|
||||
*/
|
||||
@NotEmpty(message = "插件包标识符不能为空")
|
||||
private String pluginKey;
|
||||
|
||||
/**
|
||||
* 插件实例所在 IP
|
||||
*/
|
||||
@NotEmpty(message = "插件实例所在 IP 不能为空")
|
||||
private String hostIp;
|
||||
/**
|
||||
* 插件实例的进程编号
|
||||
*/
|
||||
@NotNull(message = "插件实例的进程编号不能为空")
|
||||
private Integer downstreamPort;
|
||||
|
||||
/**
|
||||
* 是否在线
|
||||
*/
|
||||
@NotNull(message = "是否在线不能为空")
|
||||
private Boolean online;
|
||||
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* TODO 芋艿:占位
|
||||
*/
|
||||
package cn.iocoder.yudao.module.iot.api.device.dto;
|
|
@ -1,6 +1,4 @@
|
|||
/**
|
||||
* 占位
|
||||
*
|
||||
* TODO 芋艿:后续删除
|
||||
* iot API 包,定义暴露给其它模块的 API
|
||||
*/
|
||||
package cn.iocoder.yudao.module.iot.api;
|
||||
|
|
|
@ -7,16 +7,19 @@ package cn.iocoder.yudao.module.iot.enums;
|
|||
*/
|
||||
public class DictTypeConstants {
|
||||
|
||||
public static final String NET_TYPE = "iot_net_type";
|
||||
public static final String LOCATION_TYPE = "iot_location_type";
|
||||
public static final String CODEC_TYPE = "iot_codec_type";
|
||||
|
||||
public static final String PRODUCT_STATUS = "iot_product_status";
|
||||
public static final String PRODUCT_DEVICE_TYPE = "iot_product_device_type";
|
||||
public static final String NET_TYPE = "iot_net_type";
|
||||
public static final String PROTOCOL_TYPE = "iot_protocol_type";
|
||||
public static final String DATA_FORMAT = "iot_data_format";
|
||||
public static final String VALIDATE_TYPE = "iot_validate_type";
|
||||
|
||||
public static final String DEVICE_STATE = "iot_device_state";
|
||||
|
||||
public static final String IOT_DATA_BRIDGE_DIRECTION_ENUM = "iot_data_bridge_direction_enum";
|
||||
public static final String IOT_DATA_BRIDGE_TYPE_ENUM = "iot_data_bridge_type_enum";
|
||||
public static final String ALERT_LEVEL = "iot_alert_level";
|
||||
|
||||
public static final String OTA_TASK_DEVICE_SCOPE = "iot_ota_task_device_scope";
|
||||
public static final String OTA_TASK_STATUS = "iot_ota_task_status";
|
||||
public static final String OTA_TASK_RECORD_STATUS = "iot_ota_task_record_status";
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode PRODUCT_KEY_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在");
|
||||
ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除");
|
||||
ErrorCode PRODUCT_STATUS_NOT_ALLOW_THING_MODEL = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型");
|
||||
ErrorCode PRODUCT_DELETE_FAIL_HAS_DEVICE = new ErrorCode(1_050_001_004, "产品下存在设备,不允许删除");
|
||||
|
||||
// ========== 产品物模型 1-050-002-000 ============
|
||||
ErrorCode THING_MODEL_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在");
|
||||
|
@ -30,7 +31,8 @@ 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_DOWNSTREAM_FAILED = new ErrorCode(1_050_003_007, "执行失败,原因:{}");
|
||||
ErrorCode DEVICE_DOWNSTREAM_FAILED_SERVER_ID_NULL = new ErrorCode(1_050_003_007, "下行设备消息失败,原因:设备未连接网关");
|
||||
ErrorCode DEVICE_SERIAL_NUMBER_EXISTS = new ErrorCode(1_050_003_008, "设备序列号已存在,序列号必须全局唯一");
|
||||
|
||||
// ========== 产品分类 1-050-004-000 ==========
|
||||
ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_004_000, "产品分类不存在");
|
||||
|
@ -39,37 +41,42 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode DEVICE_GROUP_NOT_EXISTS = new ErrorCode(1_050_005_000, "设备分组不存在");
|
||||
ErrorCode DEVICE_GROUP_DELETE_FAIL_DEVICE_EXISTS = new ErrorCode(1_050_005_001, "设备分组下存在设备,不允许删除");
|
||||
|
||||
// ========== 插件配置 1-050-006-000 ==========
|
||||
ErrorCode PLUGIN_CONFIG_NOT_EXISTS = new ErrorCode(1_050_006_000, "插件配置不存在");
|
||||
ErrorCode PLUGIN_INSTALL_FAILED = new ErrorCode(1_050_006_001, "插件安装失败");
|
||||
ErrorCode PLUGIN_INSTALL_FAILED_FILE_NAME_NOT_MATCH = new ErrorCode(1_050_006_002, "插件安装失败,文件名与原插件id不匹配");
|
||||
ErrorCode PLUGIN_CONFIG_DELETE_FAILED_RUNNING = new ErrorCode(1_050_006_003, "请先停止插件");
|
||||
ErrorCode PLUGIN_STATUS_INVALID = new ErrorCode(1_050_006_004, "插件状态无效");
|
||||
ErrorCode PLUGIN_CONFIG_KEY_DUPLICATE = new ErrorCode(1_050_006_005, "插件标识已存在");
|
||||
ErrorCode PLUGIN_START_FAILED = new ErrorCode(1_050_006_006, "插件启动失败");
|
||||
ErrorCode PLUGIN_STOP_FAILED = new ErrorCode(1_050_006_007, "插件停止失败");
|
||||
|
||||
// ========== 插件实例 1-050-007-000 ==========
|
||||
|
||||
// ========== 固件相关 1-050-008-000 ==========
|
||||
// ========== OTA 固件相关 1-050-008-000 ==========
|
||||
|
||||
ErrorCode OTA_FIRMWARE_NOT_EXISTS = new ErrorCode(1_050_008_000, "固件信息不存在");
|
||||
ErrorCode OTA_FIRMWARE_PRODUCT_VERSION_DUPLICATE = new ErrorCode(1_050_008_001, "产品版本号重复");
|
||||
|
||||
ErrorCode OTA_UPGRADE_TASK_NOT_EXISTS = new ErrorCode(1_050_008_100, "升级任务不存在");
|
||||
ErrorCode OTA_UPGRADE_TASK_NAME_DUPLICATE = new ErrorCode(1_050_008_101, "升级任务名称重复");
|
||||
ErrorCode OTA_UPGRADE_TASK_DEVICE_IDS_EMPTY = new ErrorCode(1_050_008_102, "设备编号列表不能为空");
|
||||
ErrorCode OTA_UPGRADE_TASK_DEVICE_LIST_EMPTY = new ErrorCode(1_050_008_103, "设备列表不能为空");
|
||||
ErrorCode OTA_UPGRADE_TASK_CANNOT_CANCEL = new ErrorCode(1_050_008_104, "升级任务不能取消");
|
||||
// ========== OTA 升级任务相关 1-050-008-100 ==========
|
||||
|
||||
ErrorCode OTA_UPGRADE_RECORD_NOT_EXISTS = new ErrorCode(1_050_008_200, "升级记录不存在");
|
||||
ErrorCode OTA_UPGRADE_RECORD_DUPLICATE = new ErrorCode(1_050_008_201, "升级记录重复");
|
||||
ErrorCode OTA_UPGRADE_RECORD_CANNOT_RETRY = new ErrorCode(1_050_008_202, "升级记录不能重试");
|
||||
ErrorCode OTA_TASK_NOT_EXISTS = new ErrorCode(1_050_008_100, "升级任务不存在");
|
||||
ErrorCode OTA_TASK_CREATE_FAIL_NAME_DUPLICATE = new ErrorCode(1_050_008_101, "创建 OTA 任务失败,原因:任务名称重复");
|
||||
ErrorCode OTA_TASK_CREATE_FAIL_DEVICE_FIRMWARE_EXISTS = new ErrorCode(1_050_008_102,
|
||||
"创建 OTA 任务失败,原因:设备({})已经是该固件版本");
|
||||
ErrorCode OTA_TASK_CREATE_FAIL_DEVICE_OTA_IN_PROCESS = new ErrorCode(1_050_008_102,
|
||||
"创建 OTA 任务失败,原因:设备({})已经在升级中...");
|
||||
ErrorCode OTA_TASK_CREATE_FAIL_DEVICE_EMPTY = new ErrorCode(1_050_008_103, "创建 OTA 任务失败,原因:没有可升级的设备");
|
||||
ErrorCode OTA_TASK_CANCEL_FAIL_STATUS_END = new ErrorCode(1_050_008_104, "取消 OTA 任务失败,原因:任务状态不是进行中");
|
||||
|
||||
// ========== MQTT 通信相关 1-050-009-000 ==========
|
||||
ErrorCode MQTT_TOPIC_ILLEGAL = new ErrorCode(1_050_009_000, "topic illegal");
|
||||
// ========== OTA 升级任务记录相关 1-050-008-200 ==========
|
||||
|
||||
// ========== IoT 数据桥梁 1-050-010-000 ==========
|
||||
ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_010_000, "IoT 数据桥梁不存在");
|
||||
ErrorCode OTA_TASK_RECORD_NOT_EXISTS = new ErrorCode(1_050_008_200, "升级记录不存在");
|
||||
ErrorCode OTA_TASK_RECORD_CANCEL_FAIL_STATUS_ERROR = new ErrorCode(1_050_008_201, "取消 OTA 升级记录失败,原因:记录状态不是进行中");
|
||||
ErrorCode OTA_TASK_RECORD_UPDATE_PROGRESS_FAIL_NO_EXISTS = new ErrorCode(1_050_008_202, "更新 OTA 升级记录进度失败,原因:该设备没有进行中的升级记录");
|
||||
|
||||
// ========== IoT 数据流转规则 1-050-010-000 ==========
|
||||
ErrorCode DATA_RULE_NOT_EXISTS = new ErrorCode(1_050_010_000, "数据流转规则不存在");
|
||||
|
||||
// ========== IoT 数据流转目的 1-050-011-000 ==========
|
||||
ErrorCode DATA_SINK_NOT_EXISTS = new ErrorCode(1_050_011_000, "数据桥梁不存在");
|
||||
ErrorCode DATA_SINK_DELETE_FAIL_USED_BY_RULE = new ErrorCode(1_050_011_001, "数据流转目的正在被数据流转规则使用,无法删除");
|
||||
|
||||
// ========== IoT 场景联动 1-050-012-000 ==========
|
||||
ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_012_000, "场景联动不存在");
|
||||
|
||||
// ========== IoT 告警配置 1-050-013-000 ==========
|
||||
ErrorCode ALERT_CONFIG_NOT_EXISTS = new ErrorCode(1_050_013_000, "IoT 告警配置不存在");
|
||||
|
||||
// ========== IoT 告警记录 1-050-014-000 ==========
|
||||
ErrorCode ALERT_RECORD_NOT_EXISTS = new ErrorCode(1_050_014_000, "IoT 告警记录不存在");
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.rule;
|
||||
package cn.iocoder.yudao.module.iot.enums.alert;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
|
@ -7,21 +7,22 @@ import lombok.RequiredArgsConstructor;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 告警配置的接收方式枚举
|
||||
* IoT 告警的接收方式枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotAlertConfigReceiveTypeEnum implements ArrayValuable<Integer> {
|
||||
public enum IotAlertReceiveTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
SMS(1), // 短信
|
||||
MAIL(2), // 邮箱
|
||||
NOTIFY(3); // 通知
|
||||
NOTIFY(3); // 站内信
|
||||
// TODO 待实现(欢迎 pull request):webhook 4
|
||||
|
||||
private final Integer type;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotAlertConfigReceiveTypeEnum::getType).toArray(Integer[]::new);
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotAlertReceiveTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
|
@ -7,11 +7,12 @@ import lombok.RequiredArgsConstructor;
|
|||
/**
|
||||
* IoT 设备消息标识符枚举
|
||||
*/
|
||||
@Deprecated
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum IotDeviceMessageIdentifierEnum {
|
||||
|
||||
PROPERTY_GET("get"), // 下行 TODO 芋艿:【讨论】貌似这个“上行”更合理?device 主动拉取配置。和 IotDevicePropertyGetReqDTO 一样的配置
|
||||
PROPERTY_GET("get"), // 下行
|
||||
PROPERTY_SET("set"), // 下行
|
||||
PROPERTY_REPORT("report"), // 上行
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import java.util.Arrays;
|
|||
/**
|
||||
* IoT 设备消息类型枚举
|
||||
*/
|
||||
@Deprecated
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum IotDeviceMessageTypeEnum implements ArrayValuable<String> {
|
||||
|
|
|
@ -7,18 +7,19 @@ import lombok.RequiredArgsConstructor;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT OTA 升级任务的范围枚举
|
||||
* IoT OTA 升级任务的设备范围枚举
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotOtaUpgradeTaskScopeEnum implements ArrayValuable<Integer> {
|
||||
public enum IotOtaTaskDeviceScopeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
ALL(1), // 全部设备:只包括当前产品下的设备,不包括未来创建的设备
|
||||
SELECT(2); // 指定设备
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotOtaUpgradeTaskScopeEnum::getScope).toArray(Integer[]::new);
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values())
|
||||
.map(IotOtaTaskDeviceScopeEnum::getScope).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 范围
|
|
@ -0,0 +1,57 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.ota;
|
||||
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* IoT OTA 升级任务记录的状态枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotOtaTaskRecordStatusEnum implements ArrayValuable<Integer> {
|
||||
|
||||
PENDING(0), // 待推送
|
||||
PUSHED(10), // 已推送
|
||||
UPGRADING(20), // 升级中
|
||||
SUCCESS(30), // 升级成功
|
||||
FAILURE(40), // 升级失败
|
||||
CANCELED(50),; // 升级取消
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values())
|
||||
.map(IotOtaTaskRecordStatusEnum::getStatus).toArray(Integer[]::new);
|
||||
|
||||
public static final Set<Integer> IN_PROCESS_STATUSES = SetUtils.asSet(
|
||||
PENDING.getStatus(),
|
||||
PUSHED.getStatus(),
|
||||
UPGRADING.getStatus());
|
||||
|
||||
public static final List<Integer> PRIORITY_STATUSES = Arrays.asList(
|
||||
SUCCESS.getStatus(),
|
||||
PENDING.getStatus(), PUSHED.getStatus(), UPGRADING.getStatus(),
|
||||
FAILURE.getStatus(), CANCELED.getStatus());
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private final Integer status;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
public static IotOtaTaskRecordStatusEnum of(Integer status) {
|
||||
return ArrayUtil.firstMatch(o -> o.getStatus().equals(status), values());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.ota;
|
||||
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
@ -8,25 +7,23 @@ import lombok.RequiredArgsConstructor;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT OTA 升级记录的范围枚举
|
||||
* IoT OTA 升级任务的状态
|
||||
*
|
||||
* @author haohao
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotOtaUpgradeRecordStatusEnum implements ArrayValuable<Integer> {
|
||||
public enum IotOtaTaskStatusEnum implements ArrayValuable<Integer> {
|
||||
|
||||
PENDING(0), // 待推送
|
||||
PUSHED(10), // 已推送
|
||||
UPGRADING(20), // 升级中
|
||||
SUCCESS(30), // 升级成功
|
||||
FAILURE(40), // 升级失败
|
||||
CANCELED(50),; // 已取消
|
||||
IN_PROGRESS(10), // 进行中(升级中)
|
||||
END(20), // 已结束(包括全部成功、部分成功)
|
||||
CANCELED(30),; // 已取消(一般是主动取消任务)
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotOtaUpgradeRecordStatusEnum::getStatus).toArray(Integer[]::new);
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values())
|
||||
.map(IotOtaTaskStatusEnum::getStatus).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 范围
|
||||
* 状态
|
||||
*/
|
||||
private final Integer status;
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.ota;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT OTA 升级任务的范围枚举
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotOtaUpgradeTaskStatusEnum implements ArrayValuable<Integer> {
|
||||
|
||||
IN_PROGRESS(10), // 进行中:升级中
|
||||
COMPLETED(20), // 已完成:已结束,全部升级完成
|
||||
INCOMPLETE(21), // 未完成:已结束,部分升级完成
|
||||
CANCELED(30),; // 已取消:一般是主动取消任务
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotOtaUpgradeTaskStatusEnum::getStatus).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 范围
|
||||
*/
|
||||
private final Integer status;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.plugin;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 部署方式枚举
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotPluginDeployTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
JAR(0, "JAR 部署"),
|
||||
STANDALONE(1, "独立部署");
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotPluginDeployTypeEnum::getDeployType).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 部署方式
|
||||
*/
|
||||
private final Integer deployType;
|
||||
/**
|
||||
* 部署方式名
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.plugin;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 插件状态枚举
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotPluginStatusEnum implements ArrayValuable<Integer> {
|
||||
|
||||
STOPPED(0, "停止"),
|
||||
RUNNING(1, "运行");
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotPluginStatusEnum::getStatus).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private final Integer status;
|
||||
/**
|
||||
* 状态名
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.plugin;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 插件类型枚举
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum IotPluginTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
NORMAL(0, "普通插件"),
|
||||
DEVICE(1, "设备插件");
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotPluginTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 类型名
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.product;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 产品数据格式枚举类
|
||||
*
|
||||
* @author ahh
|
||||
* @see <a href="https://help.aliyun.com/zh/iot/user-guide/message-parsing">阿里云 - 什么是消息解析</a>
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum IotDataFormatEnum implements ArrayValuable<Integer> {
|
||||
|
||||
JSON(0, "标准数据格式(JSON)"),
|
||||
CUSTOMIZE(1, "透传/自定义");
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataFormatEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,18 +7,19 @@ import lombok.Getter;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 数据校验级别枚举类
|
||||
* IoT 定位方式枚举类
|
||||
*
|
||||
* @author ahh
|
||||
* @author alwayssuper
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum IotValidateTypeEnum implements ArrayValuable<Integer> {
|
||||
public enum IotLocationTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
WEAK(0, "弱校验"),
|
||||
NONE(1, "免校验");
|
||||
IP(1, "IP 定位"),
|
||||
DEVICE(2, "设备上报"),
|
||||
MANUAL(3, "手动定位");
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotValidateTypeEnum::getType).toArray(Integer[]::new);
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotLocationTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 类型
|
|
@ -1,40 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.product;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 接入网关协议枚举类
|
||||
*
|
||||
* @author ahh
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum IotProtocolTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
CUSTOM(0, "自定义"),
|
||||
MODBUS(1, "Modbus"),
|
||||
OPC_UA(2, "OPC UA"),
|
||||
ZIGBEE(3, "ZigBee"),
|
||||
BLE(4, "BLE");
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotProtocolTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.rule;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 数据桥接的方向枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotDataBridgeDirectionEnum implements ArrayValuable<Integer> {
|
||||
|
||||
INPUT(1), // 输入
|
||||
OUTPUT(2); // 输出
|
||||
|
||||
private final Integer type;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataBridgeDirectionEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.rule;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 数据桥接的类型枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotDataBridgeTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
HTTP(1, "HTTP"),
|
||||
TCP(2, "TCP"),
|
||||
WEBSOCKET(3, "WEBSOCKET"),
|
||||
|
||||
MQTT(10, "MQTT"),
|
||||
|
||||
DATABASE(20, "DATABASE"),
|
||||
REDIS_STREAM(21, "REDIS_STREAM"),
|
||||
|
||||
ROCKETMQ(30, "ROCKETMQ"),
|
||||
RABBITMQ(31, "RABBITMQ"),
|
||||
KAFKA(32, "KAFKA");
|
||||
|
||||
private final Integer type;
|
||||
|
||||
private final String name;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataBridgeTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.rule;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 数据目的的类型枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotDataSinkTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
HTTP(1, "HTTP"),
|
||||
TCP(2, "TCP"), // TODO @puhui999:待实现;
|
||||
WEBSOCKET(3, "WebSocket"), // TODO @puhui999:待实现;
|
||||
|
||||
MQTT(10, "MQTT"), // TODO 待实现;
|
||||
|
||||
DATABASE(20, "Database"), // TODO @puhui999:待实现;可以简单点,对应的表名是什么,字段先固定了。
|
||||
REDIS(21, "Redis"),
|
||||
|
||||
ROCKETMQ(30, "RocketMQ"),
|
||||
RABBITMQ(31, "RabbitMQ"),
|
||||
KAFKA(32, "Kafka");
|
||||
|
||||
private final Integer type;
|
||||
|
||||
private final String name;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataSinkTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,21 +7,26 @@ import lombok.RequiredArgsConstructor;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 规则场景的触发类型枚举
|
||||
* IoT Redis 数据结构类型枚举
|
||||
*
|
||||
* 设备触发,定时触发
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotRuleSceneActionTypeEnum implements ArrayValuable<Integer> {
|
||||
public enum IotRedisDataStructureEnum implements ArrayValuable<Integer> {
|
||||
|
||||
DEVICE_CONTROL(1), // 设备执行
|
||||
ALERT(2), // 告警执行
|
||||
DATA_BRIDGE(3); // 桥接执行
|
||||
STREAM(1, "Stream"),
|
||||
HASH(2, "Hash"),
|
||||
LIST(3, "List"),
|
||||
SET(4, "Set"),
|
||||
ZSET(5, "ZSet"),
|
||||
STRING(6, "String");
|
||||
|
||||
private final Integer type;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneActionTypeEnum::getType).toArray(Integer[]::new);
|
||||
private final String name;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotRedisDataStructureEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
|
@ -1,30 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.rule;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 场景流转的触发类型枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotRuleSceneTriggerTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
DEVICE(1), // 设备触发
|
||||
TIMER(2); // 定时触发
|
||||
|
||||
private final Integer type;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneTriggerTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.rule;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 规则场景的触发类型枚举
|
||||
*
|
||||
* 设备触发,定时触发
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotSceneRuleActionTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
/**
|
||||
* 设备属性设置
|
||||
*
|
||||
* 对应 {@link IotDeviceMessageMethodEnum#PROPERTY_SET}
|
||||
*/
|
||||
DEVICE_PROPERTY_SET(1),
|
||||
/**
|
||||
* 设备服务调用
|
||||
*
|
||||
* 对应 {@link IotDeviceMessageMethodEnum#SERVICE_INVOKE}
|
||||
*/
|
||||
DEVICE_SERVICE_INVOKE(2),
|
||||
|
||||
/**
|
||||
* 告警触发
|
||||
*/
|
||||
ALERT_TRIGGER(100),
|
||||
/**
|
||||
* 告警恢复
|
||||
*/
|
||||
ALERT_RECOVER(101),
|
||||
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotSceneRuleActionTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
|
@ -8,13 +8,13 @@ import lombok.RequiredArgsConstructor;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 场景触发条件参数的操作符枚举
|
||||
* IoT 场景触发条件的操作符枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotRuleSceneTriggerConditionParameterOperatorEnum implements ArrayValuable<String> {
|
||||
public enum IotSceneRuleConditionOperatorEnum implements ArrayValuable<String> {
|
||||
|
||||
EQUALS("=", "#source == #value"),
|
||||
NOT_EQUALS("!=", "!(#source == #value)"),
|
||||
|
@ -32,12 +32,28 @@ public enum IotRuleSceneTriggerConditionParameterOperatorEnum implements ArrayVa
|
|||
NOT_BETWEEN("not between", "(#source < #values.get(0)) || (#source > #values.get(1))"),
|
||||
|
||||
LIKE("like", "#source.contains(#value)"), // 字符串匹配
|
||||
NOT_NULL("not null", "#source != null && #source.length() > 0"); // 非空
|
||||
NOT_NULL("not null", "#source != null && #source.length() > 0"), // 非空
|
||||
|
||||
// ========== 特殊:不放在字典里 ==========
|
||||
|
||||
// TODO @puhui999:@芋艿:需要测试下
|
||||
DATE_TIME_GREATER_THAN("date_time_>", "#source > #value"), // 在时间之后:时间戳
|
||||
DATE_TIME_LESS_THAN("date_time_<", "#source < #value"), // 在时间之前:时间戳
|
||||
DATE_TIME_BETWEEN("date_time_between", // 在时间之间:时间戳
|
||||
"(#source >= #values.get(0)) && (#source <= #values.get(1))"),
|
||||
|
||||
// TODO @puhui999:@芋艿:需要测试下
|
||||
TIME_GREATER_THAN("time_>", "#source.isAfter(#value)"), // 在当日时间之后:HH:mm:ss
|
||||
TIME_LESS_THAN("time_<", "#source.isBefore(#value)"), // 在当日时间之前:HH:mm:ss
|
||||
TIME_BETWEEN("time_between", // 在当日时间之间:HH:mm:ss
|
||||
"(#source >= #values.get(0)) && (#source <= #values.get(1))"),
|
||||
|
||||
;
|
||||
|
||||
private final String operator;
|
||||
private final String springExpression;
|
||||
|
||||
public static final String[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneTriggerConditionParameterOperatorEnum::getOperator).toArray(String[]::new);
|
||||
public static final String[] ARRAYS = Arrays.stream(values()).map(IotSceneRuleConditionOperatorEnum::getOperator).toArray(String[]::new);
|
||||
|
||||
/**
|
||||
* Spring 表达式 - 原始值
|
||||
|
@ -50,9 +66,9 @@ public enum IotRuleSceneTriggerConditionParameterOperatorEnum implements ArrayVa
|
|||
/**
|
||||
* Spring 表达式 - 目标值数组
|
||||
*/
|
||||
public static final String SPRING_EXPRESSION_VALUE_List = "values";
|
||||
public static final String SPRING_EXPRESSION_VALUE_LIST = "values";
|
||||
|
||||
public static IotRuleSceneTriggerConditionParameterOperatorEnum operatorOf(String operator) {
|
||||
public static IotSceneRuleConditionOperatorEnum operatorOf(String operator) {
|
||||
return ArrayUtil.firstMatch(item -> item.getOperator().equals(operator), values());
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.rule;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 条件类型枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotSceneRuleConditionTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
DEVICE_STATE(1, "设备状态"),
|
||||
DEVICE_PROPERTY(2, "设备属性"),
|
||||
|
||||
CURRENT_TIME(100, "当前时间"),
|
||||
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
private final String name;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotSceneRuleConditionTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
public static IotSceneRuleConditionTypeEnum typeOf(Integer type) {
|
||||
return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package cn.iocoder.yudao.module.iot.enums.rule;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 场景流转的触发类型枚举
|
||||
*
|
||||
* 为什么不直接使用 IotDeviceMessageMethodEnum 呢?
|
||||
* 原因是,物模型属性上报,存在批量上报的情况,不只对应一个 method!!!
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotSceneRuleTriggerTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
// TODO @芋艿:后续“对应”部分,要 @下,等包结构梳理完;
|
||||
/**
|
||||
* 设备上下线变更
|
||||
*
|
||||
* 对应 IotDeviceMessageMethodEnum.STATE_UPDATE
|
||||
*/
|
||||
DEVICE_STATE_UPDATE(1),
|
||||
/**
|
||||
* 物模型属性上报
|
||||
*
|
||||
* 对应 IotDeviceMessageMethodEnum.DEVICE_PROPERTY_POST
|
||||
*/
|
||||
DEVICE_PROPERTY_POST(2),
|
||||
/**
|
||||
* 设备事件上报
|
||||
*
|
||||
* 对应 IotDeviceMessageMethodEnum.DEVICE_EVENT_POST
|
||||
*/
|
||||
DEVICE_EVENT_POST(3),
|
||||
/**
|
||||
* 设备服务调用
|
||||
*
|
||||
* 对应 IotDeviceMessageMethodEnum.DEVICE_SERVICE_INVOKE
|
||||
*/
|
||||
DEVICE_SERVICE_INVOKE(4),
|
||||
|
||||
/**
|
||||
* 定时触发
|
||||
*/
|
||||
TIMER(100)
|
||||
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotSceneRuleTriggerTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
public static IotSceneRuleTriggerTypeEnum typeOf(Integer type) {
|
||||
return ArrayUtil.firstMatch(item -> item.getType().equals(type), values());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot;
|
||||
|
||||
import cn.hutool.script.ScriptUtil;
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
/**
|
||||
* TODO 芋艿:测试脚本的接入
|
||||
*/
|
||||
public class ScriptTest {
|
||||
|
||||
public static void main2(String[] args) {
|
||||
// 创建一个 Groovy 脚本引擎
|
||||
ScriptEngine engine = ScriptUtil.createGroovyEngine();
|
||||
|
||||
// 创建绑定参数
|
||||
Bindings bindings = engine.createBindings();
|
||||
bindings.put("name", "Alice");
|
||||
bindings.put("age", 30);
|
||||
|
||||
// 定义一个稍微复杂的 Groovy 脚本
|
||||
String script = "def greeting = 'Hello, ' + name + '!';\n" +
|
||||
"def ageInFiveYears = age + 5;\n" +
|
||||
"def message = greeting + ' In five years, you will be ' + ageInFiveYears + ' years old.';\n" +
|
||||
"return message.toUpperCase();\n";
|
||||
|
||||
try {
|
||||
// 执行脚本并获取结果
|
||||
Object result = engine.eval(script, bindings);
|
||||
System.out.println(result); // 输出: HELLO, ALICE! IN FIVE YEARS, YOU WILL BE 35 YEARS OLD.
|
||||
} catch (ScriptException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 创建一个 JavaScript 脚本引擎
|
||||
ScriptEngine jsEngine = ScriptUtil.createJsEngine();
|
||||
|
||||
// 创建绑定参数
|
||||
Bindings jsBindings = jsEngine.createBindings();
|
||||
jsBindings.put("name", "Bob");
|
||||
jsBindings.put("age", 25);
|
||||
|
||||
// 定义一个简单的 JavaScript 脚本
|
||||
String jsScript = "var greeting = 'Hello, ' + name + '!';\n" +
|
||||
"var ageInTenYears = age + 10;\n" +
|
||||
"var message = greeting + ' In ten years, you will be ' + ageInTenYears + ' years old.';\n" +
|
||||
"message.toUpperCase();\n";
|
||||
|
||||
try {
|
||||
// 执行脚本并获取结果
|
||||
Object jsResult = jsEngine.eval(jsScript, jsBindings);
|
||||
System.out.println(jsResult); // 输出: HELLO, BOB! IN TEN YEARS, YOU WILL BE 35 YEARS OLD.
|
||||
} catch (ScriptException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.*;
|
||||
import cn.iocoder.yudao.module.iot.service.device.control.IotDeviceUpstreamService;
|
||||
import cn.iocoder.yudao.module.iot.service.plugin.IotPluginInstanceService;
|
||||
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;
|
||||
|
||||
/**
|
||||
* * 设备数据 Upstream 上行 API 实现类
|
||||
*/
|
||||
@RestController
|
||||
@Validated
|
||||
public class IoTDeviceUpstreamApiImpl implements IotDeviceUpstreamApi {
|
||||
|
||||
@Resource
|
||||
private IotDeviceUpstreamService deviceUpstreamService;
|
||||
@Resource
|
||||
private IotPluginInstanceService pluginInstanceService;
|
||||
|
||||
// ========== 设备相关 ==========
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {
|
||||
deviceUpstreamService.updateDeviceState(updateReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) {
|
||||
deviceUpstreamService.reportDeviceProperty(reportReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) {
|
||||
deviceUpstreamService.reportDeviceEvent(reportReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> registerDevice(IotDeviceRegisterReqDTO registerReqDTO) {
|
||||
deviceUpstreamService.registerDevice(registerReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO) {
|
||||
deviceUpstreamService.registerSubDevice(registerReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO) {
|
||||
deviceUpstreamService.addDeviceTopology(addReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) {
|
||||
boolean result = deviceUpstreamService.authenticateEmqxConnection(authReqDTO);
|
||||
return success(result);
|
||||
}
|
||||
|
||||
// ========== 插件相关 ==========
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> heartbeatPluginInstance(IotPluginInstanceHeartbeatReqDTO heartbeatReqDTO) {
|
||||
pluginInstanceService.heartbeatPluginInstance(heartbeatReqDTO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
/**
|
||||
* 占位
|
||||
*
|
||||
* TODO 芋艿:后续删除
|
||||
*/
|
||||
package cn.iocoder.yudao.module.iot.api;
|
|
@ -1,75 +0,0 @@
|
|||
### 请求 /iot/device/downstream 接口(服务调用) => 成功
|
||||
POST {{baseUrl}}/iot/device/downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "service",
|
||||
"identifier": "temperature",
|
||||
"data": {
|
||||
"xx": "yy"
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/device/downstream 接口(属性设置) => 成功
|
||||
POST {{baseUrl}}/iot/device/downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "property",
|
||||
"identifier": "set",
|
||||
"data": {
|
||||
"xx": "yy"
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/device/downstream 接口(属性获取) => 成功
|
||||
POST {{baseUrl}}/iot/device/downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "property",
|
||||
"identifier": "get",
|
||||
"data": ["xx", "yy"]
|
||||
}
|
||||
|
||||
### 请求 /iot/device/downstream 接口(配置设置) => 成功
|
||||
POST {{baseUrl}}/iot/device/downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "config",
|
||||
"identifier": "set"
|
||||
}
|
||||
|
||||
### 请求 /iot/device/downstream 接口(OTA 升级) => 成功
|
||||
POST {{baseUrl}}/iot/device/downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "ota",
|
||||
"identifier": "upgrade",
|
||||
"data": {
|
||||
"firmwareId": 1,
|
||||
"version": "1.0.0",
|
||||
"signMethod": "MD5",
|
||||
"fileSign": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"fileSize": 1024,
|
||||
"fileUrl": "http://example.com/firmware.bin",
|
||||
"information": "{\"desc\":\"升级到最新版本\"}"
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.device;
|
||||
|
||||
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.data.IotDeviceLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDeviceLogRespVO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
|
||||
import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 设备日志")
|
||||
@RestController
|
||||
@RequestMapping("/iot/device/log")
|
||||
@Validated
|
||||
public class IotDeviceLogController {
|
||||
|
||||
@Resource
|
||||
private IotDeviceLogService deviceLogService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得设备日志分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:log-query')")
|
||||
public CommonResult<PageResult<IotDeviceLogRespVO>> getDeviceLogPage(@Valid IotDeviceLogPageReqVO pageReqVO) {
|
||||
PageResult<IotDeviceLogDO> pageResult = deviceLogService.getDeviceLogPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotDeviceLogRespVO.class));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.device;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryPageReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
||||
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
|
||||
import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
|
||||
import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 设备属性")
|
||||
@RestController
|
||||
@RequestMapping("/iot/device/property")
|
||||
@Validated
|
||||
public class IotDevicePropertyController {
|
||||
|
||||
@Resource
|
||||
private IotDevicePropertyService devicePropertyService;
|
||||
@Resource
|
||||
private IotThingModelService thingModelService;
|
||||
@Resource
|
||||
private IotDeviceService deviceService;
|
||||
|
||||
@GetMapping("/latest")
|
||||
@Operation(summary = "获取设备属性最新属性")
|
||||
@Parameters({
|
||||
@Parameter(name = "deviceId", description = "设备编号", required = true),
|
||||
@Parameter(name = "identifier", description = "标识符"),
|
||||
@Parameter(name = "name", description = "名称")
|
||||
})
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:property-query')")
|
||||
public CommonResult<List<IotDevicePropertyRespVO>> getLatestDeviceProperties(
|
||||
@RequestParam("deviceId") Long deviceId,
|
||||
@RequestParam(value = "identifier", required = false) String identifier,
|
||||
@RequestParam(value = "name", required = false) String name) {
|
||||
Map<String, IotDevicePropertyDO> properties = devicePropertyService.getLatestDeviceProperties(deviceId);
|
||||
|
||||
// 拼接数据
|
||||
IotDeviceDO device = deviceService.getDevice(deviceId);
|
||||
Assert.notNull(device, "设备不存在");
|
||||
List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductId(device.getProductId());
|
||||
return success(convertList(properties.entrySet(), entry -> {
|
||||
IotThingModelDO thingModel = CollUtil.findOne(thingModels,
|
||||
item -> item.getIdentifier().equals(entry.getKey()));
|
||||
if (thingModel == null || thingModel.getProperty() == null) {
|
||||
return null;
|
||||
}
|
||||
if (StrUtil.isNotEmpty(identifier) && !StrUtil.contains(thingModel.getIdentifier(), identifier)) {
|
||||
return null;
|
||||
}
|
||||
if (StrUtil.isNotEmpty(name) && !StrUtil.contains(thingModel.getName(), name)) {
|
||||
return null;
|
||||
}
|
||||
// 构建对象
|
||||
IotDevicePropertyDO property = entry.getValue();
|
||||
return new IotDevicePropertyRespVO().setProperty(thingModel.getProperty())
|
||||
.setValue(property.getValue()).setUpdateTime(LocalDateTimeUtil.toEpochMilli(property.getUpdateTime()));
|
||||
}));
|
||||
}
|
||||
|
||||
@GetMapping("/history-page")
|
||||
@Operation(summary = "获取设备属性历史数据")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:property-query')")
|
||||
public CommonResult<PageResult<IotDevicePropertyRespVO>> getHistoryDevicePropertyPage(
|
||||
@Valid IotDevicePropertyHistoryPageReqVO pageReqVO) {
|
||||
Assert.notEmpty(pageReqVO.getIdentifier(), "标识符不能为空");
|
||||
return success(devicePropertyService.getHistoryDevicePropertyPage(pageReqVO));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.device.vo.control;
|
||||
|
||||
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 lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备下行 Request VO") // 服务调用、属性设置、属性获取等
|
||||
@Data
|
||||
public class IotDeviceDownstreamReqVO {
|
||||
|
||||
@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; // 例如说:服务调用的 params、属性设置的 properties
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.device.vo.control;
|
||||
|
||||
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 lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备上行 Request VO") // 属性上报、事件上报、状态变更等
|
||||
@Data
|
||||
public class IotDeviceUpstreamReqVO {
|
||||
|
||||
@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
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.device.vo.data;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备日志分页查询 Request VO")
|
||||
@Data
|
||||
public class IotDeviceLogPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
|
||||
@NotEmpty(message = "设备标识不能为空")
|
||||
private String deviceKey;
|
||||
|
||||
@Schema(description = "消息类型", example = "property")
|
||||
private String type; // 参见 IotDeviceMessageTypeEnum 枚举,精准匹配
|
||||
|
||||
@Schema(description = "标识符", example = "temperature")
|
||||
private String identifier; // 参见 IotDeviceMessageIdentifierEnum 枚举,模糊匹配
|
||||
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.device.vo.data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备日志 Response VO")
|
||||
@Data
|
||||
public class IotDeviceLogRespVO {
|
||||
|
||||
@Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123")
|
||||
private String productKey;
|
||||
|
||||
@Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
|
||||
private String deviceKey;
|
||||
|
||||
@Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature")
|
||||
private String identifier;
|
||||
|
||||
@Schema(description = "日志内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String content;
|
||||
|
||||
@Schema(description = "上报时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime reportTime;
|
||||
|
||||
@Schema(description = "记录时间戳", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime ts;
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备 MQTT 连接参数 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class IotDeviceMqttConnectionParamsRespVO {
|
||||
|
||||
@Schema(description = "MQTT 客户端 ID", example = "24602")
|
||||
@ExcelProperty("MQTT 客户端 ID")
|
||||
private String mqttClientId;
|
||||
|
||||
@Schema(description = "MQTT 用户名", example = "芋艿")
|
||||
@ExcelProperty("MQTT 用户名")
|
||||
private String mqttUsername;
|
||||
|
||||
@Schema(description = "MQTT 密码")
|
||||
@ExcelProperty("MQTT 密码")
|
||||
private String mqttPassword;
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.ota;
|
||||
|
||||
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.ota.vo.upgrade.record.IotOtaUpgradeRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.upgrade.record.IotOtaUpgradeRecordRespVO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaUpgradeRecordDO;
|
||||
import cn.iocoder.yudao.module.iot.service.ota.IotOtaUpgradeRecordService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT OTA 升级记录")
|
||||
@RestController
|
||||
@RequestMapping("/iot/ota-upgrade-record")
|
||||
@Validated
|
||||
public class IotOtaUpgradeRecordController {
|
||||
|
||||
@Resource
|
||||
private IotOtaUpgradeRecordService upgradeRecordService;
|
||||
|
||||
@GetMapping("/get-statistics")
|
||||
@Operation(summary = "固件升级设备统计")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
|
||||
@Parameter(name = "firmwareId", description = "固件编号", required = true, example = "1024")
|
||||
public CommonResult<Map<Integer, Long>> getOtaUpgradeRecordStatistics(@RequestParam(value = "firmwareId") Long firmwareId) {
|
||||
return success(upgradeRecordService.getOtaUpgradeRecordStatistics(firmwareId));
|
||||
}
|
||||
|
||||
@GetMapping("/get-count")
|
||||
@Operation(summary = "获得升级记录分页 tab 数量")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
|
||||
public CommonResult<Map<Integer, Long>> getOtaUpgradeRecordCount(
|
||||
@Valid IotOtaUpgradeRecordPageReqVO pageReqVO) {
|
||||
return success(upgradeRecordService.getOtaUpgradeRecordCount(pageReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得升级记录分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
|
||||
public CommonResult<PageResult<IotOtaUpgradeRecordRespVO>> getUpgradeRecordPage(
|
||||
@Valid IotOtaUpgradeRecordPageReqVO pageReqVO) {
|
||||
PageResult<IotOtaUpgradeRecordDO> pageResult = upgradeRecordService.getUpgradeRecordPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotOtaUpgradeRecordRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得升级记录")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
|
||||
@Parameter(name = "id", description = "升级记录编号", required = true, example = "1024")
|
||||
public CommonResult<IotOtaUpgradeRecordRespVO> getUpgradeRecord(@RequestParam("id") Long id) {
|
||||
IotOtaUpgradeRecordDO upgradeRecord = upgradeRecordService.getUpgradeRecord(id);
|
||||
return success(BeanUtils.toBean(upgradeRecord, IotOtaUpgradeRecordRespVO.class));
|
||||
}
|
||||
|
||||
@PutMapping("/retry")
|
||||
@Operation(summary = "重试升级记录")
|
||||
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:retry')")
|
||||
@Parameter(name = "id", description = "升级记录编号", required = true, example = "1024")
|
||||
public CommonResult<Boolean> retryUpgradeRecord(@RequestParam("id") Long id) {
|
||||
upgradeRecordService.retryUpgradeRecord(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.ota;
|
||||
|
||||
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.ota.vo.upgrade.task.IotOtaUpgradeTaskPageReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.upgrade.task.IotOtaUpgradeTaskRespVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.upgrade.task.IotOtaUpgradeTaskSaveReqVO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaUpgradeTaskDO;
|
||||
import cn.iocoder.yudao.module.iot.service.ota.IotOtaUpgradeTaskService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT OTA 升级任务")
|
||||
@RestController
|
||||
@RequestMapping("/iot/ota-upgrade-task")
|
||||
@Validated
|
||||
public class IotOtaUpgradeTaskController {
|
||||
|
||||
@Resource
|
||||
private IotOtaUpgradeTaskService upgradeTaskService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建升级任务")
|
||||
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:create')")
|
||||
public CommonResult<Long> createUpgradeTask(@Valid @RequestBody IotOtaUpgradeTaskSaveReqVO createReqVO) {
|
||||
return success(upgradeTaskService.createUpgradeTask(createReqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/cancel")
|
||||
@Operation(summary = "取消升级任务")
|
||||
@Parameter(name = "id", description = "升级任务编号", required = true)
|
||||
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:cancel')")
|
||||
public CommonResult<Boolean> cancelUpgradeTask(@RequestParam("id") Long id) {
|
||||
upgradeTaskService.cancelUpgradeTask(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得升级任务分页")
|
||||
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:query')")
|
||||
public CommonResult<PageResult<IotOtaUpgradeTaskRespVO>> getUpgradeTaskPage(@Valid IotOtaUpgradeTaskPageReqVO pageReqVO) {
|
||||
PageResult<IotOtaUpgradeTaskDO> pageResult = upgradeTaskService.getUpgradeTaskPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotOtaUpgradeTaskRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得升级任务")
|
||||
@Parameter(name = "id", description = "升级任务编号", required = true, example = "1024")
|
||||
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:query')")
|
||||
public CommonResult<IotOtaUpgradeTaskRespVO> getUpgradeTask(@RequestParam("id") Long id) {
|
||||
IotOtaUpgradeTaskDO upgradeTask = upgradeTaskService.getUpgradeTask(id);
|
||||
return success(BeanUtils.toBean(upgradeTask, IotOtaUpgradeTaskRespVO.class));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.ota.vo.firmware;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Schema(description = "管理后台 - IoT OTA 固件创建 Request VO")
|
||||
@Data
|
||||
public class IotOtaFirmwareCreateReqVO {
|
||||
|
||||
@Schema(description = "固件名称", requiredMode = REQUIRED, example = "智能开关固件")
|
||||
@NotEmpty(message = "固件名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "固件描述", example = "某品牌型号固件,测试用")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "版本号", requiredMode = REQUIRED, example = "1.0.0")
|
||||
@NotEmpty(message = "版本号不能为空")
|
||||
private String version;
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = REQUIRED, example = "1024")
|
||||
@NotNull(message = "产品编号不能为空")
|
||||
private String productId;
|
||||
|
||||
@Schema(description = "签名方式", example = "MD5")
|
||||
// TODO @li:是不是必传哈
|
||||
private String signMethod;
|
||||
|
||||
@Schema(description = "固件文件 URL", requiredMode = REQUIRED, example = "https://www.iocoder.cn/yudao-firmware.zip")
|
||||
@NotEmpty(message = "固件文件 URL 不能为空")
|
||||
private String fileUrl;
|
||||
|
||||
@Schema(description = "自定义信息,建议使用 JSON 格式", example = "{\"key1\":\"value1\",\"key2\":\"value2\"}")
|
||||
private String information;
|
||||
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.ota.vo.firmware;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||
import com.fhs.core.trans.anno.Trans;
|
||||
import com.fhs.core.trans.constant.TransType;
|
||||
import com.fhs.core.trans.vo.VO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 固件 Response VO")
|
||||
public class IotOtaFirmwareRespVO implements VO {
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
*/
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
/**
|
||||
* 固件名称
|
||||
*/
|
||||
@Schema(description = "固件名称", requiredMode = REQUIRED, example = "OTA固件")
|
||||
private String name;
|
||||
/**
|
||||
* 固件描述
|
||||
*/
|
||||
@Schema(description = "固件描述")
|
||||
private String description;
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
@Schema(description = "版本号", requiredMode = REQUIRED, example = "1.0.0")
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 产品编号
|
||||
* <p>
|
||||
* 关联 {@link cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO#getId()}
|
||||
*/
|
||||
@Schema(description = "产品编号", requiredMode = REQUIRED, example = "1024")
|
||||
@Trans(type = TransType.SIMPLE, target = IotProductDO.class, fields = {"name"}, refs = {"productName"})
|
||||
private String productId;
|
||||
/**
|
||||
* 产品标识
|
||||
* <p>
|
||||
* 冗余 {@link cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO#getProductKey()}
|
||||
*/
|
||||
@Schema(description = "产品标识", requiredMode = REQUIRED, example = "iot-product-key")
|
||||
private String productKey;
|
||||
/**
|
||||
* 产品名称
|
||||
*/
|
||||
@Schema(description = "产品名称", requiredMode = REQUIRED, example = "OTA产品")
|
||||
private String productName;
|
||||
/**
|
||||
* 签名方式
|
||||
* <p>
|
||||
* 例如说:MD5、SHA256
|
||||
*/
|
||||
@Schema(description = "签名方式", example = "MD5")
|
||||
private String signMethod;
|
||||
/**
|
||||
* 固件文件签名
|
||||
*/
|
||||
@Schema(description = "固件文件签名", example = "1024")
|
||||
private String fileSign;
|
||||
/**
|
||||
* 固件文件大小
|
||||
*/
|
||||
@Schema(description = "固件文件大小", requiredMode = REQUIRED, example = "1024")
|
||||
private Long fileSize;
|
||||
/**
|
||||
* 固件文件 URL
|
||||
*/
|
||||
@Schema(description = "固件文件 URL", requiredMode = REQUIRED, example = "https://www.iocoder.cn")
|
||||
private String fileUrl;
|
||||
/**
|
||||
* 自定义信息,建议使用 JSON 格式
|
||||
*/
|
||||
@Schema(description = "自定义信息,建议使用 JSON 格式")
|
||||
private String information;
|
||||
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.ota.vo.upgrade.record;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 升级记录分页 Request VO")
|
||||
public class IotOtaUpgradeRecordPageReqVO extends PageParam {
|
||||
|
||||
// TODO @li:已经有注解,不用重复注释
|
||||
/**
|
||||
* 升级任务编号字段。
|
||||
* <p>
|
||||
* 该字段用于标识升级任务的唯一编号,不能为空。
|
||||
*/
|
||||
@Schema(description = "升级任务编号", requiredMode = REQUIRED, example = "1024")
|
||||
@NotNull(message = "升级任务编号不能为空")
|
||||
private Long taskId;
|
||||
|
||||
/**
|
||||
* 设备标识字段。
|
||||
* <p>
|
||||
* 该字段用于标识设备的名称,通常用于区分不同的设备。
|
||||
*/
|
||||
@Schema(description = "设备标识", requiredMode = REQUIRED, example = "摄像头A1-1")
|
||||
private String deviceName;
|
||||
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.ota.vo.upgrade.record;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaUpgradeTaskDO;
|
||||
import com.fhs.core.trans.anno.Trans;
|
||||
import com.fhs.core.trans.constant.TransType;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 升级记录 Response VO")
|
||||
public class IotOtaUpgradeRecordRespVO {
|
||||
|
||||
/**
|
||||
* 升级记录编号
|
||||
*/
|
||||
@Schema(description = "升级记录编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
/**
|
||||
* 固件编号
|
||||
* <p>
|
||||
* 关联 {@link IotOtaFirmwareDO#getId()}
|
||||
*/
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
@Trans(type = TransType.SIMPLE, target = IotOtaFirmwareDO.class, fields = {"version"}, refs = {"firmwareVersion"})
|
||||
private Long firmwareId;
|
||||
/**
|
||||
* 固件版本
|
||||
*/
|
||||
@Schema(description = "固件版本", requiredMode = REQUIRED, example = "v1.0.0")
|
||||
private String firmwareVersion;
|
||||
/**
|
||||
* 任务编号
|
||||
* <p>
|
||||
* 关联 {@link IotOtaUpgradeTaskDO#getId()}
|
||||
*/
|
||||
@Schema(description = "任务编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long taskId;
|
||||
/**
|
||||
* 产品标识
|
||||
* <p>
|
||||
* 关联 {@link cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO#getId()}
|
||||
*/
|
||||
@Schema(description = "产品标识", requiredMode = REQUIRED, example = "iot")
|
||||
private String productKey;
|
||||
/**
|
||||
* 设备名称
|
||||
* <p>
|
||||
* 关联 {@link cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO#getId()}
|
||||
*/
|
||||
@Schema(description = "设备名称", requiredMode = REQUIRED, example = "iot")
|
||||
private String deviceName;
|
||||
/**
|
||||
* 设备编号
|
||||
* <p>
|
||||
* 关联 {@link cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO#getId()}
|
||||
*/
|
||||
@Schema(description = "设备编号", requiredMode = REQUIRED, example = "1024")
|
||||
private String deviceId;
|
||||
/**
|
||||
* 来源的固件编号
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getFirmwareId()}
|
||||
*/
|
||||
@Schema(description = "来源的固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
@Trans(type = TransType.SIMPLE, target = IotOtaFirmwareDO.class, fields = {"version"}, refs = {"fromFirmwareVersion"})
|
||||
private Long fromFirmwareId;
|
||||
/**
|
||||
* 来源的固件版本
|
||||
*/
|
||||
@Schema(description = "来源的固件版本", requiredMode = REQUIRED, example = "v1.0.0")
|
||||
private String fromFirmwareVersion;
|
||||
/**
|
||||
* 升级状态
|
||||
* <p>
|
||||
* 关联 {@link cn.iocoder.yudao.module.iot.enums.ota.IotOtaUpgradeRecordStatusEnum}
|
||||
*/
|
||||
@Schema(description = "升级状态", requiredMode = REQUIRED, allowableValues = {"0", "10", "20", "30", "40", "50"})
|
||||
private Integer status;
|
||||
/**
|
||||
* 升级进度,百分比
|
||||
*/
|
||||
@Schema(description = "升级进度,百分比", requiredMode = REQUIRED, example = "10")
|
||||
private Integer progress;
|
||||
/**
|
||||
* 升级进度描述
|
||||
* <p>
|
||||
* 注意,只记录设备最后一次的升级进度描述
|
||||
* 如果想看历史记录,可以查看 {@link cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO} 设备日志
|
||||
*/
|
||||
@Schema(description = "升级进度描述", requiredMode = REQUIRED, example = "10")
|
||||
private String description;
|
||||
/**
|
||||
* 升级开始时间
|
||||
*/
|
||||
@Schema(description = "升级开始时间", requiredMode = REQUIRED, example = "2022-07-08 07:30:00")
|
||||
private LocalDateTime startTime;
|
||||
/**
|
||||
* 升级结束时间
|
||||
*/
|
||||
@Schema(description = "升级结束时间", requiredMode = REQUIRED, example = "2022-07-08 07:30:00")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.ota.vo.upgrade.task;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 升级任务分页 Request VO")
|
||||
public class IotOtaUpgradeTaskPageReqVO extends PageParam {
|
||||
|
||||
/**
|
||||
* 任务名称字段,用于描述任务的名称
|
||||
*/
|
||||
@Schema(description = "任务名称", example = "升级任务")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 固件编号字段,用于唯一标识固件,不能为空
|
||||
*/
|
||||
@NotNull(message = "固件编号不能为空")
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long firmwareId;
|
||||
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.ota.vo.upgrade.task;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
|
||||
import com.fhs.core.trans.vo.VO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 升级任务 Response VO")
|
||||
public class IotOtaUpgradeTaskRespVO implements VO {
|
||||
|
||||
/**
|
||||
* 任务编号
|
||||
*/
|
||||
@Schema(description = "任务编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
@Schema(description = "任务名称", requiredMode = REQUIRED, example = "升级任务")
|
||||
private String name;
|
||||
/**
|
||||
* 任务描述
|
||||
*/
|
||||
@Schema(description = "任务描述", example = "升级任务")
|
||||
private String description;
|
||||
/**
|
||||
* 固件编号
|
||||
* <p>
|
||||
* 关联 {@link IotOtaFirmwareDO#getId()}
|
||||
*/
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long firmwareId;
|
||||
/**
|
||||
* 任务状态
|
||||
* <p>
|
||||
* 关联 {@link cn.iocoder.yudao.module.iot.enums.ota.IotOtaUpgradeTaskStatusEnum}
|
||||
*/
|
||||
@Schema(description = "任务状态", requiredMode = REQUIRED, allowableValues = {"10", "20", "21", "30"})
|
||||
private Integer status;
|
||||
/**
|
||||
* 任务状态名称
|
||||
*/
|
||||
@Schema(description = "任务状态名称", requiredMode = REQUIRED, example = "进行中")
|
||||
private String statusName;
|
||||
/**
|
||||
* 升级范围
|
||||
* <p>
|
||||
* 关联 {@link cn.iocoder.yudao.module.iot.enums.ota.IotOtaUpgradeTaskScopeEnum}
|
||||
*/
|
||||
@Schema(description = "升级范围", requiredMode = REQUIRED, allowableValues = {"1", "2"})
|
||||
private Integer scope;
|
||||
/**
|
||||
* 设备数量
|
||||
*/
|
||||
@Schema(description = "设备数量", requiredMode = REQUIRED, example = "1024")
|
||||
private Long deviceCount;
|
||||
/**
|
||||
* 选中的设备编号数组
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getId()}
|
||||
*/
|
||||
@Schema(description = "选中的设备编号数组", example = "1024")
|
||||
private List<Long> deviceIds;
|
||||
/**
|
||||
* 选中的设备名字数组
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getDeviceName()}
|
||||
*/
|
||||
@Schema(description = "选中的设备名字数组", example = "1024")
|
||||
private List<String> deviceNames;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description = "创建时间", requiredMode = REQUIRED, example = "2022-07-08 07:30:00")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.ota.vo.upgrade.task;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.ota.IotOtaUpgradeTaskScopeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
|
||||
|
||||
@Data
|
||||
@Schema(description = "管理后台 - IoT OTA 升级任务创建/修改 Request VO")
|
||||
public class IotOtaUpgradeTaskSaveReqVO {
|
||||
|
||||
// TODO @li:已经有注解,不用重复注释
|
||||
// TODO @li: @Schema 写在参数校验前面。先有定义;其他的,也检查下;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
@NotEmpty(message = "任务名称不能为空")
|
||||
@Schema(description = "任务名称", requiredMode = REQUIRED, example = "升级任务")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 任务描述
|
||||
*/
|
||||
@Schema(description = "任务描述", example = "升级任务")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 固件编号
|
||||
* <p>
|
||||
* 关联 {@link IotOtaFirmwareDO#getId()}
|
||||
*/
|
||||
@NotNull(message = "固件编号不能为空")
|
||||
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
|
||||
private Long firmwareId;
|
||||
|
||||
/**
|
||||
* 升级范围
|
||||
* <p>
|
||||
* 关联 {@link cn.iocoder.yudao.module.iot.enums.ota.IotOtaUpgradeTaskScopeEnum}
|
||||
*/
|
||||
@NotNull(message = "升级范围不能为空")
|
||||
@InEnum(value = IotOtaUpgradeTaskScopeEnum.class)
|
||||
@Schema(description = "升级范围", requiredMode = REQUIRED, example = "1")
|
||||
private Integer scope;
|
||||
|
||||
/**
|
||||
* 选中的设备编号数组
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getId()}
|
||||
*/
|
||||
@Schema(description = "选中的设备编号数组", requiredMode = REQUIRED, example = "[1,2,3,4]")
|
||||
private List<Long> deviceIds;
|
||||
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.plugin;
|
||||
|
||||
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.plugin.vo.config.PluginConfigImportReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigPageReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigRespVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigSaveReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config.PluginConfigStatusReqVO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginConfigDO;
|
||||
import cn.iocoder.yudao.module.iot.service.plugin.IotPluginConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 插件配置")
|
||||
@RestController
|
||||
@RequestMapping("/iot/plugin-config")
|
||||
@Validated
|
||||
public class PluginConfigController {
|
||||
|
||||
@Resource
|
||||
private IotPluginConfigService pluginConfigService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建插件配置")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:create')")
|
||||
public CommonResult<Long> createPluginConfig(@Valid @RequestBody PluginConfigSaveReqVO createReqVO) {
|
||||
return success(pluginConfigService.createPluginConfig(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新插件配置")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:update')")
|
||||
public CommonResult<Boolean> updatePluginConfig(@Valid @RequestBody PluginConfigSaveReqVO updateReqVO) {
|
||||
pluginConfigService.updatePluginConfig(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除插件配置")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:delete')")
|
||||
public CommonResult<Boolean> deletePluginConfig(@RequestParam("id") Long id) {
|
||||
pluginConfigService.deletePluginConfig(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得插件配置")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:query')")
|
||||
public CommonResult<PluginConfigRespVO> getPluginConfig(@RequestParam("id") Long id) {
|
||||
IotPluginConfigDO pluginConfig = pluginConfigService.getPluginConfig(id);
|
||||
return success(BeanUtils.toBean(pluginConfig, PluginConfigRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得插件配置分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:query')")
|
||||
public CommonResult<PageResult<PluginConfigRespVO>> getPluginConfigPage(@Valid PluginConfigPageReqVO pageReqVO) {
|
||||
PageResult<IotPluginConfigDO> pageResult = pluginConfigService.getPluginConfigPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, PluginConfigRespVO.class));
|
||||
}
|
||||
|
||||
@PostMapping("/upload-file")
|
||||
@Operation(summary = "上传插件文件")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:update')")
|
||||
public CommonResult<Boolean> uploadFile(@Valid PluginConfigImportReqVO reqVO) {
|
||||
pluginConfigService.uploadFile(reqVO.getId(), reqVO.getFile());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/update-status")
|
||||
@Operation(summary = "修改插件状态")
|
||||
@PreAuthorize("@ss.hasPermission('iot:plugin-config:update')")
|
||||
public CommonResult<Boolean> updatePluginConfigStatus(@Valid @RequestBody PluginConfigStatusReqVO reqVO) {
|
||||
pluginConfigService.updatePluginStatus(reqVO.getId(), reqVO.getStatus());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 插件上传 Request VO")
|
||||
@Data
|
||||
public class PluginConfigImportReqVO {
|
||||
|
||||
@Schema(description = "主键 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "插件文件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "插件文件不能为空")
|
||||
private MultipartFile file;
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 插件配置分页 Request VO")
|
||||
@Data
|
||||
public class PluginConfigPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "插件名称", example = "http")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "状态", example = "1")
|
||||
@InEnum(IotPluginStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 插件配置 Response VO")
|
||||
@Data
|
||||
public class PluginConfigRespVO {
|
||||
|
||||
@Schema(description = "主键 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "插件包标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "24627")
|
||||
private String pluginKey;
|
||||
|
||||
@Schema(description = "插件名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述", example = "你猜")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "部署方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer deployType;
|
||||
|
||||
@Schema(description = "插件包文件名", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String fileName;
|
||||
|
||||
@Schema(description = "插件版本", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String version;
|
||||
|
||||
@Schema(description = "插件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "设备插件协议类型")
|
||||
private String protocol;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "插件配置项描述信息")
|
||||
private String configSchema;
|
||||
|
||||
@Schema(description = "插件配置信息")
|
||||
private String config;
|
||||
|
||||
@Schema(description = "插件脚本")
|
||||
private String script;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 插件配置新增/修改 Request VO")
|
||||
@Data
|
||||
public class PluginConfigSaveReqVO {
|
||||
|
||||
// TODO @haohao:新增的字段有点多,每个都需要哇?
|
||||
|
||||
// TODO @haohao:一些枚举字段,需要加枚举校验。例如说,deployType、status、type 等
|
||||
|
||||
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "插件包标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "24627")
|
||||
private String pluginKey;
|
||||
|
||||
@Schema(description = "插件名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "描述", example = "你猜")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "部署方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer deployType;
|
||||
|
||||
@Schema(description = "插件包文件名", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String fileName;
|
||||
|
||||
@Schema(description = "插件版本", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String version;
|
||||
|
||||
@Schema(description = "插件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "设备插件协议类型")
|
||||
private String protocol;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@InEnum(IotPluginStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "插件配置项描述信息")
|
||||
private String configSchema;
|
||||
|
||||
@Schema(description = "插件配置信息")
|
||||
private String config;
|
||||
|
||||
@Schema(description = "插件脚本")
|
||||
private String script;
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.plugin.IotPluginStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 插件配置状态 Request VO")
|
||||
@Data
|
||||
public class PluginConfigStatusReqVO {
|
||||
|
||||
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@InEnum(IotPluginStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.instance;
|
||||
|
||||
import lombok.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
// TODO @haohao:后续需要使用下
|
||||
@Schema(description = "管理后台 - IoT 插件实例分页 Request VO")
|
||||
@Data
|
||||
public class PluginInstancePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "插件主程序编号", example = "23738")
|
||||
private String mainId;
|
||||
|
||||
@Schema(description = "插件id", example = "26498")
|
||||
private Long pluginId;
|
||||
|
||||
@Schema(description = "插件主程序所在ip")
|
||||
private String ip;
|
||||
|
||||
@Schema(description = "插件主程序端口")
|
||||
private Integer port;
|
||||
|
||||
@Schema(description = "心跳时间,心路时间超过30秒需要剔除")
|
||||
private Long heartbeatAt;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.plugin.vo.instance;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
// TODO @haohao:后续需要使用下
|
||||
@Schema(description = "管理后台 - IoT 插件实例 Response VO")
|
||||
@Data
|
||||
public class PluginInstanceRespVO {
|
||||
|
||||
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23864")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "插件主程序id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23738")
|
||||
private String mainId;
|
||||
|
||||
@Schema(description = "插件id", requiredMode = Schema.RequiredMode.REQUIRED, example = "26498")
|
||||
private Long pluginId;
|
||||
|
||||
@Schema(description = "插件主程序所在ip", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String ip;
|
||||
|
||||
@Schema(description = "插件主程序端口", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer port;
|
||||
|
||||
@Schema(description = "心跳时间,心路时间超过30秒需要剔除", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long heartbeatAt;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.rule;
|
||||
|
||||
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.rule.vo.databridge.IotDataBridgePageReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.IotDataBridgeRespVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.IotDataBridgeSaveReqVO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
|
||||
import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 数据桥梁")
|
||||
@RestController
|
||||
@RequestMapping("/iot/data-bridge")
|
||||
@Validated
|
||||
public class IotDataBridgeController {
|
||||
|
||||
@Resource
|
||||
private IotDataBridgeService dataBridgeService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建数据桥梁")
|
||||
@PreAuthorize("@ss.hasPermission('iot:data-bridge:create')")
|
||||
public CommonResult<Long> createDataBridge(@Valid @RequestBody IotDataBridgeSaveReqVO createReqVO) {
|
||||
return success(dataBridgeService.createDataBridge(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新数据桥梁")
|
||||
@PreAuthorize("@ss.hasPermission('iot:data-bridge:update')")
|
||||
public CommonResult<Boolean> updateDataBridge(@Valid @RequestBody IotDataBridgeSaveReqVO updateReqVO) {
|
||||
dataBridgeService.updateDataBridge(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除数据桥梁")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('iot:data-bridge:delete')")
|
||||
public CommonResult<Boolean> deleteDataBridge(@RequestParam("id") Long id) {
|
||||
dataBridgeService.deleteDataBridge(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得数据桥梁")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('iot:data-bridge:query')")
|
||||
public CommonResult<IotDataBridgeRespVO> getDataBridge(@RequestParam("id") Long id) {
|
||||
IotDataBridgeDO dataBridge = dataBridgeService.getDataBridge(id);
|
||||
return success(BeanUtils.toBean(dataBridge, IotDataBridgeRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得数据桥梁分页")
|
||||
@PreAuthorize("@ss.hasPermission('iot:data-bridge:query')")
|
||||
public CommonResult<PageResult<IotDataBridgeRespVO>> getDataBridgePage(@Valid IotDataBridgePageReqVO pageReqVO) {
|
||||
PageResult<IotDataBridgeDO> pageResult = dataBridgeService.getDataBridgePage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, IotDataBridgeRespVO.class));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.rule;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.service.rule.IotRuleSceneService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
|
||||
@Tag(name = "管理后台 - IoT 规则场景")
|
||||
@RestController
|
||||
@RequestMapping("/iot/rule-scene")
|
||||
@Validated
|
||||
public class IotRuleSceneController {
|
||||
|
||||
@Resource
|
||||
private IotRuleSceneService ruleSceneService;
|
||||
|
||||
@GetMapping("/test")
|
||||
@PermitAll
|
||||
public void test() {
|
||||
ruleSceneService.test();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeAbstractConfig;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 数据桥梁 Response VO")
|
||||
@Data
|
||||
public class IotDataBridgeRespVO {
|
||||
|
||||
@Schema(description = "桥梁编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18564")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "桥梁名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "桥梁描述", example = "随便")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "桥梁状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "桥梁方向", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer direction;
|
||||
|
||||
@Schema(description = "桥梁类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "桥梁配置")
|
||||
private IotDataBridgeAbstractConfig config;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeAbstractConfig;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeDirectionEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 数据桥梁新增/修改 Request VO")
|
||||
@Data
|
||||
public class IotDataBridgeSaveReqVO {
|
||||
|
||||
@Schema(description = "桥梁编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18564")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "桥梁名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
|
||||
@NotEmpty(message = "桥梁名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "桥梁描述", example = "随便")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "桥梁状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "桥梁状态不能为空")
|
||||
@InEnum(CommonStatusEnum.class)
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "桥梁方向", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "桥梁方向不能为空")
|
||||
@InEnum(IotDataBridgeDirectionEnum.class)
|
||||
private Integer direction;
|
||||
|
||||
@Schema(description = "桥梁类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "桥梁类型不能为空")
|
||||
@InEnum(IotDataBridgeTypeEnum.class)
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "桥梁配置")
|
||||
@NotNull(message = "桥梁配置不能为空")
|
||||
private IotDataBridgeAbstractConfig config;
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* IoT IotDataBridgeConfig 抽象类
|
||||
*
|
||||
* 用于表示数据桥梁配置数据的通用类型,根据具体的 "type" 字段动态映射到对应的子类
|
||||
* 提供多态支持,适用于不同类型的数据结构序列化和反序列化场景。
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true)
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = IotDataBridgeHttpConfig.class, name = "1"),
|
||||
@JsonSubTypes.Type(value = IotDataBridgeMqttConfig.class, name = "10"),
|
||||
@JsonSubTypes.Type(value = IotDataBridgeRedisStreamMQConfig.class, name = "21"),
|
||||
@JsonSubTypes.Type(value = IotDataBridgeRocketMQConfig.class, name = "30"),
|
||||
@JsonSubTypes.Type(value = IotDataBridgeRabbitMQConfig.class, name = "31"),
|
||||
@JsonSubTypes.Type(value = IotDataBridgeKafkaMQConfig.class, name = "32"),
|
||||
})
|
||||
public abstract class IotDataBridgeAbstractConfig {
|
||||
|
||||
/**
|
||||
* 配置类型
|
||||
*
|
||||
* 枚举 {@link IotDataBridgeTypeEnum#getType()}
|
||||
*/
|
||||
private String type;
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
// TODO @puhui999:MQ 可以去掉哈。stream 更精准
|
||||
/**
|
||||
* IoT Redis Stream 配置 {@link IotDataBridgeAbstractConfig} 实现类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
public class IotDataBridgeRedisStreamMQConfig extends IotDataBridgeAbstractConfig {
|
||||
|
||||
/**
|
||||
* Redis 服务器地址
|
||||
*/
|
||||
private String host;
|
||||
/**
|
||||
* 端口
|
||||
*/
|
||||
private Integer port;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* 数据库索引
|
||||
*/
|
||||
private Integer database;
|
||||
|
||||
/**
|
||||
* 主题
|
||||
*/
|
||||
private String topic;
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
// TODO @芋艿:占位
|
||||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo;
|
|
@ -1,19 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 设备上下行消息数量统计 Response VO")
|
||||
@Data
|
||||
public class IotStatisticsDeviceMessageSummaryRespVO {
|
||||
|
||||
@Schema(description = "每小时上行数据数量统计")
|
||||
private List<Map<Long, Integer>> upstreamCounts;
|
||||
|
||||
@Schema(description = "每小时下行数据数量统计")
|
||||
private List<Map<Long, Integer>> downstreamCounts;
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - IoT 统计 Request VO")
|
||||
@Data
|
||||
public class IotStatisticsReqVO {
|
||||
|
||||
// TODO @super:前端传递的时候,还是通过 startTime 和 endTime 传递。后端转成 Long
|
||||
|
||||
@Schema(description = "查询起始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1658486600000")
|
||||
@NotNull(message = "查询起始时间不能为空")
|
||||
private Long startTime;
|
||||
|
||||
@Schema(description = "查询结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1758486600000")
|
||||
@NotNull(message = "查询结束时间不能为空")
|
||||
private Long endTime;
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* IoT 物模型数据类型为布尔型或枚举型的 DataSpec 定义
|
||||
*
|
||||
* 数据类型,取值为 bool 或 enum。
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
||||
public class ThingModelBoolOrEnumDataSpecs extends ThingModelDataSpecs {
|
||||
|
||||
// TODO @puhui999:要不写下参数校验?这样,注释可以简洁一点
|
||||
/**
|
||||
* 枚举项的名称。
|
||||
* 可包含中文、大小写英文字母、数字、下划线(_)和短划线(-)
|
||||
* 必须以中文、英文字母或数字开头,长度不超过 20 个字符
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 枚举值。
|
||||
*/
|
||||
private Integer value;
|
||||
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
### 请求 /iot/think-model-function/create 接口 => 成功
|
||||
POST {{baseUrl}}/iot/think-model-function/create
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"productId": 1001,
|
||||
"productKey": "smart-sensor-001",
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"description": "当前温度值",
|
||||
"type": 1,
|
||||
"property": {
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"accessMode": "r",
|
||||
"required": true,
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"min": -10.0,
|
||||
"max": 100.0,
|
||||
"step": 0.1,
|
||||
"unit": "℃"
|
||||
}
|
||||
},
|
||||
"description": "当前温度值"
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/think-model-function/create 接口 => 成功
|
||||
POST {{baseUrl}}/iot/think-model-function/create
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"productId": 1001,
|
||||
"productKey": "smart-sensor-001",
|
||||
"identifier": "Humidity",
|
||||
"name": "湿度",
|
||||
"description": "当前湿度值",
|
||||
"type": 1,
|
||||
"property": {
|
||||
"identifier": "Humidity",
|
||||
"name": "湿度",
|
||||
"accessMode": "r",
|
||||
"required": true,
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"min": 0.0,
|
||||
"max": 100.0,
|
||||
"step": 0.1,
|
||||
"unit": "%"
|
||||
}
|
||||
},
|
||||
"description": "当前湿度值"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
### 请求 /iot/think-model-function/update 接口 => 成功
|
||||
PUT {{baseUrl}}/iot/think-model-function/update
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 11,
|
||||
"productId": 1001,
|
||||
"productKey": "smart-sensor-001",
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"description": "当前温度值",
|
||||
"type": 1,
|
||||
"property": {
|
||||
"identifier": "Temperature",
|
||||
"name": "温度",
|
||||
"accessMode": "r",
|
||||
"required": true,
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"min": -111.0,
|
||||
"max": 222.0,
|
||||
"step": 0.1,
|
||||
"unit": "℃"
|
||||
}
|
||||
},
|
||||
"description": "当前温度值"
|
||||
}
|
||||
}
|
||||
|
||||
### 请求 /iot/think-model-function/delete 接口 => 成功
|
||||
DELETE {{baseUrl}}/iot/think-model-function/delete?id=7
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
### 请求 /iot/think-model-function/get 接口 => 成功
|
||||
GET {{baseUrl}}/iot/think-model-function/get?id=10
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
|
||||
### 请求 /iot/think-model-function/list-by-product-id 接口 => 成功
|
||||
GET {{baseUrl}}/iot/think-model-function/list-by-product-id?productId=1001
|
||||
tenant-id: {{adminTenantId}}
|
||||
Authorization: Bearer {{token}}
|
|
@ -1,95 +0,0 @@
|
|||
package cn.iocoder.yudao.module.iot.dal.dataobject.device;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* IoT 设备日志数据 DO
|
||||
*
|
||||
* 目前使用 TDengine 存储
|
||||
*
|
||||
* @author alwayssuper
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class IotDeviceLogDO {
|
||||
|
||||
/**
|
||||
* 日志编号
|
||||
*
|
||||
* 通过 {@link IdUtil#fastSimpleUUID()} 生成
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 请求编号
|
||||
*
|
||||
* 对应 {@link IotDeviceMessage#getRequestId()} 字段
|
||||
*/
|
||||
private String requestId;
|
||||
|
||||
/**
|
||||
* 产品标识
|
||||
* <p>
|
||||
* 关联 {@link IotProductDO#getProductKey()}
|
||||
*/
|
||||
private String productKey;
|
||||
/**
|
||||
* 设备名称
|
||||
*
|
||||
* 关联 {@link IotDeviceDO#getDeviceName()}
|
||||
*/
|
||||
private String deviceName;
|
||||
/**
|
||||
* 设备标识
|
||||
* <p>
|
||||
* 关联 {@link IotDeviceDO#getDeviceKey()}}
|
||||
*/
|
||||
private String deviceKey; // 非存储字段,用于 TDengine 的 TAG
|
||||
|
||||
/**
|
||||
* 日志类型
|
||||
*
|
||||
* 枚举 {@link IotDeviceMessageTypeEnum}
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 标识符
|
||||
*
|
||||
* 枚举 {@link IotDeviceMessageIdentifierEnum}
|
||||
*/
|
||||
private String identifier;
|
||||
|
||||
/**
|
||||
* 数据内容
|
||||
*
|
||||
* 存储具体的消息数据内容,通常是 JSON 格式
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 响应码
|
||||
*
|
||||
* 目前只有 server 下行消息给 device 设备时,才会有响应码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 上报时间戳
|
||||
*/
|
||||
private Long reportTime;
|
||||
|
||||
/**
|
||||
* 时序时间
|
||||
*/
|
||||
private Long ts;
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue