feat:【IOT】添加 IoT 脚本模块及相关配置,删除不再使用的插件模块
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.iot.protocol.config;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.protocol.message.IotMessageParser;
|
||||
import cn.iocoder.yudao.module.iot.protocol.message.impl.IotAlinkMessageParser;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* IoT 协议模块自动配置类
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class IotProtocolAutoConfiguration {
|
||||
|
||||
/**
|
||||
* 注册 Alink 协议消息解析器
|
||||
*
|
||||
* @return Alink 协议消息解析器
|
||||
*/
|
||||
@Bean
|
||||
public IotMessageParser iotAlinkMessageParser() {
|
||||
return new IotAlinkMessageParser();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package cn.iocoder.yudao.module.iot.protocol.constants;
|
||||
|
||||
/**
|
||||
* IoT 设备主题常量类
|
||||
* <p>
|
||||
* 用于统一管理 MQTT 协议中的主题常量,基于 Alink 协议规范
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
public class IotTopicConstants {
|
||||
|
||||
/**
|
||||
* 系统主题前缀
|
||||
*/
|
||||
public static final String SYS_TOPIC_PREFIX = "/sys/";
|
||||
|
||||
/**
|
||||
* 服务调用主题前缀
|
||||
*/
|
||||
public static final String SERVICE_TOPIC_PREFIX = "/thing/service/";
|
||||
|
||||
/**
|
||||
* 设备属性设置主题
|
||||
* 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/set
|
||||
* 响应Topic:/sys/${productKey}/${deviceName}/thing/service/property/set_reply
|
||||
*/
|
||||
public static final String PROPERTY_SET_TOPIC = "/thing/service/property/set";
|
||||
|
||||
/**
|
||||
* 设备属性获取主题
|
||||
* 请求Topic:/sys/${productKey}/${deviceName}/thing/service/property/get
|
||||
* 响应Topic:/sys/${productKey}/${deviceName}/thing/service/property/get_reply
|
||||
*/
|
||||
public static final String PROPERTY_GET_TOPIC = "/thing/service/property/get";
|
||||
|
||||
/**
|
||||
* 设备配置设置主题
|
||||
* 请求Topic:/sys/${productKey}/${deviceName}/thing/service/config/set
|
||||
* 响应Topic:/sys/${productKey}/${deviceName}/thing/service/config/set_reply
|
||||
*/
|
||||
public static final String CONFIG_SET_TOPIC = "/thing/service/config/set";
|
||||
|
||||
/**
|
||||
* 设备OTA升级主题
|
||||
* 请求Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade
|
||||
* 响应Topic:/sys/${productKey}/${deviceName}/thing/service/ota/upgrade_reply
|
||||
*/
|
||||
public static final String OTA_UPGRADE_TOPIC = "/thing/service/ota/upgrade";
|
||||
|
||||
/**
|
||||
* 设备属性上报主题
|
||||
* 请求Topic:/sys/${productKey}/${deviceName}/thing/event/property/post
|
||||
* 响应Topic:/sys/${productKey}/${deviceName}/thing/event/property/post_reply
|
||||
*/
|
||||
public static final String PROPERTY_POST_TOPIC = "/thing/event/property/post";
|
||||
|
||||
/**
|
||||
* 设备事件上报主题前缀
|
||||
*/
|
||||
public static final String EVENT_POST_TOPIC_PREFIX = "/thing/event/";
|
||||
|
||||
/**
|
||||
* 设备事件上报主题后缀
|
||||
*/
|
||||
public static final String EVENT_POST_TOPIC_SUFFIX = "/post";
|
||||
|
||||
/**
|
||||
* 响应主题后缀
|
||||
*/
|
||||
public static final String REPLY_SUFFIX = "_reply";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package cn.iocoder.yudao.module.iot.protocol.message;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* IoT Alink 消息模型
|
||||
* <p>
|
||||
* 基于阿里云 Alink 协议规范实现的标准消息格式
|
||||
* @see <a href="https://help.aliyun.com/zh/iot/user-guide/alink-protocol-1">阿里云物联网 —— Alink 协议</a>
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class IotAlinkMessage {
|
||||
|
||||
/**
|
||||
* 消息 ID
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 协议版本
|
||||
*/
|
||||
@Builder.Default
|
||||
private String version = "1.0";
|
||||
|
||||
/**
|
||||
* 消息方法
|
||||
*/
|
||||
private String method;
|
||||
|
||||
/**
|
||||
* 消息参数
|
||||
*/
|
||||
private Map<String, Object> params;
|
||||
|
||||
/**
|
||||
* 转换为 JSONObject
|
||||
*
|
||||
* @return JSONObject 对象
|
||||
*/
|
||||
public JSONObject toJsonObject() {
|
||||
JSONObject json = new JSONObject();
|
||||
json.set("id", id);
|
||||
json.set("version", version);
|
||||
json.set("method", method);
|
||||
json.set("params", params != null ? params : new JSONObject());
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 JSON 字符串
|
||||
*
|
||||
* @return JSON 字符串
|
||||
*/
|
||||
public String toJsonString() {
|
||||
return toJsonObject().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建设备服务调用消息
|
||||
*
|
||||
* @param requestId 请求 ID,为空时自动生成
|
||||
* @param serviceIdentifier 服务标识符
|
||||
* @param params 服务参数
|
||||
* @return Alink 消息对象
|
||||
*/
|
||||
public static IotAlinkMessage createServiceInvokeMessage(String requestId, String serviceIdentifier,
|
||||
Map<String, Object> params) {
|
||||
return IotAlinkMessage.builder()
|
||||
.id(requestId != null ? requestId : generateRequestId())
|
||||
.method("thing.service." + serviceIdentifier)
|
||||
.params(params)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建设备属性设置消息
|
||||
*
|
||||
* @param requestId 请求 ID,为空时自动生成
|
||||
* @param properties 设备属性
|
||||
* @return Alink 消息对象
|
||||
*/
|
||||
public static IotAlinkMessage createPropertySetMessage(String requestId, Map<String, Object> properties) {
|
||||
return IotAlinkMessage.builder()
|
||||
.id(requestId != null ? requestId : generateRequestId())
|
||||
.method("thing.service.property.set")
|
||||
.params(properties)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建设备属性获取消息
|
||||
*
|
||||
* @param requestId 请求 ID,为空时自动生成
|
||||
* @param identifiers 要获取的属性标识符列表
|
||||
* @return Alink 消息对象
|
||||
*/
|
||||
public static IotAlinkMessage createPropertyGetMessage(String requestId, String[] identifiers) {
|
||||
JSONObject params = new JSONObject();
|
||||
params.set("identifiers", identifiers);
|
||||
|
||||
return IotAlinkMessage.builder()
|
||||
.id(requestId != null ? requestId : generateRequestId())
|
||||
.method("thing.service.property.get")
|
||||
.params(params)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建设备配置设置消息
|
||||
*
|
||||
* @param requestId 请求 ID,为空时自动生成
|
||||
* @param configs 设备配置
|
||||
* @return Alink 消息对象
|
||||
*/
|
||||
public static IotAlinkMessage createConfigSetMessage(String requestId, Map<String, Object> configs) {
|
||||
return IotAlinkMessage.builder()
|
||||
.id(requestId != null ? requestId : generateRequestId())
|
||||
.method("thing.service.config.set")
|
||||
.params(configs)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建设备 OTA 升级消息
|
||||
*
|
||||
* @param requestId 请求 ID,为空时自动生成
|
||||
* @param otaInfo OTA 升级信息
|
||||
* @return Alink 消息对象
|
||||
*/
|
||||
public static IotAlinkMessage createOtaUpgradeMessage(String requestId, Map<String, Object> otaInfo) {
|
||||
return IotAlinkMessage.builder()
|
||||
.id(requestId != null ? requestId : generateRequestId())
|
||||
.method("thing.service.ota.upgrade")
|
||||
.params(otaInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成请求 ID
|
||||
*
|
||||
* @return 请求 ID
|
||||
*/
|
||||
public static String generateRequestId() {
|
||||
return IdUtil.fastSimpleUUID();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.iot.protocol.message;
|
||||
|
||||
/**
|
||||
* IoT 消息解析器接口
|
||||
* <p>
|
||||
* 用于解析不同协议的消息内容
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
public interface IotMessageParser {
|
||||
|
||||
/**
|
||||
* 解析消息
|
||||
*
|
||||
* @param topic 主题
|
||||
* @param payload 消息负载
|
||||
* @return 解析后的标准消息,如果解析失败返回 null
|
||||
*/
|
||||
IotAlinkMessage parse(String topic, byte[] payload);
|
||||
|
||||
/**
|
||||
* 格式化响应消息
|
||||
*
|
||||
* @param response 标准响应
|
||||
* @return 格式化后的响应字节数组
|
||||
*/
|
||||
byte[] formatResponse(IotStandardResponse response);
|
||||
|
||||
/**
|
||||
* 检查是否能够处理指定主题的消息
|
||||
*
|
||||
* @param topic 主题
|
||||
* @return 如果能处理返回 true,否则返回 false
|
||||
*/
|
||||
boolean canHandle(String topic);
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package cn.iocoder.yudao.module.iot.protocol.message;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* IoT 标准协议响应实体类
|
||||
* <p>
|
||||
* 用于统一 MQTT 和 HTTP 的响应格式
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class IotStandardResponse {
|
||||
|
||||
/**
|
||||
* 消息 ID
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 响应数据
|
||||
*/
|
||||
private Object data;
|
||||
|
||||
/**
|
||||
* 响应消息
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 方法名
|
||||
*/
|
||||
private String method;
|
||||
|
||||
/**
|
||||
* 协议版本
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 创建成功响应
|
||||
*
|
||||
* @param id 消息 ID
|
||||
* @param method 方法名
|
||||
* @return 成功响应
|
||||
*/
|
||||
public static IotStandardResponse success(String id, String method) {
|
||||
return success(id, method, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建成功响应
|
||||
*
|
||||
* @param id 消息 ID
|
||||
* @param method 方法名
|
||||
* @param data 响应数据
|
||||
* @return 成功响应
|
||||
*/
|
||||
public static IotStandardResponse success(String id, String method, Object data) {
|
||||
return new IotStandardResponse()
|
||||
.setId(id)
|
||||
.setCode(200)
|
||||
.setData(data)
|
||||
.setMessage("success")
|
||||
.setMethod(method)
|
||||
.setVersion("1.0");
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建错误响应
|
||||
*
|
||||
* @param id 消息 ID
|
||||
* @param method 方法名
|
||||
* @param code 错误码
|
||||
* @param message 错误消息
|
||||
* @return 错误响应
|
||||
*/
|
||||
public static IotStandardResponse error(String id, String method, Integer code, String message) {
|
||||
return new IotStandardResponse()
|
||||
.setId(id)
|
||||
.setCode(code)
|
||||
.setData(null)
|
||||
.setMessage(StrUtil.blankToDefault(message, "error"))
|
||||
.setMethod(method)
|
||||
.setVersion("1.0");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package cn.iocoder.yudao.module.iot.protocol.message.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.iot.protocol.message.IotAlinkMessage;
|
||||
import cn.iocoder.yudao.module.iot.protocol.message.IotMessageParser;
|
||||
import cn.iocoder.yudao.module.iot.protocol.message.IotStandardResponse;
|
||||
import cn.iocoder.yudao.module.iot.protocol.util.IotTopicUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* IoT Alink 协议消息解析器实现
|
||||
* <p>
|
||||
* 基于阿里云 Alink 协议规范实现的消息解析器
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
@Slf4j
|
||||
public class IotAlinkMessageParser implements IotMessageParser {
|
||||
|
||||
@Override
|
||||
public IotAlinkMessage parse(String topic, byte[] payload) {
|
||||
if (payload == null || payload.length == 0) {
|
||||
log.warn("[Alink] 收到空消息内容, topic={}", topic);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
String message = new String(payload, StandardCharsets.UTF_8);
|
||||
if (!JSONUtil.isTypeJSON(message)) {
|
||||
log.warn("[Alink] 收到非JSON格式消息, topic={}, message={}", topic, message);
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject json = JSONUtil.parseObj(message);
|
||||
String id = json.getStr("id");
|
||||
String method = json.getStr("method");
|
||||
|
||||
if (StrUtil.isBlank(method)) {
|
||||
// 尝试从 topic 中解析方法
|
||||
method = IotTopicUtils.parseMethodFromTopic(topic);
|
||||
if (StrUtil.isBlank(method)) {
|
||||
log.warn("[Alink] 无法确定消息方法, topic={}, message={}", topic, message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> params = (Map<String, Object>) json.getObj("params", Map.class);
|
||||
return IotAlinkMessage.builder()
|
||||
.id(id)
|
||||
.method(method)
|
||||
.version(json.getStr("version", "1.0"))
|
||||
.params(params)
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
log.error("[Alink] 解析消息失败, topic={}", topic, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] formatResponse(IotStandardResponse response) {
|
||||
try {
|
||||
String json = JsonUtils.toJsonString(response);
|
||||
return json.getBytes(StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
log.error("[Alink] 格式化响应失败", e);
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(String topic) {
|
||||
// Alink 协议处理所有系统主题
|
||||
return topic != null && topic.startsWith("/sys/");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package cn.iocoder.yudao.module.iot.protocol.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.iot.protocol.constants.IotTopicConstants;
|
||||
|
||||
/**
|
||||
* IoT 主题工具类
|
||||
* <p>
|
||||
* 用于构建和解析设备主题
|
||||
*
|
||||
* @author haohao
|
||||
*/
|
||||
public class IotTopicUtils {
|
||||
|
||||
/**
|
||||
* 构建设备服务调用主题
|
||||
*
|
||||
* @param productKey 产品Key
|
||||
* @param deviceName 设备名称
|
||||
* @param serviceIdentifier 服务标识符
|
||||
* @return 完整的主题路径
|
||||
*/
|
||||
public static String buildServiceTopic(String productKey, String deviceName, String serviceIdentifier) {
|
||||
return buildDeviceBaseTopic(productKey, deviceName) +
|
||||
IotTopicConstants.SERVICE_TOPIC_PREFIX + serviceIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备属性设置主题
|
||||
*
|
||||
* @param productKey 产品Key
|
||||
* @param deviceName 设备名称
|
||||
* @return 完整的主题路径
|
||||
*/
|
||||
public static String buildPropertySetTopic(String productKey, String deviceName) {
|
||||
return buildDeviceBaseTopic(productKey, deviceName) + IotTopicConstants.PROPERTY_SET_TOPIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备属性获取主题
|
||||
*
|
||||
* @param productKey 产品Key
|
||||
* @param deviceName 设备名称
|
||||
* @return 完整的主题路径
|
||||
*/
|
||||
public static String buildPropertyGetTopic(String productKey, String deviceName) {
|
||||
return buildDeviceBaseTopic(productKey, deviceName) + IotTopicConstants.PROPERTY_GET_TOPIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备配置设置主题
|
||||
*
|
||||
* @param productKey 产品Key
|
||||
* @param deviceName 设备名称
|
||||
* @return 完整的主题路径
|
||||
*/
|
||||
public static String buildConfigSetTopic(String productKey, String deviceName) {
|
||||
return buildDeviceBaseTopic(productKey, deviceName) + IotTopicConstants.CONFIG_SET_TOPIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备 OTA 升级主题
|
||||
*
|
||||
* @param productKey 产品Key
|
||||
* @param deviceName 设备名称
|
||||
* @return 完整的主题路径
|
||||
*/
|
||||
public static String buildOtaUpgradeTopic(String productKey, String deviceName) {
|
||||
return buildDeviceBaseTopic(productKey, deviceName) + IotTopicConstants.OTA_UPGRADE_TOPIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备属性上报主题
|
||||
*
|
||||
* @param productKey 产品Key
|
||||
* @param deviceName 设备名称
|
||||
* @return 完整的主题路径
|
||||
*/
|
||||
public static String buildPropertyPostTopic(String productKey, String deviceName) {
|
||||
return buildDeviceBaseTopic(productKey, deviceName) + IotTopicConstants.PROPERTY_POST_TOPIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备事件上报主题
|
||||
*
|
||||
* @param productKey 产品Key
|
||||
* @param deviceName 设备名称
|
||||
* @param eventIdentifier 事件标识符
|
||||
* @return 完整的主题路径
|
||||
*/
|
||||
public static String buildEventPostTopic(String productKey, String deviceName, String eventIdentifier) {
|
||||
return buildDeviceBaseTopic(productKey, deviceName) +
|
||||
IotTopicConstants.EVENT_POST_TOPIC_PREFIX + eventIdentifier + IotTopicConstants.EVENT_POST_TOPIC_SUFFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取响应主题
|
||||
*
|
||||
* @param requestTopic 请求主题
|
||||
* @return 响应主题
|
||||
*/
|
||||
public static String getReplyTopic(String requestTopic) {
|
||||
return requestTopic + IotTopicConstants.REPLY_SUFFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备基础主题
|
||||
* 格式: /sys/${productKey}/${deviceName}
|
||||
*
|
||||
* @param productKey 产品Key
|
||||
* @param deviceName 设备名称
|
||||
* @return 设备基础主题
|
||||
*/
|
||||
public static String buildDeviceBaseTopic(String productKey, String deviceName) {
|
||||
return IotTopicConstants.SYS_TOPIC_PREFIX + productKey + "/" + deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从主题中解析产品Key
|
||||
* 格式: /sys/${productKey}/${deviceName}/...
|
||||
*
|
||||
* @param topic 主题
|
||||
* @return 产品Key,如果无法解析则返回null
|
||||
*/
|
||||
public static String parseProductKeyFromTopic(String topic) {
|
||||
if (StrUtil.isBlank(topic) || !topic.startsWith(IotTopicConstants.SYS_TOPIC_PREFIX)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] parts = topic.split("/");
|
||||
if (parts.length < 4) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parts[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* 从主题中解析设备名称
|
||||
* 格式: /sys/${productKey}/${deviceName}/...
|
||||
*
|
||||
* @param topic 主题
|
||||
* @return 设备名称,如果无法解析则返回null
|
||||
*/
|
||||
public static String parseDeviceNameFromTopic(String topic) {
|
||||
if (StrUtil.isBlank(topic) || !topic.startsWith(IotTopicConstants.SYS_TOPIC_PREFIX)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] parts = topic.split("/");
|
||||
if (parts.length < 4) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parts[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* 从主题中解析方法名
|
||||
* 例如:从 /sys/pk/dn/thing/service/property/set 解析出 property.set
|
||||
*
|
||||
* @param topic 主题
|
||||
* @return 方法名,如果无法解析则返回null
|
||||
*/
|
||||
public static String parseMethodFromTopic(String topic) {
|
||||
if (StrUtil.isBlank(topic) || !topic.startsWith(IotTopicConstants.SYS_TOPIC_PREFIX)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 服务调用主题
|
||||
if (topic.contains("/thing/service/")) {
|
||||
String servicePart = topic.substring(topic.indexOf("/thing/service/") + "/thing/service/".length());
|
||||
return servicePart.replace("/", ".");
|
||||
}
|
||||
|
||||
// 事件上报主题
|
||||
if (topic.contains("/thing/event/")) {
|
||||
String eventPart = topic.substring(topic.indexOf("/thing/event/") + "/thing/event/".length());
|
||||
return "event." + eventPart.replace("/", ".");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
cn.iocoder.yudao.module.iot.protocol.config.IotProtocolAutoConfiguration
|
||||
Reference in New Issue
Block a user