feat(device): 新增设备下发命令功能

- 在 DeviceController 中添加 send 方法处理设备命令下发请求- 在 DeviceService 接口中定义 send 方法签名
- 实现 DeviceServiceImpl 中的 send 方法逻辑
- 更新 Param 类中的 Type 枚举,使用字符串值代替整数值- 修正 Serve 类中的 inputs 和 outputs 类型,从 ParamDto改为 Param
- 更新 ServeMapper.xml 中的 SQL 查询,适应新的 Param 类型和枚举值
This commit is contained in:
zhuangtianxiang 2025-03-03 12:39:54 +08:00
parent 6e7b557c3d
commit 662d34da11
6 changed files with 85 additions and 20 deletions

View File

@ -1,6 +1,5 @@
package com.zsc.edu.gateway.modules.iot.device.controller; package com.zsc.edu.gateway.modules.iot.device.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -18,6 +17,8 @@ import com.zsc.edu.gateway.modules.iot.record.entity.RecordData;
import com.zsc.edu.gateway.modules.iot.record.entity.RecordDataStatusVo; import com.zsc.edu.gateway.modules.iot.record.entity.RecordDataStatusVo;
import com.zsc.edu.gateway.modules.iot.record.service.RecordDataService; import com.zsc.edu.gateway.modules.iot.record.service.RecordDataService;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@ -148,4 +149,12 @@ public class DeviceController {
public DataWarningVo dataWarning() { public DataWarningVo dataWarning() {
return recordService.dataWarning(); return recordService.dataWarning();
} }
/**
* 下发命令
*/
@PostMapping("/send")
public String send(Long deviceId, String topic, Integer qos) throws JSONException {
return service.send(deviceId, topic, qos);
}
} }

View File

@ -10,6 +10,8 @@ import com.zsc.edu.gateway.modules.iot.device.entity.Device;
import com.zsc.edu.gateway.modules.iot.device.query.DeviceQuery; import com.zsc.edu.gateway.modules.iot.device.query.DeviceQuery;
import com.zsc.edu.gateway.modules.iot.device.vo.DeviceStatusVo; import com.zsc.edu.gateway.modules.iot.device.vo.DeviceStatusVo;
import com.zsc.edu.gateway.modules.iot.device.vo.DeviceVo; import com.zsc.edu.gateway.modules.iot.device.vo.DeviceVo;
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import java.util.List; import java.util.List;
@ -30,4 +32,6 @@ public interface DeviceService extends IService<Device> {
IPage<Device> query(Page<Device> page, DeviceQuery query); IPage<Device> query(Page<Device> page, DeviceQuery query);
DeviceStatusVo status(); DeviceStatusVo status();
String send(Long deviceId, String topic, Integer qos) throws JSONException;
} }

View File

@ -1,5 +1,6 @@
package com.zsc.edu.gateway.modules.iot.device.service.impl; package com.zsc.edu.gateway.modules.iot.device.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -19,11 +20,19 @@ import com.zsc.edu.gateway.modules.iot.device.vo.DeviceStatusVo;
import com.zsc.edu.gateway.modules.iot.device.vo.DeviceVo; import com.zsc.edu.gateway.modules.iot.device.vo.DeviceVo;
import com.zsc.edu.gateway.modules.iot.product.entity.Product; import com.zsc.edu.gateway.modules.iot.product.entity.Product;
import com.zsc.edu.gateway.modules.iot.product.repo.ProductRepository; import com.zsc.edu.gateway.modules.iot.product.repo.ProductRepository;
import com.zsc.edu.gateway.modules.iot.tsl.dto.ParamDto;
import com.zsc.edu.gateway.modules.iot.tsl.entity.Param;
import com.zsc.edu.gateway.modules.iot.tsl.entity.Serve;
import com.zsc.edu.gateway.modules.iot.tsl.mapper.ParamMapper;
import com.zsc.edu.gateway.modules.iot.tsl.repo.EventRepository; import com.zsc.edu.gateway.modules.iot.tsl.repo.EventRepository;
import com.zsc.edu.gateway.modules.iot.tsl.repo.PropertyRepository; import com.zsc.edu.gateway.modules.iot.tsl.repo.PropertyRepository;
import com.zsc.edu.gateway.modules.iot.tsl.repo.ServeRepository; import com.zsc.edu.gateway.modules.iot.tsl.repo.ServeRepository;
import com.zsc.edu.gateway.modules.iot.tsl.service.ServeService;
import com.zsc.edu.gateway.modules.mqtt.config.MqttSender;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.configurationprocessor.json.JSONException;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -49,8 +58,14 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceRepository, Device> imp
private EventRepository eventRepo; private EventRepository eventRepo;
@Resource @Resource
private ServeRepository serveRepo; private ServeRepository serveRepo;
@Resource
private MqttSender mqttSender;
@Resource
private ServeService serveService;
@Resource
private DeviceRepository deviceRepo;
@Resource
private ParamMapper paramMapper;
/** /**
* 新建设备 * 新建设备
*/ */
@ -208,4 +223,42 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceRepository, Device> imp
vo.gatewaySubCount = productRepo.selectCount(new LambdaQueryWrapper<Product>().eq(Product::getLink, Product.LinkType.MQTT)); vo.gatewaySubCount = productRepo.selectCount(new LambdaQueryWrapper<Product>().eq(Product::getLink, Product.LinkType.MQTT));
return vo; return vo;
} }
@Override
public String send(Long deviceId, String topic, Integer qos) throws JSONException {
Device device = deviceRepo.selectOne(new LambdaQueryWrapper<Device>().eq(Device::getId, deviceId));
Serve serve1 = serveRepo.selectOne(new LambdaQueryWrapper<Serve>().eq(Serve::getProductId, device.getProductId()));
Serve serve = serveService.detail(serve1.getId());
List<Param> params = serve.getInputs();
params.addAll(serve.getOutputs());
JSONArray paramArray = new JSONArray();
for (Param param : params) {
JSONObject paramJson = new JSONObject();
paramJson.put("name", param.getName());
paramArray.add(paramJson);
}
JSONObject payloadJson = new JSONObject();
payloadJson.put("mid", 641);
payloadJson.put("serviceId", serve.getId());
payloadJson.put("deviceId", deviceId);
payloadJson.put("cmd", "runParam");
payloadJson.put("paras", paramArray);
payloadJson.put("msgType", "cloudReq");
String payload = payloadJson.toString();
boolean sendSuccess = true;
try {
mqttSender.sendMsg(topic, qos, payload);
} catch (Exception e) {
log.error("发送mqtt消息失败topic={}, qos={}, payload={}", topic, qos, payload, e);
sendSuccess = false;
}
JSONObject responseJson = new JSONObject();
responseJson.put("mid", 641);
responseJson.put("msgType", "deviceRsp");
responseJson.put("errcode", sendSuccess ? 0 : 1);
mqttSender.sendMsg(topic, qos, responseJson.toString());
log.info("发送mqtt消息成功topic={}, qos={}, payload={}", topic, qos, payload);
return responseJson.toString();
}
} }

