【代码新增】IoT:增加 device 配置下发(设置)实现
This commit is contained in:
parent
47c281d933
commit
f46a2fb011
|
@ -0,0 +1,22 @@
|
||||||
|
package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 设备【配置】设置 Request DTO
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class IotDeviceConfigSetReqDTO extends IotDeviceDownstreamAbstractReqDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置
|
||||||
|
*/
|
||||||
|
@NotNull(message = "配置不能为空")
|
||||||
|
private Map<String, Object> config;
|
||||||
|
|
||||||
|
}
|
|
@ -10,15 +10,17 @@ import lombok.RequiredArgsConstructor;
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public enum IotDeviceMessageIdentifierEnum {
|
public enum IotDeviceMessageIdentifierEnum {
|
||||||
|
|
||||||
PROPERTY_GET("get"), // 下行
|
PROPERTY_GET("get"), // 下行 TODO 芋艿:【讨论】貌似这个“上行”更合理?device 主动拉取配置。和 IotDevicePropertyGetReqDTO 一样的配置
|
||||||
PROPERTY_SET("set"), // 下行
|
PROPERTY_SET("set"), // 下行
|
||||||
PROPERTY_REPORT("report"), // 上行
|
PROPERTY_REPORT("report"), // 上行
|
||||||
|
|
||||||
STATE_ONLINE("online"), // 上行
|
STATE_ONLINE("online"), // 上行
|
||||||
STATE_OFFLINE("offline"), // 上行
|
STATE_OFFLINE("offline"), // 上行
|
||||||
|
|
||||||
SERVICE_REPLY_SUFFIX("_reply"); // TODO 上行 or 下行
|
CONFIG_GET("get"), // 上行 TODO 芋艿:【讨论】暂时没有上行的场景
|
||||||
|
CONFIG_SET("set"), // 下行
|
||||||
|
|
||||||
|
SERVICE_REPLY_SUFFIX("_reply"); // 芋艿:TODO 芋艿:【讨论】上行 or 下行
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标志符
|
* 标志符
|
||||||
|
|
|
@ -16,7 +16,8 @@ public enum IotDeviceMessageTypeEnum implements ArrayValuable<String> {
|
||||||
STATE("state"), // 设备状态
|
STATE("state"), // 设备状态
|
||||||
PROPERTY("property"), // 设备属性
|
PROPERTY("property"), // 设备属性
|
||||||
EVENT("event"), // 设备事件
|
EVENT("event"), // 设备事件
|
||||||
SERVICE("service"); // 设备服务
|
SERVICE("service"), // 设备服务
|
||||||
|
CONFIG("config"); // 设备配置
|
||||||
|
|
||||||
public static final String[] ARRAYS = Arrays.stream(values()).map(IotDeviceMessageTypeEnum::getType).toArray(String[]::new);
|
public static final String[] ARRAYS = Arrays.stream(values()).map(IotDeviceMessageTypeEnum::getType).toArray(String[]::new);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
### 请求 /iot/device/simulation-downstream 接口(服务调用) => 成功
|
### 请求 /iot/device/downstream 接口(服务调用) => 成功
|
||||||
POST {{baseUrl}}/iot/device/simulation-downstream
|
POST {{baseUrl}}/iot/device/downstream
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
tenant-id: {{adminTenentId}}
|
tenant-id: {{adminTenentId}}
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
|
@ -13,8 +13,8 @@ Authorization: Bearer {{token}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
### 请求 /iot/device/simulation-downstream 接口(属性设置) => 成功
|
### 请求 /iot/device/downstream 接口(属性设置) => 成功
|
||||||
POST {{baseUrl}}/iot/device/simulation-downstream
|
POST {{baseUrl}}/iot/device/downstream
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
tenant-id: {{adminTenentId}}
|
tenant-id: {{adminTenentId}}
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
|
@ -28,8 +28,8 @@ Authorization: Bearer {{token}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
### 请求 /iot/device/simulation-downstream 接口(属性获取) => 成功
|
### 请求 /iot/device/downstream 接口(属性获取) => 成功
|
||||||
POST {{baseUrl}}/iot/device/simulation-downstream
|
POST {{baseUrl}}/iot/device/downstream
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
tenant-id: {{adminTenentId}}
|
tenant-id: {{adminTenentId}}
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
|
@ -40,3 +40,15 @@ Authorization: Bearer {{token}}
|
||||||
"identifier": "get",
|
"identifier": "get",
|
||||||
"data": ["xx", "yy"]
|
"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"
|
||||||
|
}
|
|
@ -5,10 +5,8 @@ import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceDownstreamAbstractReqDTO;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;
|
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.*;
|
||||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO;
|
|
||||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
|
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInstanceDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInstanceDO;
|
||||||
|
@ -68,21 +66,27 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 属性相关
|
// 属性相关
|
||||||
if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType()))
|
if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType())) {
|
||||||
// 属性设置
|
// 属性设置
|
||||||
if (Objects.equals(downstreamReqVO.getIdentifier(),
|
if (Objects.equals(downstreamReqVO.getIdentifier(),
|
||||||
IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier())) {
|
IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier())) {
|
||||||
setDeviceProperty(downstreamReqVO, device, parentDevice);
|
setDeviceProperty(downstreamReqVO, device, parentDevice);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 属性设置
|
// 属性设置
|
||||||
if (Objects.equals(downstreamReqVO.getIdentifier(),
|
if (Objects.equals(downstreamReqVO.getIdentifier(),
|
||||||
IotDeviceMessageIdentifierEnum.PROPERTY_GET.getIdentifier())) {
|
IotDeviceMessageIdentifierEnum.PROPERTY_GET.getIdentifier())) {
|
||||||
getDeviceProperty(downstreamReqVO, device, parentDevice);
|
getDeviceProperty(downstreamReqVO, device, parentDevice);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 配置下发
|
||||||
|
if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.CONFIG.getType())
|
||||||
|
&& Objects.equals(downstreamReqVO.getIdentifier(), IotDeviceMessageIdentifierEnum.CONFIG_SET.getIdentifier())) {
|
||||||
|
setDeviceConfig(downstreamReqVO, device, parentDevice);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO 芋艿:ota 升级
|
// TODO 芋艿:ota 升级
|
||||||
// TODO 芋艿:配置下发
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,6 +202,41 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置设备配置
|
||||||
|
*
|
||||||
|
* @param downstreamReqVO 下行请求
|
||||||
|
* @param device 设备
|
||||||
|
* @param parentDevice 父设备
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unchecked", "unused"})
|
||||||
|
private void setDeviceConfig(IotDeviceDownstreamReqVO downstreamReqVO,
|
||||||
|
IotDeviceDO device, IotDeviceDO parentDevice) {
|
||||||
|
// 1. 参数转换,无需校验
|
||||||
|
Map<String, Object> config = JsonUtils.parseObject(device.getConfig(), Map.class);
|
||||||
|
|
||||||
|
// 2. 发送请求
|
||||||
|
String url = String.format( "sys/%s/%s/thing/service/config/set",
|
||||||
|
getProductKey(device, parentDevice), getDeviceName(device, parentDevice));
|
||||||
|
IotDeviceConfigSetReqDTO reqDTO = new IotDeviceConfigSetReqDTO()
|
||||||
|
.setConfig(config);
|
||||||
|
CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);
|
||||||
|
|
||||||
|
// 3. 发送设备消息
|
||||||
|
IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())
|
||||||
|
.setType(IotDeviceMessageTypeEnum.CONFIG.getType())
|
||||||
|
.setIdentifier(IotDeviceMessageIdentifierEnum.CONFIG_SET.getIdentifier())
|
||||||
|
.setData(reqDTO.getConfig());
|
||||||
|
sendDeviceMessage(message, device, result.getCode());
|
||||||
|
|
||||||
|
// 4. 如果不成功,抛出异常,提示用户
|
||||||
|
if (result.isError()) {
|
||||||
|
log.error("[setDeviceConfig][设备({})配置下发失败,请求参数:({}),响应结果:({})]",
|
||||||
|
device.getDeviceKey(), reqDTO, result);
|
||||||
|
throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求插件
|
* 请求插件
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.iot.plugin.common.downstream;
|
package cn.iocoder.yudao.module.iot.plugin.common.downstream;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceConfigSetReqDTO;
|
||||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;
|
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;
|
||||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO;
|
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO;
|
||||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
|
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
|
||||||
|
@ -38,4 +39,12 @@ public interface IotDeviceDownstreamHandler {
|
||||||
*/
|
*/
|
||||||
CommonResult<Boolean> setDeviceProperty(IotDevicePropertySetReqDTO setReqDTO);
|
CommonResult<Boolean> setDeviceProperty(IotDevicePropertySetReqDTO setReqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置设备配置
|
||||||
|
*
|
||||||
|
* @param setReqDTO 设置设备配置的请求
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
CommonResult<Boolean> setDeviceConfig(IotDeviceConfigSetReqDTO setReqDTO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.iot.plugin.common.downstream;
|
package cn.iocoder.yudao.module.iot.plugin.common.downstream;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.plugin.common.config.IotPluginCommonProperties;
|
import cn.iocoder.yudao.module.iot.plugin.common.config.IotPluginCommonProperties;
|
||||||
|
import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDeviceConfigSetVertxHandler;
|
||||||
import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDevicePropertyGetVertxHandler;
|
import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDevicePropertyGetVertxHandler;
|
||||||
import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDevicePropertySetVertxHandler;
|
import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDevicePropertySetVertxHandler;
|
||||||
import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDeviceServiceInvokeVertxHandler;
|
import cn.iocoder.yudao.module.iot.plugin.common.downstream.router.IotDeviceServiceInvokeVertxHandler;
|
||||||
|
@ -36,6 +37,8 @@ public class IotDeviceDownstreamServer {
|
||||||
.handler(new IotDevicePropertySetVertxHandler(deviceDownstreamHandler));
|
.handler(new IotDevicePropertySetVertxHandler(deviceDownstreamHandler));
|
||||||
router.post(IotDevicePropertyGetVertxHandler.PATH)
|
router.post(IotDevicePropertyGetVertxHandler.PATH)
|
||||||
.handler(new IotDevicePropertyGetVertxHandler(deviceDownstreamHandler));
|
.handler(new IotDevicePropertyGetVertxHandler(deviceDownstreamHandler));
|
||||||
|
router.post(IotDeviceConfigSetVertxHandler.PATH)
|
||||||
|
.handler(new IotDeviceConfigSetVertxHandler(deviceDownstreamHandler));
|
||||||
// 创建 HttpServer 实例
|
// 创建 HttpServer 实例
|
||||||
this.server = vertx.createHttpServer().requestHandler(router);
|
this.server = vertx.createHttpServer().requestHandler(router);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package cn.iocoder.yudao.module.iot.plugin.common.downstream.router;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceConfigSetReqDTO;
|
||||||
|
import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
|
||||||
|
import cn.iocoder.yudao.module.iot.plugin.common.util.IotPluginCommonUtils;
|
||||||
|
import io.vertx.core.Handler;
|
||||||
|
import io.vertx.core.json.JsonObject;
|
||||||
|
import io.vertx.ext.web.RoutingContext;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IOT 设备配置设置 Vertx Handler
|
||||||
|
*
|
||||||
|
* 芋道源码
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class IotDeviceConfigSetVertxHandler implements Handler<RoutingContext> {
|
||||||
|
|
||||||
|
public static final String PATH = "/sys/:productKey/:deviceName/thing/service/config/set";
|
||||||
|
|
||||||
|
private final IotDeviceDownstreamHandler deviceDownstreamHandler;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void handle(RoutingContext routingContext) {
|
||||||
|
// 1. 解析参数
|
||||||
|
IotDeviceConfigSetReqDTO reqDTO;
|
||||||
|
try {
|
||||||
|
String productKey = routingContext.pathParam("productKey");
|
||||||
|
String deviceName = routingContext.pathParam("deviceName");
|
||||||
|
JsonObject body = routingContext.body().asJsonObject();
|
||||||
|
String requestId = body.getString("requestId");
|
||||||
|
Map<String, Object> config = (Map<String, Object>) body.getMap().get("config");
|
||||||
|
reqDTO = ((IotDeviceConfigSetReqDTO) new IotDeviceConfigSetReqDTO()
|
||||||
|
.setRequestId(requestId).setProductKey(productKey).setDeviceName(deviceName))
|
||||||
|
.setConfig(config);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[handle][路径参数({}) 解析参数失败]", routingContext.pathParams(), e);
|
||||||
|
IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 调用处理器
|
||||||
|
try {
|
||||||
|
CommonResult<Boolean> result = deviceDownstreamHandler.setDeviceConfig(reqDTO);
|
||||||
|
IotPluginCommonUtils.writeJson(routingContext, result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[handle][请求参数({}) 配置设置异常]", reqDTO, e);
|
||||||
|
IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.iot.plugin.http.downstream;
|
package cn.iocoder.yudao.module.iot.plugin.http.downstream;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceConfigSetReqDTO;
|
||||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;
|
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertyGetReqDTO;
|
||||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO;
|
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePropertySetReqDTO;
|
||||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
|
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
|
||||||
|
@ -33,4 +34,9 @@ public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandle
|
||||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
|
return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> setDeviceConfig(IotDeviceConfigSetReqDTO setReqDTO) {
|
||||||
|
return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue