reactor:【IoT 物联网】清理 yudao-module-iot-api
This commit is contained in:
@@ -1,14 +1,21 @@
|
||||
package cn.iocoder.yudao.module.iot.dal.dataobject.rule;
|
||||
package cn.iocoder.yudao.module.iot.dal.dataobject.alert;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotAlertConfigReceiveTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
|
||||
import cn.iocoder.yudao.module.iot.enums.DictTypeConstants;
|
||||
import cn.iocoder.yudao.module.iot.enums.alert.IotAlertConfigReceiveTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -41,37 +48,37 @@ public class IotAlertConfigDO extends BaseDO {
|
||||
/**
|
||||
* 配置状态
|
||||
*
|
||||
* TODO 数据字典
|
||||
* 字典 {@link DictTypeConstants#ALERT_LEVEL}
|
||||
*/
|
||||
private Integer level;
|
||||
/**
|
||||
* 配置状态
|
||||
*
|
||||
* 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 关联的规则场景编号数组
|
||||
* 关联的场景联动规则编号数组
|
||||
*
|
||||
* 关联 {@link IotRuleSceneDO#getId()}
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<Long> ruleSceneIds;
|
||||
@TableField(typeHandler = LongListTypeHandler.class)
|
||||
private List<Long> sceneRuleIds;
|
||||
|
||||
/**
|
||||
* 接收的用户编号数组
|
||||
*
|
||||
* 关联 {@link AdminUserRespDTO#getId()}
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
@TableField(typeHandler = LongListTypeHandler.class)
|
||||
private List<Long> receiveUserIds;
|
||||
/**
|
||||
* 接收的类型数组
|
||||
*
|
||||
* 枚举 {@link IotAlertConfigReceiveTypeEnum}
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
@TableField(typeHandler = IntegerListTypeHandler.class)
|
||||
private List<Integer> receiveTypes;
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.module.iot.dal.dataobject.rule;
|
||||
package cn.iocoder.yudao.module.iot.dal.dataobject.alert;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
@@ -45,17 +45,17 @@ public class IotAlertRecordDO extends BaseDO {
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 产品标识
|
||||
* 产品编号
|
||||
*
|
||||
* 关联 {@link IotProductDO#getProductKey()} ()}
|
||||
* 关联 {@link IotProductDO#getId()}
|
||||
*/
|
||||
private String productKey;
|
||||
private Long productId;
|
||||
/**
|
||||
* 设备名称
|
||||
* 设备编号
|
||||
*
|
||||
* 冗余 {@link IotDeviceDO#getDeviceName()}
|
||||
* 关联 {@link IotDeviceDO#getId()}
|
||||
*/
|
||||
private String deviceName;
|
||||
private String deviceId;
|
||||
|
||||
// TODO @芋艿:有没更好的方式
|
||||
/**
|
||||
@@ -64,7 +64,6 @@ public class IotAlertRecordDO extends BaseDO {
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private IotDeviceMessage deviceMessage;
|
||||
|
||||
// TODO @芋艿:换成枚举,枚举对应 ApiErrorLogProcessStatusEnum
|
||||
/**
|
||||
* 处理状态
|
||||
*
|
||||
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.rule;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.yudao.module.iot.enums;
|
||||
|
||||
/**
|
||||
* IoT 字典类型的枚举类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class DictTypeConstants {
|
||||
|
||||
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 CODEC_TYPE = "iot_codec_type";
|
||||
|
||||
public static final String DEVICE_STATE = "iot_device_state";
|
||||
|
||||
public static final String ALERT_LEVEL = "iot_alert_level";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package cn.iocoder.yudao.module.iot.enums;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
|
||||
/**
|
||||
* iot 错误码枚举类
|
||||
* <p>
|
||||
* iot 系统,使用 1-050-000-000 段
|
||||
*/
|
||||
public interface ErrorCodeConstants {
|
||||
|
||||
// ========== 产品相关 1-050-001-000 ============
|
||||
ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在");
|
||||
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, "产品状是发布状态,不允许操作物模型");
|
||||
|
||||
// ========== 产品物模型 1-050-002-000 ============
|
||||
ErrorCode THING_MODEL_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在");
|
||||
ErrorCode THING_MODEL_EXISTS_BY_PRODUCT_KEY = new ErrorCode(1_050_002_001, "ProductKey 对应的产品物模型已存在");
|
||||
ErrorCode THING_MODEL_IDENTIFIER_EXISTS = new ErrorCode(1_050_002_002, "存在重复的功能标识符。");
|
||||
ErrorCode THING_MODEL_NAME_EXISTS = new ErrorCode(1_050_002_003, "存在重复的功能名称。");
|
||||
ErrorCode THING_MODEL_IDENTIFIER_INVALID = new ErrorCode(1_050_002_003, "产品物模型标识无效");
|
||||
|
||||
// ========== 设备 1-050-003-000 ============
|
||||
ErrorCode DEVICE_NOT_EXISTS = new ErrorCode(1_050_003_000, "设备不存在");
|
||||
ErrorCode DEVICE_NAME_EXISTS = new ErrorCode(1_050_003_001, "设备名称在同一产品下必须唯一");
|
||||
ErrorCode DEVICE_HAS_CHILDREN = new ErrorCode(1_050_003_002, "有子设备,不允许删除");
|
||||
ErrorCode DEVICE_KEY_EXISTS = new ErrorCode(1_050_003_003, "设备标识已经存在");
|
||||
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_SERVER_ID_NULL = new ErrorCode(1_050_003_007, "下行设备消息失败,原因:设备未连接网关");
|
||||
|
||||
// ========== 产品分类 1-050-004-000 ==========
|
||||
ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_004_000, "产品分类不存在");
|
||||
|
||||
// ========== 设备分组 1-050-005-000 ==========
|
||||
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-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, "升级任务不能取消");
|
||||
|
||||
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, "升级记录不能重试");
|
||||
|
||||
// ========== 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, "场景联动不存在");
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.iot.enums.alert;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 告警配置的接收方式枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotAlertConfigReceiveTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
SMS(1), // 短信
|
||||
MAIL(2), // 邮箱
|
||||
NOTIFY(3); // 通知
|
||||
|
||||
private final Integer type;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotAlertConfigReceiveTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cn.iocoder.yudao.module.iot.enums.device;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
// TODO @芋艿:需要添加对应的 DTO,以及上下行的链路,网关、网关服务、设备等
|
||||
/**
|
||||
* IoT 设备消息标识符枚举
|
||||
*/
|
||||
@Deprecated
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum IotDeviceMessageIdentifierEnum {
|
||||
|
||||
PROPERTY_GET("get"), // 下行
|
||||
PROPERTY_SET("set"), // 下行
|
||||
PROPERTY_REPORT("report"), // 上行
|
||||
|
||||
STATE_ONLINE("online"), // 上行
|
||||
STATE_OFFLINE("offline"), // 上行
|
||||
|
||||
CONFIG_GET("get"), // 上行 TODO 芋艿:【讨论】暂时没有上行的场景
|
||||
CONFIG_SET("set"), // 下行
|
||||
|
||||
SERVICE_INVOKE("${identifier}"), // 下行
|
||||
SERVICE_REPLY_SUFFIX("_reply"), // 芋艿:TODO 芋艿:【讨论】上行 or 下行
|
||||
|
||||
OTA_UPGRADE("upgrade"), // 下行
|
||||
OTA_PULL("pull"), // 上行
|
||||
OTA_PROGRESS("progress"), // 上行
|
||||
OTA_REPORT("report"), // 上行
|
||||
|
||||
REGISTER_REGISTER("register"), // 上行
|
||||
REGISTER_REGISTER_SUB("register_sub"), // 上行
|
||||
REGISTER_UNREGISTER_SUB("unregister_sub"), // 下行
|
||||
|
||||
TOPOLOGY_ADD("topology_add"), // 下行;
|
||||
;
|
||||
|
||||
/**
|
||||
* 标志符
|
||||
*/
|
||||
private final String identifier;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.iot.enums.device;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 设备消息类型枚举
|
||||
*/
|
||||
@Deprecated
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum IotDeviceMessageTypeEnum implements ArrayValuable<String> {
|
||||
|
||||
STATE("state"), // 设备状态
|
||||
PROPERTY("property"), // 设备属性:可参考 https://help.aliyun.com/zh/iot/user-guide/device-properties-events-and-services 设备属性、事件、服务
|
||||
EVENT("event"), // 设备事件:可参考 https://help.aliyun.com/zh/iot/user-guide/device-properties-events-and-services 设备属性、事件、服务
|
||||
SERVICE("service"), // 设备服务:可参考 https://help.aliyun.com/zh/iot/user-guide/device-properties-events-and-services 设备属性、事件、服务
|
||||
CONFIG("config"), // 设备配置:可参考 https://help.aliyun.com/zh/iot/user-guide/remote-configuration-1 远程配置
|
||||
OTA("ota"), // 设备 OTA:可参考 https://help.aliyun.com/zh/iot/user-guide/ota-update OTA 升级
|
||||
REGISTER("register"), // 设备注册:可参考 https://help.aliyun.com/zh/iot/user-guide/register-devices 设备身份注册
|
||||
TOPOLOGY("topology"),; // 设备拓扑:可参考 https://help.aliyun.com/zh/iot/user-guide/manage-topological-relationships 设备拓扑
|
||||
|
||||
public static final String[] ARRAYS = Arrays.stream(values()).map(IotDeviceMessageTypeEnum::getType).toArray(String[]::new);
|
||||
|
||||
/**
|
||||
* 属性
|
||||
*/
|
||||
private final String type;
|
||||
|
||||
@Override
|
||||
public String[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
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 IotOtaUpgradeRecordStatusEnum implements ArrayValuable<Integer> {
|
||||
|
||||
PENDING(0), // 待推送
|
||||
PUSHED(10), // 已推送
|
||||
UPGRADING(20), // 升级中
|
||||
SUCCESS(30), // 升级成功
|
||||
FAILURE(40), // 升级失败
|
||||
CANCELED(50),; // 已取消
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotOtaUpgradeRecordStatusEnum::getStatus).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 范围
|
||||
*/
|
||||
private final Integer status;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
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 IotOtaUpgradeTaskScopeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
ALL(1), // 全部设备:只包括当前产品下的设备,不包括未来创建的设备
|
||||
SELECT(2); // 指定设备
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotOtaUpgradeTaskScopeEnum::getScope).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 范围
|
||||
*/
|
||||
private final Integer scope;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
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 IotNetTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
WIFI(0, "Wi-Fi"),
|
||||
CELLULAR(1, "Cellular"),
|
||||
ETHERNET(2, "Ethernet"),
|
||||
OTHER(3, "其他");
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotNetTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
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 IotProductDeviceTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
DIRECT(0, "直连设备"),
|
||||
GATEWAY_SUB(1, "网关子设备"),
|
||||
GATEWAY(2, "网关设备");
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotProductDeviceTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是网关
|
||||
*
|
||||
* @param type 类型
|
||||
* @return 是否是网关
|
||||
*/
|
||||
public static boolean isGateway(Integer type) {
|
||||
return GATEWAY.getType().equals(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是网关子设备
|
||||
*
|
||||
* @param type 类型
|
||||
* @return 是否是网关子设备
|
||||
*/
|
||||
public static boolean isGatewaySub(Integer type) {
|
||||
return GATEWAY_SUB.getType().equals(type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
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 IotProductStatusEnum implements ArrayValuable<Integer> {
|
||||
|
||||
UNPUBLISHED(0, "开发中"),
|
||||
PUBLISHED(1, "已发布");
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotProductStatusEnum::getStatus).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer status;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
@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_STREAM(21, "Redis Stream"), // TODO @puhui999:改成 Redis;然后枚举不同的数据结构?这样,枚举就可以是 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
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 IotRuleSceneActionTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
// TODO @芋艿:后续“对应”部分,要 @下,等包结构梳理完;
|
||||
/**
|
||||
* 设备属性设置
|
||||
*
|
||||
* 对应 IotDeviceMessageMethodEnum.DEVICE_PROPERTY_SET
|
||||
*/
|
||||
DEVICE_PROPERTY_SET(1),
|
||||
/**
|
||||
* 设备服务调用
|
||||
*
|
||||
* 对应 IotDeviceMessageMethodEnum.DEVICE_SERVICE_INVOKE
|
||||
*/
|
||||
DEVICE_SERVICE_INVOKE(2),
|
||||
|
||||
/**
|
||||
* 告警触发
|
||||
*/
|
||||
ALERT_TRIGGER(100),
|
||||
/**
|
||||
* 告警恢复
|
||||
*/
|
||||
ALERT_RECOVER(101),
|
||||
|
||||
@Deprecated
|
||||
ALERT(2), // 告警执行
|
||||
;
|
||||
|
||||
private final Integer type;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneActionTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
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 IotRuleSceneConditionOperatorEnum implements ArrayValuable<String> {
|
||||
|
||||
EQUALS("=", "#source == #value"),
|
||||
NOT_EQUALS("!=", "!(#source == #value)"),
|
||||
|
||||
GREATER_THAN(">", "#source > #value"),
|
||||
GREATER_THAN_OR_EQUALS(">=", "#source >= #value"),
|
||||
|
||||
LESS_THAN("<", "#source < #value"),
|
||||
LESS_THAN_OR_EQUALS("<=", "#source <= #value"),
|
||||
|
||||
IN("in", "#values.contains(#source)"),
|
||||
NOT_IN("not in", "!(#values.contains(#source))"),
|
||||
|
||||
BETWEEN("between", "(#source >= #values.get(0)) && (#source <= #values.get(1))"),
|
||||
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"), // 非空
|
||||
|
||||
// ========== 特殊:不放在字典里 ==========
|
||||
|
||||
// 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(IotRuleSceneConditionOperatorEnum::getOperator).toArray(String[]::new);
|
||||
|
||||
/**
|
||||
* Spring 表达式 - 原始值
|
||||
*/
|
||||
public static final String SPRING_EXPRESSION_SOURCE = "source";
|
||||
/**
|
||||
* Spring 表达式 - 目标值
|
||||
*/
|
||||
public static final String SPRING_EXPRESSION_VALUE = "value";
|
||||
/**
|
||||
* Spring 表达式 - 目标值数组
|
||||
*/
|
||||
public static final String SPRING_EXPRESSION_VALUE_LIST = "values";
|
||||
|
||||
public static IotRuleSceneConditionOperatorEnum operatorOf(String operator) {
|
||||
return ArrayUtil.firstMatch(item -> item.getOperator().equals(operator), values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
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 IotRuleSceneConditionTypeEnum 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(IotRuleSceneConditionTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
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 场景流转的触发类型枚举
|
||||
*
|
||||
* 为什么不直接使用 IotDeviceMessageMethodEnum 呢?
|
||||
* 原因是,物模型属性上报,存在批量上报的情况,不只对应一个 method!!!
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum IotRuleSceneTriggerTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
@Deprecated
|
||||
DEVICE(1), // 设备触发 // TODO @puhui999:@芋艿:这个可以作废
|
||||
|
||||
// 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(IotRuleSceneTriggerTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.iocoder.yudao.module.iot.enums.thingmodel;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 数据定义的数据类型枚举类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum IotDataSpecsDataTypeEnum implements ArrayValuable<String> {
|
||||
|
||||
INT("int"),
|
||||
FLOAT("float"),
|
||||
DOUBLE("double"),
|
||||
ENUM("enum"),
|
||||
BOOL("bool"),
|
||||
TEXT("text"),
|
||||
DATE("date"),
|
||||
STRUCT("struct"),
|
||||
ARRAY("array");
|
||||
|
||||
public static final String[] ARRAYS = Arrays.stream(values()).map(IotDataSpecsDataTypeEnum::getDataType).toArray(String[]::new);
|
||||
|
||||
private final String dataType;
|
||||
|
||||
@Override
|
||||
public String[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.iot.enums.thingmodel;
|
||||
|
||||
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 IotThingModelAccessModeEnum implements ArrayValuable<String> {
|
||||
|
||||
READ_ONLY("r"),
|
||||
READ_WRITE("rw");
|
||||
|
||||
public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelAccessModeEnum::getMode).toArray(String[]::new);
|
||||
|
||||
private final String mode;
|
||||
|
||||
@Override
|
||||
public String[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.iot.enums.thingmodel;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* IoT 产品物模型参数是输入参数还是输出参数枚举
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum IotThingModelParamDirectionEnum implements ArrayValuable<String> {
|
||||
|
||||
INPUT("input"), // 输入参数
|
||||
OUTPUT("output"); // 输出参数
|
||||
|
||||
public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelParamDirectionEnum::getDirection).toArray(String[]::new);
|
||||
|
||||
private final String direction;
|
||||
|
||||
@Override
|
||||
public String[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.iot.enums.thingmodel;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 产品物模型服务调用方式枚举
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum IotThingModelServiceCallTypeEnum implements ArrayValuable<String> {
|
||||
|
||||
ASYNC("async"), // 异步调用
|
||||
SYNC("sync"); // 同步调用
|
||||
|
||||
public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelServiceCallTypeEnum::getType).toArray(String[]::new);
|
||||
|
||||
private final String type;
|
||||
|
||||
@Override
|
||||
public String[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.iot.enums.thingmodel;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* IoT 产品物模型事件类型枚举
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum IotThingModelServiceEventTypeEnum implements ArrayValuable<String> {
|
||||
|
||||
INFO("info"), // 信息
|
||||
ALERT("alert"), // 告警
|
||||
ERROR("error"); // 故障
|
||||
|
||||
public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelServiceEventTypeEnum::getType).toArray(String[]::new);
|
||||
|
||||
private final String type;
|
||||
|
||||
@Override
|
||||
public String[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.yudao.module.iot.enums.thingmodel;
|
||||
|
||||
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 IotThingModelTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
PROPERTY(1, "属性"),
|
||||
SERVICE(2, "服务"),
|
||||
EVENT(3, "事件");
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotThingModelTypeEnum::getType).toArray(Integer[]::new);
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
@Override
|
||||
public Integer[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package cn.iocoder.yudao.module.iot.mq.consumer.device;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
|
||||
@@ -19,6 +18,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 针对 {@link IotDeviceMessage} 的业务处理器:调用 method 对应的逻辑。例如说:
|
||||
@@ -83,15 +83,14 @@ public class IotDeviceMessageSubscriber implements IotMessageSubscriber<IotDevic
|
||||
return;
|
||||
}
|
||||
// 如果是 STATE 相关的消息,无需处理,不然就重复处理状态了
|
||||
if (ObjectUtils.equalsAny(message.getMethod(), IotDeviceMessageMethodEnum.STATE_ONLINE.getMethod(),
|
||||
IotDeviceMessageMethodEnum.STATE_OFFLINE.getMethod())) {
|
||||
if (Objects.equals(message.getMethod(), IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 特殊:设备非在线时,主动标记设备为在线
|
||||
// 为什么不直接更新状态呢?因为通过 IotDeviceMessage 可以经过一系列的处理,例如说记录日志、规则引擎等等
|
||||
try {
|
||||
deviceMessageService.sendDeviceMessage(IotDeviceMessage.buildStateOnline().setDeviceId(device.getId()));
|
||||
deviceMessageService.sendDeviceMessage(IotDeviceMessage.buildStateUpdateOnline().setDeviceId(device.getId()));
|
||||
} catch (Exception e) {
|
||||
// 注意:即使执行失败,也不影响主流程
|
||||
log.error("[forceDeviceOnline][message({}) device({}) 强制设备上线失败]", message, device, e);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.iot.service.device.message;
|
||||
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
@@ -13,7 +14,6 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceM
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryByDateRespVO;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
|
||||
import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
|
||||
@@ -176,15 +176,12 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService {
|
||||
// TODO @芋艿:可优化:未来逻辑复杂后,可以独立拆除 Processor 处理器
|
||||
@SuppressWarnings("SameReturnValue")
|
||||
private Object handleUpstreamDeviceMessage0(IotDeviceMessage message, IotDeviceDO device) {
|
||||
// 设备上线
|
||||
if (Objects.equal(message.getMethod(), IotDeviceMessageMethodEnum.STATE_ONLINE.getMethod())) {
|
||||
deviceService.updateDeviceState(device, IotDeviceStateEnum.ONLINE.getState());
|
||||
// TODO 芋艿:子设备的关联
|
||||
return null;
|
||||
}
|
||||
// 设备下线
|
||||
if (Objects.equal(message.getMethod(), IotDeviceMessageMethodEnum.STATE_OFFLINE.getMethod())) {
|
||||
deviceService.updateDeviceState(device, IotDeviceStateEnum.OFFLINE.getState());
|
||||
// 设备上下线
|
||||
if (Objects.equal(message.getMethod(), IotDeviceMessageMethodEnum.STATE_UPDATE.getMethod())) {
|
||||
String stateStr = IotDeviceMessageUtils.getIdentifier(message);
|
||||
assert stateStr != null;
|
||||
Assert.notEmpty(stateStr, "设备状态不能为空");
|
||||
deviceService.updateDeviceState(device, Integer.valueOf(stateStr));
|
||||
// TODO 芋艿:子设备的关联
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ public class IotDataRuleServiceImpl implements IotDataRuleService {
|
||||
for (IotDataRuleDO rule : rules) {
|
||||
IotDataRuleDO.SourceConfig found = CollUtil.findOne(rule.getSourceConfigs(),
|
||||
config -> ObjectUtils.equalsAny(config.getDeviceId(), deviceId, IotDeviceDO.DEVICE_ID_ALL)
|
||||
&& (StrUtil.isNotEmpty(config.getMethod()) || ObjUtil.equal(config.getMethod(), method))
|
||||
&& Objects.equals(config.getMethod(), method)
|
||||
&& (StrUtil.isEmpty(config.getIdentifier()) || ObjUtil.equal(config.getIdentifier(), identifier)));
|
||||
if (found != null) {
|
||||
matchedRules.add(new IotDataRuleDO().setId(rule.getId()).setSinkIds(rule.getSinkIds()));
|
||||
|
||||
@@ -18,6 +18,8 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
||||
|
||||
/**
|
||||
* HTTP 的 {@link IotDataRuleAction} 实现类
|
||||
*
|
||||
@@ -36,6 +38,7 @@ public class IotHttpDataSinkAction implements IotDataRuleAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void execute(IotDeviceMessage message, IotDataSinkDO dataSink) {
|
||||
IotDataSinkHttpConfig config = (IotDataSinkHttpConfig) dataSink.getConfig();
|
||||
Assert.notNull(config, "配置({})不能为空", dataSink.getId());
|
||||
@@ -49,8 +52,7 @@ public class IotHttpDataSinkAction implements IotDataRuleAction {
|
||||
if (CollUtil.isNotEmpty(config.getHeaders())) {
|
||||
config.getHeaders().putAll(config.getHeaders());
|
||||
}
|
||||
// TODO @puhui999:@yunai:可能需要通过设备查询到租户,然后 set
|
||||
// headers.add(HEADER_TENANT_ID, message.getTenantId().toString());
|
||||
headers.add(HEADER_TENANT_ID, message.getTenantId().toString());
|
||||
// 1.2 构建 URL
|
||||
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(config.getUrl());
|
||||
if (CollUtil.isNotEmpty(config.getQuery())) {
|
||||
@@ -72,18 +74,17 @@ public class IotHttpDataSinkAction implements IotDataRuleAction {
|
||||
requestEntity = new HttpEntity<>(JsonUtils.toJsonString(requestBody), headers);
|
||||
}
|
||||
|
||||
// 2.1 发送请求
|
||||
// 2. 发送请求
|
||||
responseEntity = restTemplate.exchange(url, method, requestEntity, String.class);
|
||||
// 2.2 记录日志
|
||||
if (responseEntity.getStatusCode().is2xxSuccessful()) {
|
||||
log.info("[executeHttp][message({}) config({}) url({}) method({}) requestEntity({}) 请求成功({})]",
|
||||
log.info("[execute][message({}) config({}) url({}) method({}) requestEntity({}) 请求成功({})]",
|
||||
message, config, url, method, requestEntity, responseEntity);
|
||||
} else {
|
||||
log.error("[executeHttp][message({}) config({}) url({}) method({}) requestEntity({}) 请求失败({})]",
|
||||
log.error("[execute][message({}) config({}) url({}) method({}) requestEntity({}) 请求失败({})]",
|
||||
message, config, url, method, requestEntity, responseEntity);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[executeHttp][message({}) config({}) url({}) method({}) requestEntity({}) 请求异常({})]",
|
||||
log.error("[execute][message({}) config({}) url({}) method({}) requestEntity({}) 请求异常({})]",
|
||||
message, config, url, method, requestEntity, responseEntity, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.data.action;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.config.IotDataSinkKafkaConfig;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotDataSinkTypeEnum;
|
||||
@@ -9,6 +10,7 @@ import org.apache.kafka.common.serialization.StringSerializer;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
|
||||
import org.springframework.kafka.core.KafkaTemplate;
|
||||
import org.springframework.kafka.support.SendResult;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
@@ -36,13 +38,27 @@ public class IotKafkaDataRuleAction extends
|
||||
|
||||
@Override
|
||||
public void execute(IotDeviceMessage message, IotDataSinkKafkaConfig config) throws Exception {
|
||||
// 1. 获取或创建 KafkaTemplate
|
||||
KafkaTemplate<String, String> kafkaTemplate = getProducer(config);
|
||||
try {
|
||||
// 1. 获取或创建 KafkaTemplate
|
||||
KafkaTemplate<String, String> kafkaTemplate = getProducer(config);
|
||||
|
||||
// 2. 发送消息并等待结果
|
||||
kafkaTemplate.send(config.getTopic(), message.toString())
|
||||
.get(SEND_TIMEOUT.getSeconds(), TimeUnit.SECONDS); // 添加超时等待
|
||||
log.info("[execute0][message({}) 发送成功]", message);
|
||||
// 2. 发送消息并等待结果
|
||||
SendResult<String, String> sendResult = kafkaTemplate.send(config.getTopic(), JsonUtils.toJsonString(message))
|
||||
.get(SEND_TIMEOUT.getSeconds(), TimeUnit.SECONDS);
|
||||
// 3. 处理发送结果
|
||||
if (sendResult != null && sendResult.getRecordMetadata() != null) {
|
||||
log.info("[execute][message({}) config({}) 发送成功,结果: partition={}, offset={}, timestamp={}]",
|
||||
message, config,
|
||||
sendResult.getRecordMetadata().partition(),
|
||||
sendResult.getRecordMetadata().offset(),
|
||||
sendResult.getRecordMetadata().timestamp());
|
||||
} else {
|
||||
log.warn("[execute][message({}) config({}) 发送结果为空]", message, config);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[execute][message({}) config({}) 发送失败]", message, config, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.data.action;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.config.IotDataSinkRabbitMQConfig;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.config.IotDataSinkRabbitMQConfig;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotDataSinkTypeEnum;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import com.rabbitmq.client.Connection;
|
||||
@@ -10,8 +11,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* RabbitMQ 的 {@link IotDataRuleAction} 实现类
|
||||
*
|
||||
@@ -20,8 +19,8 @@ import java.nio.charset.StandardCharsets;
|
||||
@ConditionalOnClass(name = "com.rabbitmq.client.Channel")
|
||||
@Component
|
||||
@Slf4j
|
||||
public class IotRabbitMQDataRuleAction extends
|
||||
IotDataRuleCacheableAction<IotDataSinkRabbitMQConfig, Channel> {
|
||||
public class IotRabbitMQDataRuleAction
|
||||
extends IotDataRuleCacheableAction<IotDataSinkRabbitMQConfig, Channel> {
|
||||
|
||||
@Override
|
||||
public Integer getType() {
|
||||
@@ -30,17 +29,22 @@ public class IotRabbitMQDataRuleAction extends
|
||||
|
||||
@Override
|
||||
public void execute(IotDeviceMessage message, IotDataSinkRabbitMQConfig config) throws Exception {
|
||||
// 1.1 获取或创建 Channel
|
||||
Channel channel = getProducer(config);
|
||||
// 1.2 声明交换机、队列和绑定关系
|
||||
channel.exchangeDeclare(config.getExchange(), "direct", true);
|
||||
channel.queueDeclare(config.getQueue(), true, false, false, null);
|
||||
channel.queueBind(config.getQueue(), config.getExchange(), config.getRoutingKey());
|
||||
try {
|
||||
// 1.1 获取或创建 Channel
|
||||
Channel channel = getProducer(config);
|
||||
// 1.2 声明交换机、队列和绑定关系
|
||||
channel.exchangeDeclare(config.getExchange(), "direct", true);
|
||||
channel.queueDeclare(config.getQueue(), true, false, false, null);
|
||||
channel.queueBind(config.getQueue(), config.getExchange(), config.getRoutingKey());
|
||||
|
||||
// 2. 发送消息
|
||||
channel.basicPublish(config.getExchange(), config.getRoutingKey(), null,
|
||||
message.toString().getBytes(StandardCharsets.UTF_8));
|
||||
log.info("[executeRabbitMQ][message({}) config({}) 发送成功]", message, config);
|
||||
// 2. 发送消息
|
||||
channel.basicPublish(config.getExchange(), config.getRoutingKey(), null,
|
||||
JsonUtils.toJsonByte(message));
|
||||
log.info("[execute][message({}) config({}) 发送成功]", message, config);
|
||||
} catch (Exception e) {
|
||||
log.error("[execute][message({}) config({}) 发送失败]", message, config, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.data.action;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.config.IotDataSinkRedisStreamConfig;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotDataSinkTypeEnum;
|
||||
@@ -38,10 +39,10 @@ public class IotRedisStreamRuleAction extends
|
||||
RedisTemplate<String, Object> redisTemplate = getProducer(config);
|
||||
|
||||
// 2. 创建并发送 Stream 记录
|
||||
ObjectRecord<String, IotDeviceMessage> record = StreamRecords.newRecord()
|
||||
.ofObject(message).withStreamKey(config.getTopic());
|
||||
ObjectRecord<String, ?> record = StreamRecords.newRecord()
|
||||
.ofObject(JsonUtils.toJsonString(message)).withStreamKey(config.getTopic());
|
||||
String recordId = String.valueOf(redisTemplate.opsForStream().add(record));
|
||||
log.info("[executeRedisStream][消息发送成功] messageId: {}, config: {}", recordId, config);
|
||||
log.info("[execute][消息发送成功] messageId: {}, config: {}", recordId, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,11 +57,11 @@ public class IotRedisStreamRuleAction extends
|
||||
serverConfig.setPassword(config.getPassword());
|
||||
}
|
||||
|
||||
// 创建 RedisTemplate 并配置
|
||||
// 2.1 创建 RedisTemplate 并配置
|
||||
RedissonClient redisson = Redisson.create(redissonConfig);
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(new RedissonConnectionFactory(redisson));
|
||||
// 设置序列化器
|
||||
// 2.2 设置序列化器
|
||||
template.setKeySerializer(RedisSerializer.string());
|
||||
template.setHashKeySerializer(RedisSerializer.string());
|
||||
template.setValueSerializer(RedisSerializer.json());
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package cn.iocoder.yudao.module.iot.service.rule.data.action;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.config.IotDataSinkRocketMQConfig;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.config.IotDataSinkRocketMQConfig;
|
||||
import cn.iocoder.yudao.module.iot.enums.rule.IotDataSinkTypeEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.client.producer.DefaultMQProducer;
|
||||
import org.apache.rocketmq.client.producer.SendResult;
|
||||
import org.apache.rocketmq.client.producer.SendStatus;
|
||||
import org.apache.rocketmq.common.message.Message;
|
||||
import org.apache.rocketmq.remoting.common.RemotingHelper;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -33,19 +33,15 @@ public class IotRocketMQDataRuleAction extends
|
||||
// 1. 获取或创建 Producer
|
||||
DefaultMQProducer producer = getProducer(config);
|
||||
|
||||
// 2.1 创建消息对象,指定Topic、Tag和消息体
|
||||
Message msg = new Message(
|
||||
config.getTopic(),
|
||||
config.getTags(),
|
||||
message.toString().getBytes(RemotingHelper.DEFAULT_CHARSET)
|
||||
);
|
||||
// 2.1 创建消息对象,指定 Topic、Tag 和消息体
|
||||
Message msg = new Message(config.getTopic(), config.getTags(), JsonUtils.toJsonByte(message));
|
||||
// 2.2 发送同步消息并处理结果
|
||||
SendResult sendResult = producer.send(msg);
|
||||
// 2.3 处理发送结果
|
||||
if (SendStatus.SEND_OK.equals(sendResult.getSendStatus())) {
|
||||
log.info("[executeRocketMQ][message({}) config({}) 发送成功,结果({})]", message, config, sendResult);
|
||||
log.info("[execute][message({}) config({}) 发送成功,结果({})]", message, config, sendResult);
|
||||
} else {
|
||||
log.error("[executeRocketMQ][message({}) config({}) 发送失败,结果({})]", message, config, sendResult);
|
||||
log.error("[execute][message({}) config({}) 发送失败,结果({})]", message, config, sendResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user