View File

@ -43,30 +43,31 @@ public class Param extends BaseParam {
* 联表的id * 联表的id
*/ */
private Long foreignId; private Long foreignId;
public enum Type implements IEnum<Integer>, IState<Type> {
public enum Type implements IEnum<String>, IState<Type> {
/** /**
* 物模型输入 * 物模型输入
*/ */
INPUT(1, "Input"), INPUT("INPUT", "Input"),
/** /**
* 物模型输出 * 物模型输出
*/ */
OUTPUT(2, "Output"), OUTPUT("OUTPUT", "Output"),
/** /**
* 读写属性 * 读写属性
*/ */
RW(3, "Read Write"); RW("RW", "Read Write");
private final int value; private final String value;
private final String description; private final String description;
Type(int value, String description) { Type(String value, String description) {
this.value = value; this.value = value;
this.description = description; this.description = description;
} }
@Override @Override
public Integer getValue() { public String getValue() {
return value; return value;
} }
@ -84,7 +85,7 @@ public class Param extends BaseParam {
/** /**
* 服务 * 服务
*/ */
SERVE(2, "Service"), SERVE(2, "Serve"),
/** /**
* 产品 * 产品
*/ */

View File

@ -30,9 +30,9 @@ public class Serve extends BaseParam {
* 服务输入/输出参数根据param中的type区分 * 服务输入/输出参数根据param中的type区分
*/ */
@TableField(exist = false) @TableField(exist = false)
private List<ParamDto> inputs; private List<Param> inputs;
@TableField(exist = false) @TableField(exist = false)
private List<ParamDto> outputs; private List<Param> outputs;
} }

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zsc.edu.gateway.modules.iot.tsl.repo.ServeRepository"> <mapper namespace="com.zsc.edu.gateway.modules.iot.tsl.repo.ServeRepository">
<resultMap id="paramMap" type="com.zsc.edu.gateway.modules.iot.tsl.entity.Param"> <resultMap id="paramMap" type="com.zsc.edu.gateway.modules.iot.tsl.entity.Param">
<id column="param_id" property="id"/> <id column="param_id" property="id"/>
@ -62,8 +60,8 @@
ip.foreign_id, ip.foreign_id,
ip.foreign_type ip.foreign_type
FROM iot_param ip FROM iot_param ip
WHERE ip.foreign_type = 1 WHERE ip.foreign_type = 2
and ip.type = 1) input_params ON s.id = input_params.foreign_id and ip.type = 'INPUT') input_params ON s.id = input_params.foreign_id
LEFT JOIN (SELECT ip.id, LEFT JOIN (SELECT ip.id,
ip.data_type, ip.data_type,
ip.uint, ip.uint,
@ -74,8 +72,8 @@
ip.foreign_id, ip.foreign_id,
ip.foreign_type ip.foreign_type
FROM iot_param ip FROM iot_param ip
WHERE ip.foreign_type = 1 WHERE ip.foreign_type = 2
and ip.type = 2) output_params ON s.id = output_params.foreign_id and ip.type = 'OUTPUT') output_params ON s.id = output_params.foreign_id
WHERE s.id = #{id} WHERE s.id = #{id}
</select> </select>
</mapper> </mapper>