【代码新增】IoT:实现 device 下行服务调用的逻辑
This commit is contained in:
parent
7670ac19e5
commit
b454069897
|
@ -1,7 +1,10 @@
|
|||
package cn.iocoder.yudao.module.iot.api.device.dto.control.downstream;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* IoT 设备【服务】调用 Request DTO
|
||||
*
|
||||
|
@ -9,4 +12,15 @@ import lombok.Data;
|
|||
*/
|
||||
@Data
|
||||
public class IotDeviceServiceInvokeReqDTO extends IotDeviceDownstreamAbstractReqDTO {
|
||||
|
||||
/**
|
||||
* 服务标识
|
||||
*/
|
||||
@NotEmpty(message = "服务标识不能为空")
|
||||
private String identifier;
|
||||
/**
|
||||
* 调用参数
|
||||
*/
|
||||
private Map<String, Object> params;
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ public class IotDeviceEventReportReqDTO extends IotDeviceUpstreamAbstractReqDTO
|
|||
/**
|
||||
* 事件参数
|
||||
*/
|
||||
@NotEmpty(message = "事件参数不能为空")
|
||||
private Map<String, Object> params;
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ 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, "执行失败,原因:{}");
|
||||
|
||||
// ========== 产品分类 1-050-004-000 ==========
|
||||
ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_004_000, "产品分类不存在");
|
||||
|
@ -46,6 +47,6 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode PLUGIN_STATUS_INVALID = new ErrorCode(1_050_006_004, "插件状态无效");
|
||||
|
||||
// ========== 插件实例 1-050-007-000 ==========
|
||||
ErrorCode PLUGIN_INSTANCE_NOT_EXISTS = new ErrorCode(1_050_007_000, "插件实例不存在");
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
### 请求 /iot/device/simulation-downstream 接口 => 成功
|
||||
POST {{baseUrl}}/iot/device/simulation-downstream
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenentId}}
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
{
|
||||
"id": 25,
|
||||
"type": "service",
|
||||
"identifier": "temperature",
|
||||
"data": {
|
||||
"xx": "yy"
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceSimulationDownstreamReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceSimulationUpstreamReqVO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||
|
@ -171,7 +172,7 @@ public class IotDeviceController {
|
|||
@Operation(summary = "模拟设备下行")
|
||||
@PreAuthorize("@ss.hasPermission('iot:device:simulation')")
|
||||
public CommonResult<Boolean> simulationDownstreamDevice(
|
||||
@Valid @RequestBody IotDeviceSimulationUpstreamReqVO downstreamReqVO) {
|
||||
@Valid @RequestBody IotDeviceSimulationDownstreamReqVO downstreamReqVO) {
|
||||
deviceDownstreamService.simulationDeviceDownstream(downstreamReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,12 @@ public class IotDeviceLogDO {
|
|||
* 存储具体的消息数据内容,通常是 JSON 格式
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 响应码
|
||||
*
|
||||
* 目前只有 server 下行消息给 device 设备时,才会有响应码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 上报时间戳
|
||||
|
|
|
@ -55,12 +55,16 @@ public class IotDeviceMessage {
|
|||
* 例如说:属性上报的 properties、事件上报的 params
|
||||
*/
|
||||
private Object data;
|
||||
/**
|
||||
* 响应码
|
||||
*
|
||||
* 目前只有 server 下行消息给 device 设备时,才会有响应码
|
||||
*/
|
||||
private Integer code;
|
||||
|
||||
/**
|
||||
* 上报时间
|
||||
*/
|
||||
private LocalDateTime reportTime;
|
||||
|
||||
// TODO @芋艿 code;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package cn.iocoder.yudao.module.iot.service.device.control;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceSimulationUpstreamReqVO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceSimulationDownstreamReqVO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
/**
|
||||
|
@ -17,6 +17,6 @@ public interface IotDeviceDownstreamService {
|
|||
*
|
||||
* @param downstreamReqVO 设备下行请求 VO
|
||||
*/
|
||||
void simulationDeviceDownstream(@Valid IotDeviceSimulationUpstreamReqVO downstreamReqVO);
|
||||
void simulationDeviceDownstream(@Valid IotDeviceSimulationDownstreamReqVO downstreamReqVO);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,17 +1,36 @@
|
|||
package cn.iocoder.yudao.module.iot.service.device.control;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceSimulationUpstreamReqVO;
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceDownstreamAbstractReqDTO;
|
||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceServiceInvokeReqDTO;
|
||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceSimulationDownstreamReqVO;
|
||||
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.enums.device.IotDeviceMessageIdentifierEnum;
|
||||
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
|
||||
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.mq.producer.device.IotDeviceProducer;
|
||||
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
|
||||
import cn.iocoder.yudao.module.iot.service.plugin.IotPluginInstanceService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_DOWNSTREAM_FAILED;
|
||||
|
||||
/**
|
||||
* 设备下行 Service 实现类
|
||||
*
|
||||
|
@ -24,9 +43,17 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
|
|||
|
||||
@Resource
|
||||
private IotDeviceService deviceService;
|
||||
@Resource
|
||||
private IotPluginInstanceService pluginInstanceService;
|
||||
|
||||
@Resource
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Resource
|
||||
private IotDeviceProducer deviceProducer;
|
||||
|
||||
@Override
|
||||
public void simulationDeviceDownstream(IotDeviceSimulationUpstreamReqVO downstreamReqVO) {
|
||||
public void simulationDeviceDownstream(IotDeviceSimulationDownstreamReqVO downstreamReqVO) {
|
||||
// 校验设备是否存在
|
||||
IotDeviceDO device = deviceService.validateDeviceExists(downstreamReqVO.getId());
|
||||
// TODO 芋艿:父设备的处理
|
||||
|
@ -40,12 +67,14 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
|
|||
// 属性相关
|
||||
if (Objects.equals(downstreamReqVO.getType(), IotDeviceMessageTypeEnum.PROPERTY.getType()))
|
||||
// 属性设置
|
||||
if (Objects.equals(downstreamReqVO.getIdentifier(), IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier())) {
|
||||
if (Objects.equals(downstreamReqVO.getIdentifier(),
|
||||
IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier())) {
|
||||
setDeviceProperty(downstreamReqVO, device, parentDevice);
|
||||
return;
|
||||
}
|
||||
// 属性设置
|
||||
if (Objects.equals(downstreamReqVO.getIdentifier(), IotDeviceMessageIdentifierEnum.PROPERTY_GET.getIdentifier())) {
|
||||
if (Objects.equals(downstreamReqVO.getIdentifier(),
|
||||
IotDeviceMessageIdentifierEnum.PROPERTY_GET.getIdentifier())) {
|
||||
getDeviceProperty(downstreamReqVO, device, parentDevice);
|
||||
return;
|
||||
}
|
||||
|
@ -53,22 +82,121 @@ public class IotDeviceDownstreamServiceImpl implements IotDeviceDownstreamServic
|
|||
// TODO 芋艿:配置下发
|
||||
}
|
||||
|
||||
private void invokeDeviceService(IotDeviceSimulationUpstreamReqVO downstreamReqVO,
|
||||
/**
|
||||
* 调用设备服务
|
||||
*
|
||||
* @param downstreamReqVO 下行请求
|
||||
* @param device 设备
|
||||
* @param parentDevice 父设备
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void invokeDeviceService(IotDeviceSimulationDownstreamReqVO downstreamReqVO,
|
||||
IotDeviceDO device, IotDeviceDO parentDevice) {
|
||||
// 校验服务是否存在
|
||||
// TODO 芋艿:这里需要校验服务是否存在
|
||||
// 调用服务
|
||||
// TODO 芋艿:这里需要调用服务
|
||||
// 1. 参数校验
|
||||
if (!(downstreamReqVO.getData() instanceof Map<?, ?>)) {
|
||||
throw new ServiceException(BAD_REQUEST.getCode(), "data 不是 Map 类型");
|
||||
}
|
||||
|
||||
private void setDeviceProperty(IotDeviceSimulationUpstreamReqVO downstreamReqVO,
|
||||
IotDeviceDO device, IotDeviceDO parentDevice) {
|
||||
// TODO 芋艿:这里需要设置设备属性
|
||||
// 2. 发送请求
|
||||
String url = String.format( "sys/%s/%s/thing/service/%s",
|
||||
getProductKey(device, parentDevice), getDeviceName(device, parentDevice), downstreamReqVO.getIdentifier());
|
||||
IotDeviceServiceInvokeReqDTO reqDTO = new IotDeviceServiceInvokeReqDTO()
|
||||
.setParams((Map<String, Object>) downstreamReqVO.getData());
|
||||
CommonResult<Boolean> result = requestPlugin(url, reqDTO, device);
|
||||
|
||||
// 3. 发送设备消息
|
||||
IotDeviceMessage message = new IotDeviceMessage().setRequestId(reqDTO.getRequestId())
|
||||
.setType(IotDeviceMessageTypeEnum.SERVICE.getType()).setIdentifier(reqDTO.getIdentifier())
|
||||
.setData(reqDTO.getParams());
|
||||
sendDeviceMessage(message, device, result.getCode());
|
||||
|
||||
// 4. 如果不成功,抛出异常,提示用户
|
||||
if (result.isError()) {
|
||||
log.error("[invokeDeviceService][设备({})服务调用失败,请求参数:({}),响应结果:({})]",
|
||||
device.getDeviceKey(), reqDTO, result);
|
||||
throw exception(DEVICE_DOWNSTREAM_FAILED, result.getMsg());
|
||||
}
|
||||
}
|
||||
|
||||
private void getDeviceProperty(IotDeviceSimulationUpstreamReqVO downstreamReqVO,
|
||||
/**
|
||||
* 设置设备属性
|
||||
*
|
||||
* @param downstreamReqVO 下行请求
|
||||
* @param device 设备
|
||||
* @param parentDevice 父设备
|
||||
*/
|
||||
private void setDeviceProperty(IotDeviceSimulationDownstreamReqVO downstreamReqVO,
|
||||
IotDeviceDO device, IotDeviceDO parentDevice) {
|
||||
// TODO 1. 请求
|
||||
|
||||
// TODO 2. 发送消息
|
||||
}
|
||||
|
||||
private void getDeviceProperty(IotDeviceSimulationDownstreamReqVO downstreamReqVO,
|
||||
IotDeviceDO device, IotDeviceDO parentDevice) {
|
||||
// TODO 芋艿:这里需要获取设备属性
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求插件
|
||||
*
|
||||
* @param url URL
|
||||
* @param reqDTO 请求参数,只需要设置子类的参数!
|
||||
* @param device 设备
|
||||
* @return 响应结果
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "HttpUrlsUsage"})
|
||||
private CommonResult<Boolean> requestPlugin(String url, IotDeviceDownstreamAbstractReqDTO reqDTO, IotDeviceDO device) {
|
||||
// 获得设备对应的插件实例
|
||||
IotPluginInstanceDO pluginInstance = pluginInstanceService.getPluginInstanceByDeviceKey(device.getDeviceKey());
|
||||
if (pluginInstance == null) {
|
||||
throw exception(DEVICE_DOWNSTREAM_FAILED, "设备找不到对应的插件实例");
|
||||
}
|
||||
|
||||
// 补充通用参数
|
||||
reqDTO.setRequestId(IdUtil.fastSimpleUUID());
|
||||
|
||||
// 执行请求
|
||||
ResponseEntity<CommonResult<Boolean>> responseEntity;
|
||||
try {
|
||||
responseEntity = restTemplate.postForEntity(
|
||||
String.format("http://%s:%d/%s", pluginInstance.getHostIp(), pluginInstance.getDownstreamPort(), url),
|
||||
reqDTO, (Class<CommonResult<Boolean>>) (Class<?>) CommonResult.class);
|
||||
Assert.isTrue(responseEntity.getStatusCode().is2xxSuccessful(),
|
||||
"HTTP 状态码不是 2xx,而是" + responseEntity.getStatusCode());
|
||||
Assert.notNull(responseEntity.getBody(), "响应结果不能为空");
|
||||
} catch (Exception ex) {
|
||||
log.error("[requestPlugin][设备({}) url({}) 下行消息失败,请求参数({})]", device.getDeviceKey(), url, reqDTO, ex);
|
||||
throw exception(DEVICE_DOWNSTREAM_FAILED, ExceptionUtil.getMessage(ex));
|
||||
}
|
||||
return responseEntity.getBody();
|
||||
}
|
||||
|
||||
private void sendDeviceMessage(IotDeviceMessage message, IotDeviceDO device, Integer code) {
|
||||
// 1. 完善消息
|
||||
message.setProductKey(device.getProductKey()).setDeviceName(device.getDeviceName())
|
||||
.setDeviceKey(device.getDeviceKey());
|
||||
Assert.notNull(message.getRequestId(), "requestId 不能为空");
|
||||
if (message.getReportTime() == null) {
|
||||
message.setReportTime(LocalDateTime.now());
|
||||
}
|
||||
message.setCode(code);
|
||||
|
||||
// 2. 发送消息
|
||||
try {
|
||||
deviceProducer.sendDeviceMessage(message);
|
||||
log.info("[sendDeviceMessage][message({}) 发送消息成功]", message);
|
||||
} catch (Exception e) {
|
||||
log.error("[sendDeviceMessage][message({}) 发送消息失败]", message, e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getDeviceName(IotDeviceDO device, IotDeviceDO parentDevice) {
|
||||
return parentDevice != null ? parentDevice.getDeviceName() : device.getDeviceName();
|
||||
}
|
||||
|
||||
private String getProductKey(IotDeviceDO device, IotDeviceDO parentDevice) {
|
||||
return parentDevice != null ? parentDevice.getProductKey() : device.getProductKey();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.service.plugin;
|
|||
|
||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotPluginInstanceHeartbeatReqDTO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInfoDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInstanceDO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
@ -67,4 +68,12 @@ public interface IotPluginInstanceService {
|
|||
*/
|
||||
void updateDevicePluginInstanceProcessIdAsync(String deviceKey, String processId);
|
||||
|
||||
/**
|
||||
* 获得设备对应的插件实例
|
||||
*
|
||||
* @param deviceKey 设备 Key
|
||||
* @return 插件实例
|
||||
*/
|
||||
IotPluginInstanceDO getPluginInstanceByDeviceKey(String deviceKey);
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.service.plugin;
|
|||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.iot.api.device.dto.control.upstream.IotPluginInstanceHeartbeatReqDTO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInfoDO;
|
||||
import cn.iocoder.yudao.module.iot.dal.dataobject.plugin.IotPluginInstanceDO;
|
||||
|
@ -203,4 +204,13 @@ public class IotPluginInstanceServiceImpl implements IotPluginInstanceService {
|
|||
devicePluginProcessIdRedisDAO.put(deviceKey, processId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IotPluginInstanceDO getPluginInstanceByDeviceKey(String deviceKey) {
|
||||
String processId = devicePluginProcessIdRedisDAO.get(deviceKey);
|
||||
if (StrUtil.isEmpty(processId)) {
|
||||
return null;
|
||||
}
|
||||
return pluginInstanceMapper.selectByProcessId(processId);
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
type NCHAR(50),
|
||||
identifier NCHAR(255),
|
||||
content NCHAR(1024),
|
||||
code INT,
|
||||
report_time TIMESTAMP
|
||||
) TAGS (
|
||||
device_key NCHAR(50)
|
||||
|
@ -24,7 +25,7 @@
|
|||
</select>
|
||||
|
||||
<insert id="insert">
|
||||
INSERT INTO device_log_${deviceKey} (ts, id, product_key, device_name, type, identifier, content, report_time)
|
||||
INSERT INTO device_log_${deviceKey} (ts, id, product_key, device_name, type, identifier, content, code, report_time)
|
||||
USING device_log
|
||||
TAGS ('${deviceKey}')
|
||||
VALUES (
|
||||
|
@ -35,6 +36,7 @@
|
|||
#{type},
|
||||
#{identifier},
|
||||
#{content},
|
||||
#{code},
|
||||
#{reportTime}
|
||||
)
|
||||
</insert>
|
||||
|
|
|
@ -14,10 +14,28 @@ import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDeviceSe
|
|||
*/
|
||||
public interface IotDeviceDownstreamHandler {
|
||||
|
||||
/**
|
||||
* 调用设备服务
|
||||
*
|
||||
* @param invokeReqDTO 调用设备服务的请求
|
||||
* @return 是否成功
|
||||
*/
|
||||
CommonResult<Boolean> invokeDeviceService(IotDeviceServiceInvokeReqDTO invokeReqDTO);
|
||||
|
||||
/**
|
||||
* 获取设备属性
|
||||
*
|
||||
* @param getReqDTO 获取设备属性的请求
|
||||
* @return 是否成功
|
||||
*/
|
||||
CommonResult<Boolean> getDeviceProperty(IotDevicePropertyGetReqDTO getReqDTO);
|
||||
|
||||
/**
|
||||
* 设置设备属性
|
||||
*
|
||||
* @param setReqDTO 设置设备属性的请求
|
||||
* @return 是否成功
|
||||
*/
|
||||
CommonResult<Boolean> setDeviceProperty(IotDevicePropertySetReqDTO setReqDTO);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
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.IotDeviceServiceInvokeReqDTO;
|
||||
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.ext.web.RoutingContext;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
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;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
|
@ -15,9 +23,34 @@ public class IotDeviceServiceInvokeVertxHandler implements Handler<RoutingContex
|
|||
private final IotDeviceDownstreamHandler deviceDownstreamHandler;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handle(RoutingContext routingContext) {
|
||||
// TODO 芋艿:这里没实现
|
||||
deviceDownstreamHandler.invokeDeviceService(null);
|
||||
// 1. 解析参数
|
||||
IotDeviceServiceInvokeReqDTO invokeReqDTO;
|
||||
try {
|
||||
String productKey = routingContext.pathParam("productKey");
|
||||
String deviceName = routingContext.pathParam("deviceName");
|
||||
String identifier = routingContext.pathParam("identifier");
|
||||
JsonObject body = routingContext.body().asJsonObject();
|
||||
String requestId = body.getString("requestId");
|
||||
Map<String, Object> params = (Map<String, Object>) body.getMap().get("params");
|
||||
invokeReqDTO = ((IotDeviceServiceInvokeReqDTO) new IotDeviceServiceInvokeReqDTO()
|
||||
.setRequestId(requestId).setProductKey(productKey).setDeviceName(deviceName))
|
||||
.setIdentifier(identifier).setParams(params);
|
||||
} catch (Exception e) {
|
||||
log.error("[handle][解析参数失败]", e);
|
||||
IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(BAD_REQUEST));
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 调用下游处理器
|
||||
try {
|
||||
CommonResult<Boolean> result = deviceDownstreamHandler.invokeDeviceService(invokeReqDTO);
|
||||
IotPluginCommonUtils.writeJson(routingContext, result);
|
||||
} catch (Exception e) {
|
||||
log.error("[handle][请求参数({}) 服务调用异常]", invokeReqDTO, e);
|
||||
IotPluginCommonUtils.writeJson(routingContext, CommonResult.error(INTERNAL_SERVER_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@ package cn.iocoder.yudao.module.iot.plugin.common.util;
|
|||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.system.SystemUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import io.vertx.core.http.HttpHeaders;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* IoT 插件的通用工具类
|
||||
|
@ -28,4 +33,12 @@ public class IotPluginCommonUtils {
|
|||
SystemUtil.getHostInfo().getAddress(), SystemUtil.getCurrentPID(), IdUtil.fastSimpleUUID());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void writeJson(RoutingContext routingContext, CommonResult<?> result) {
|
||||
routingContext.response()
|
||||
.setStatusCode(200)
|
||||
.putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
|
||||
.end(JsonUtils.toJsonString(result));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package cn.iocoder.yudao.module.iot.plugin.http.config;
|
||||
|
||||
import cn.iocoder.yudao.module.iot.api.device.IotDeviceUpstreamApi;
|
||||
import cn.iocoder.yudao.module.iot.plugin.common.downstream.IotDeviceDownstreamHandler;
|
||||
import cn.iocoder.yudao.module.iot.plugin.http.downstream.IotDeviceDownstreamHandlerImpl;
|
||||
import cn.iocoder.yudao.module.iot.plugin.http.upstream.IotDeviceUpstreamServer;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -26,4 +28,9 @@ public class IotPluginHttpAutoConfiguration {
|
|||
return new IotDeviceUpstreamServer(port, deviceUpstreamApi);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IotDeviceDownstreamHandler deviceDownstreamHandler() {
|
||||
return new IotDeviceDownstreamHandlerImpl();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ import cn.iocoder.yudao.module.iot.api.device.dto.control.downstream.IotDevicePr
|
|||
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.plugin.common.downstream.IotDeviceDownstreamHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED;
|
||||
|
||||
/**
|
||||
* HTTP 插件的 {@link IotDeviceDownstreamHandler} 实现类
|
||||
|
@ -15,28 +16,21 @@ import org.springframework.stereotype.Component;
|
|||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component // TODO @芋艿:后续统一处理
|
||||
public class IotDeviceDownstreamHandlerImpl implements IotDeviceDownstreamHandler {
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> invokeDeviceService(IotDeviceServiceInvokeReqDTO invokeReqDTO) {
|
||||
// TODO @芋艿:待实现
|
||||
System.out.println();
|
||||
return null;
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持调用设备服务");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> getDeviceProperty(IotDevicePropertyGetReqDTO getReqDTO) {
|
||||
// TODO @芋艿:待实现
|
||||
System.out.println();
|
||||
return null;
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持获取设备属性");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> setDeviceProperty(IotDevicePropertySetReqDTO setReqDTO) {
|
||||
// TODO @芋艿:待实现
|
||||
System.out.println();
|
||||
return null;
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(), "HTTP 不支持设置设备属性");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue