update:接口

This commit is contained in:
FAN-yeB
2025-09-17 10:04:19 +08:00
parent 03b51f73e7
commit 15ca08ce14
4 changed files with 166 additions and 7 deletions
@@ -29,15 +29,31 @@ import xiaozhi.modules.device.dto.DeviceManualAddDTO;
import xiaozhi.modules.device.entity.DeviceEntity;
import xiaozhi.modules.device.service.DeviceService;
import xiaozhi.modules.security.user.SecurityUser;
import xiaozhi.modules.sys.service.SysParamsService;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import com.fasterxml.jackson.databind.ObjectMapper;
@Tag(name = "设备管理")
@AllArgsConstructor
@RestController
@RequestMapping("/device")
public class DeviceController {
private final DeviceService deviceService;
private final RedisUtils redisUtils;
private final SysParamsService sysParamsService;
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
public DeviceController(DeviceService deviceService, RedisUtils redisUtils, SysParamsService sysParamsService, RestTemplate restTemplate, ObjectMapper objectMapper) {
this.deviceService = deviceService;
this.redisUtils = redisUtils;
this.sysParamsService = sysParamsService;
this.restTemplate = restTemplate;
this.objectMapper = objectMapper;
}
@PostMapping("/bind/{agentId}/{deviceCode}")
@Operation(summary = "绑定设备")
@@ -75,6 +91,87 @@ public class DeviceController {
return new Result<List<DeviceEntity>>().ok(devices);
}
@PostMapping("/bind/{agentId}")
@Operation(summary = "转发POST请求到MQTT网关")
@RequiresPermissions("sys:role:normal")
public Result<String> forwardToMqttGateway(@PathVariable String agentId, @RequestBody String requestBody) {
try {
// 从系统参数中获取MQTT网关地址
String mqttGatewayUrl = sysParamsService.getValue("server.mqtt_manager_api", true);
if (StringUtils.isBlank(mqttGatewayUrl)) {
return new Result<String>().error("MQTT网关地址未配置");
}
// 获取当前用户的设备列表
UserDetail user = SecurityUser.getUser();
List<DeviceEntity> devices = deviceService.getUserDevices(user.getId(), agentId);
// 构建deviceIds数组
java.util.List<String> deviceIds = new java.util.ArrayList<>();
for (DeviceEntity device : devices) {
String macAddress = device.getMacAddress() != null ? device.getMacAddress() : "unknown";
String groupId = device.getBoard() != null ? device.getBoard() : "GID_default";
// 替换冒号为下划线
groupId = groupId.replace(":", "_");
macAddress = macAddress.replace(":", "_");
// 构建mqtt客户端ID格式:groupId@@@macAddress@@@macAddress
String mqttClientId = groupId + "@@@" + macAddress + "@@@" + macAddress;
deviceIds.add(mqttClientId);
}
// 构建完整的URL
String url = "http://" + mqttGatewayUrl + "/api/devices/status";
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
// 生成Bearer令牌
String token = generateBearerToken();
if (token == null) {
return new Result<String>().error("令牌生成失败");
}
headers.set("Authorization", "Bearer " + token);
// 构建请求体JSON
String jsonBody = "{\"deviceIds\":" + objectMapper.writeValueAsString(deviceIds) + "}";
HttpEntity<String> requestEntity = new HttpEntity<>(jsonBody, headers);
// 发送POST请求
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
// 返回响应
return new Result<String>().ok(response.getBody());
} catch (Exception e) {
return new Result<String>().error("转发请求失败: " + e.getMessage());
}
}
private String generateBearerToken() {
try {
// 获取当前日期,格式为yyyy-MM-dd
String dateStr = java.time.LocalDate.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// 获取MQTT签名密钥
String signatureKey = sysParamsService.getValue("server.mqtt_signature_key", false);
if (StringUtils.isBlank(signatureKey)) {
return null;
}
// 将日期字符串与MQTT_SIGNATURE_KEY连接
String tokenContent = dateStr + signatureKey;
// 对连接后的字符串进行SHA256哈希计算
String token = org.apache.commons.codec.digest.DigestUtils.sha256Hex(tokenContent);
return token;
} catch (Exception e) {
return null;
}
}
@PostMapping("/unbind")
@Operation(summary = "解绑设备")
@RequiresPermissions("sys:role:normal")
@@ -109,4 +206,58 @@ public class DeviceController {
deviceService.manualAddDevice(user.getId(), dto);
return new Result<>();
}
@PostMapping("/commands/{deviceId}")
@Operation(summary = "发送设备指令")
@RequiresPermissions("sys:role:normal")
public Result<String> sendDeviceCommand(@PathVariable String deviceId, @RequestBody String command) {
try {
// 从系统参数中获取MQTT网关地址
String mqttGatewayUrl = sysParamsService.getValue("server.mqtt_manager_api", true);
if (StringUtils.isBlank(mqttGatewayUrl)) {
return new Result<String>().error("MQTT网关地址未配置");
}
// 构建完整的URL
// 获取设备信息以构建mqttClientId
DeviceEntity deviceById = deviceService.selectById(deviceId);
String macAddress = deviceById != null ? deviceById.getMacAddress() : "unknown";
String groupId = deviceById != null ? deviceById.getBoard() : null;
if (groupId == null) {
groupId = "GID_default";
}
groupId = groupId.replace(":", "_");
macAddress = macAddress.replace(":", "_");
// 拼接为groupId@@@macAddress@@@deviceId格式
String mqttClientId = groupId + "@@@" + macAddress + "@@@" + macAddress;
String url = "http://" + mqttGatewayUrl + "/api/commands/" + mqttClientId;
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
// 生成Bearer令牌
String dateStr = java.time.LocalDate.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String signatureKey = sysParamsService.getValue("server.mqtt_signature_key", false);
if (StringUtils.isBlank(signatureKey)) {
return new Result<String>().error("MQTT签名密钥未配置");
}
String tokenContent = dateStr + signatureKey;
String token = org.apache.commons.codec.digest.DigestUtils.sha256Hex(tokenContent);
headers.set("Authorization", "Bearer " + token);
// 构建请求体
HttpEntity<String> requestEntity = new HttpEntity<>(command, headers);
// 发送POST请求
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
// 返回响应
return new Result<String>().ok(response.getBody());
} catch (Exception e) {
return new Result<String>().error("发送指令失败: " + e.getMessage());
}
}
}
@@ -188,7 +188,7 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
try {
String groupId = deviceById != null && deviceById.getBoard() != null ? deviceById.getBoard()
: "GID_default";
DeviceReportRespDTO.MQTT mqtt = buildMqttConfig(macAddress, clientId, groupId);
DeviceReportRespDTO.MQTT mqtt = buildMqttConfig(macAddress, groupId);
if (mqtt != null) {
mqtt.setEndpoint(mqttUdpConfig);
response.setMqtt(mqtt);
@@ -479,11 +479,10 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
* 构建MQTT配置信息
*
* @param macAddress MAC地址
* @param clientId 客户端ID (UUID)
* @param groupId 分组ID
* @return MQTT配置对象
*/
private DeviceReportRespDTO.MQTT buildMqttConfig(String macAddress, String clientId, String groupId)
private DeviceReportRespDTO.MQTT buildMqttConfig(String macAddress, String groupId)
throws Exception {
// 从环境变量或系统参数获取签名密钥
String signatureKey = sysParamsService.getValue("server.mqtt_signature_key", false);
@@ -495,8 +494,7 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
// 构建客户端ID格式:groupId@@@macAddress@@@uuid
String groupIdSafeStr = groupId.replace(":", "_");
String deviceIdSafeStr = macAddress.replace(":", "_");
String clientIdSafeStr = clientId.replace(":", "_");
String mqttClientId = String.format("%s@@@%s@@@%s", groupIdSafeStr, deviceIdSafeStr, clientIdSafeStr);
String mqttClientId = String.format("%s@@@%s@@@%s", groupIdSafeStr, deviceIdSafeStr, deviceIdSafeStr);
// 构建用户数据(包含IP等信息)
Map<String, String> userData = new HashMap<>();
@@ -0,0 +1,3 @@
delete from `sys_params` where param_code = 'server.mqtt_manager_api';
INSERT INTO `sys_params` (id, param_code, param_value, value_type, param_type, remark)
VALUES (119, 'server.mqtt_manager_api', null, 'string', 1, 'MQTT网关管理API的地址');
@@ -345,3 +345,10 @@ databaseChangeLog:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202509080922.sql
- changeSet:
id: 202509161609
author: fyb
changes:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202509161609.sql