mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 15:13:55 +08:00
优化相关逻辑
This commit is contained in:
+18
-13
@@ -8,6 +8,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@@ -174,20 +175,26 @@ public class DeviceController {
|
||||
return new Result<Object>().ok(deviceAddressBookService.getAddressBookList(macAddress));
|
||||
}
|
||||
|
||||
@GetMapping("/address-book/lookup")
|
||||
@Operation(summary = "根据昵称查找目标设备")
|
||||
public Result<Map<String, String>> lookupByNickname(String callerMac, String nickname) {
|
||||
Map<String, String> result = deviceAddressBookService.lookupByNickname(callerMac, nickname);
|
||||
@GetMapping("/address-book/call")
|
||||
@Operation(summary = "根据昵称发起呼叫")
|
||||
public Result<Map<String, Object>> callByNickname(String callerMac, String nickname,
|
||||
@RequestParam(required = false, defaultValue = "false") boolean answer) {
|
||||
Map<String, Object> result = deviceAddressBookService.callByNickname(callerMac, nickname, answer);
|
||||
if (result == null) {
|
||||
return new Result<Map<String, String>>().error("未找到对应设备");
|
||||
return new Result<Map<String, Object>>().error("未找到对应设备");
|
||||
}
|
||||
return new Result<Map<String, String>>().ok(result);
|
||||
return new Result<Map<String, Object>>().ok(result);
|
||||
}
|
||||
|
||||
@PutMapping("/address-book/alias")
|
||||
@Operation(summary = "更新设备通讯录别名")
|
||||
@RequiresPermissions("sys:role:normal")
|
||||
public Result<Void> updateAlias(@Valid @RequestBody DeviceAddressBookAliasDTO dto) {
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
DeviceEntity callerDevice = deviceService.getDeviceByMacAddress(dto.getMacAddress());
|
||||
if (callerDevice == null || !callerDevice.getUserId().equals(user.getId())) {
|
||||
return new Result<Void>().error("无权限操作该设备");
|
||||
}
|
||||
deviceAddressBookService.saveOrUpdate(dto.getMacAddress(), dto.getTargetMac(), dto.getAlias(), null);
|
||||
return new Result<Void>();
|
||||
}
|
||||
@@ -196,14 +203,12 @@ public class DeviceController {
|
||||
@Operation(summary = "更新设备通讯录权限")
|
||||
@RequiresPermissions("sys:role:normal")
|
||||
public Result<Void> updatePermission(@Valid @RequestBody DeviceAddressBookPermissionDTO dto) {
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
DeviceEntity callerDevice = deviceService.getDeviceByMacAddress(dto.getMacAddress());
|
||||
if (callerDevice == null || !callerDevice.getUserId().equals(user.getId())) {
|
||||
return new Result<Void>().error("无权限操作该设备");
|
||||
}
|
||||
deviceAddressBookService.saveOrUpdate(dto.getMacAddress(), dto.getTargetMac(), null, dto.getHasPermission());
|
||||
return new Result<Void>();
|
||||
}
|
||||
|
||||
@GetMapping("/call/forward")
|
||||
@Operation(summary = "转发呼叫请求到网关")
|
||||
public Result<Map<String, Object>> forwardCallRequest(String callerMac, String targetMac, String callerNickname) {
|
||||
Map<String, Object> result = deviceService.forwardCallRequest(callerMac, targetMac, callerNickname);
|
||||
return new Result<Map<String, Object>>().ok(result);
|
||||
}
|
||||
}
|
||||
@@ -26,4 +26,9 @@ public interface DeviceAddressBookDao extends BaseMapper<DeviceAddressBookEntity
|
||||
* 更新权限
|
||||
*/
|
||||
void updatePermission(@Param("macAddress") String macAddress, @Param("targetMac") String targetMac, @Param("hasPermission") Boolean hasPermission);
|
||||
|
||||
/**
|
||||
* 批量删除设备相关的通讯录记录
|
||||
*/
|
||||
void deleteByMacAddresses(@Param("macAddresses") List<String> macAddresses);
|
||||
}
|
||||
+8
-3
@@ -38,10 +38,15 @@ public interface DeviceAddressBookService {
|
||||
void refreshCache();
|
||||
|
||||
/**
|
||||
* 根据昵称查找目标设备信息
|
||||
* 根据昵称发起呼叫
|
||||
* @param callerMac 主叫方MAC地址
|
||||
* @param nickname 被叫方昵称
|
||||
* @return {targetMac: 目标MAC, callerNickname: 目标如何称呼主叫方}
|
||||
* @param isAnswer 是否为接听模式(跳过权限检查)
|
||||
*/
|
||||
Map<String, String> lookupByNickname(String callerMac, String nickname);
|
||||
Map<String, Object> callByNickname(String callerMac, String nickname, boolean isAnswer);
|
||||
|
||||
/**
|
||||
* 批量删除设备相关的通讯录记录
|
||||
*/
|
||||
void deleteByMacAddresses(List<String> macAddresses);
|
||||
}
|
||||
@@ -138,10 +138,4 @@ public interface DeviceService extends BaseService<DeviceEntity> {
|
||||
*/
|
||||
Object callDeviceTool(String deviceId, String toolName, Map<String, Object> arguments);
|
||||
|
||||
/**
|
||||
* 转发呼叫请求到网关
|
||||
* @return 网关响应 {status, message}
|
||||
*/
|
||||
Map<String, Object> forwardCallRequest(String callerMac, String targetMac, String callerNickname);
|
||||
|
||||
}
|
||||
}
|
||||
+150
-33
@@ -1,20 +1,27 @@
|
||||
package xiaozhi.modules.device.service.impl;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import xiaozhi.common.redis.RedisKeys;
|
||||
import xiaozhi.common.redis.RedisUtils;
|
||||
import xiaozhi.modules.device.dao.DeviceAddressBookDao;
|
||||
import xiaozhi.modules.device.entity.DeviceAddressBookEntity;
|
||||
import xiaozhi.modules.device.service.DeviceAddressBookService;
|
||||
import xiaozhi.modules.device.service.DeviceService;
|
||||
import xiaozhi.modules.sys.service.SysParamsService;
|
||||
|
||||
@Service
|
||||
public class DeviceAddressBookServiceImpl implements DeviceAddressBookService {
|
||||
@@ -22,12 +29,14 @@ public class DeviceAddressBookServiceImpl implements DeviceAddressBookService {
|
||||
private final DeviceAddressBookDao deviceAddressBookDao;
|
||||
private final RedisUtils redisUtils;
|
||||
private final DeviceService deviceService;
|
||||
private final SysParamsService sysParamsService;
|
||||
|
||||
public DeviceAddressBookServiceImpl(DeviceAddressBookDao deviceAddressBookDao, RedisUtils redisUtils,
|
||||
DeviceService deviceService) {
|
||||
@Lazy DeviceService deviceService, SysParamsService sysParamsService) {
|
||||
this.deviceAddressBookDao = deviceAddressBookDao;
|
||||
this.redisUtils = redisUtils;
|
||||
this.deviceService = deviceService;
|
||||
this.sysParamsService = sysParamsService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,33 +56,46 @@ public class DeviceAddressBookServiceImpl implements DeviceAddressBookService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> lookupByNickname(String callerMac, String nickname) {
|
||||
public Map<String, Object> callByNickname(String callerMac, String nickname, boolean isAnswer) {
|
||||
Map<String, Map<String, String>> allBooks = getAllAddressBooks();
|
||||
|
||||
if (isAnswer) {
|
||||
return postToMqtt("/api/call/accept", Map.of("mac", callerMac), "接听");
|
||||
}
|
||||
|
||||
// 主动呼叫模式
|
||||
Map<String, String> callerBook = allBooks.get(callerMac.toLowerCase());
|
||||
if (callerBook == null) {
|
||||
return null;
|
||||
return errorResult("未找到备注为'" + nickname + "'的设备");
|
||||
}
|
||||
// 从缓存获取 targetMac,格式: "mac|permission"
|
||||
String targetMacWithPerm = callerBook.get(nickname);
|
||||
if (targetMacWithPerm == null) {
|
||||
return null;
|
||||
return errorResult("未找到备注为'" + nickname + "'的设备");
|
||||
}
|
||||
// 解析 targetMac 和 permission
|
||||
String[] parts = targetMacWithPerm.split("\\|");
|
||||
String targetMac = parts[0];
|
||||
boolean hasPermission = parts.length > 1 && "1".equals(parts[1]);
|
||||
|
||||
Map<String, String> targetBook = allBooks.get(targetMac.toLowerCase());
|
||||
if (targetBook == null) {
|
||||
return null;
|
||||
if (!hasPermission) {
|
||||
return errorResult("呼叫失败,您没有权限呼叫该设备");
|
||||
}
|
||||
// 检查双向关系:目标设备是否也添加了主叫方为联系人
|
||||
String callerNickname = targetBook.get(callerMac.toLowerCase());
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("targetMac", targetMac);
|
||||
result.put("callerNickname", callerNickname);
|
||||
result.put("hasPermission", hasPermission ? "true" : "false");
|
||||
return result;
|
||||
|
||||
// 获取目标设备如何称呼主叫方
|
||||
Map<String, String> targetBook = allBooks.get(targetMac.toLowerCase());
|
||||
String callerNickname = null;
|
||||
if (targetBook != null) {
|
||||
callerNickname = targetBook.get(callerMac.toLowerCase());
|
||||
}
|
||||
if (StringUtils.isBlank(callerNickname)) {
|
||||
callerNickname = deviceService.getDeviceByMacAddress(callerMac).getAlias();
|
||||
if (StringUtils.isBlank(callerNickname)) {
|
||||
callerNickname = formatMacAsDeviceName(callerMac);
|
||||
}
|
||||
}
|
||||
|
||||
return postToMqtt("/api/call/request",
|
||||
Map.of("caller_mac", callerMac, "target_mac", targetMac, "caller_nickname", callerNickname),
|
||||
"呼叫");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,43 +103,44 @@ public class DeviceAddressBookServiceImpl implements DeviceAddressBookService {
|
||||
Map<String, Map<String, String>> result = new HashMap<>();
|
||||
List<DeviceAddressBookEntity> allRecords = deviceAddressBookDao.selectList(null);
|
||||
Map<String, String> reverseMap = new HashMap<>();
|
||||
Map<String, Boolean> permissionMap = new HashMap<>();
|
||||
|
||||
for (DeviceAddressBookEntity entity : allRecords) {
|
||||
String macA = entity.getMacAddress().toLowerCase();
|
||||
String macB = entity.getTargetMac().toLowerCase();
|
||||
String alias = entity.getAlias();
|
||||
Boolean hasPermission = entity.getHasPermission();
|
||||
|
||||
// 构建正向映射: A对B的映射 nickname -> macB|permission
|
||||
if (alias != null && !alias.isEmpty()) {
|
||||
result.computeIfAbsent(macA, k -> new HashMap<>());
|
||||
String permStr = (hasPermission != null && hasPermission) ? "1" : "0";
|
||||
result.get(macA).put(alias, macB + "|" + permStr);
|
||||
}
|
||||
|
||||
// 构建反向记录用于查找B对A的称呼
|
||||
if (alias != null && !alias.isEmpty()) {
|
||||
// 反向记录: (macB, macA) = B对A的称呼
|
||||
reverseMap.put(macB + ":" + macA, alias);
|
||||
}
|
||||
// 记录 A 对 B 是否有权限呼叫
|
||||
permissionMap.put(macA + ":" + macB, hasPermission != null && hasPermission);
|
||||
}
|
||||
|
||||
// 构建反向映射: B对A的映射 macA -> nickname
|
||||
for (DeviceAddressBookEntity entity : allRecords) {
|
||||
String macA = entity.getMacAddress().toLowerCase();
|
||||
String macB = entity.getTargetMac().toLowerCase();
|
||||
String aliasAtoB = entity.getAlias();
|
||||
result.computeIfAbsent(macA, k -> new HashMap<>());
|
||||
result.computeIfAbsent(macB, k -> new HashMap<>());
|
||||
if (aliasAtoB != null && !aliasAtoB.isEmpty()) {
|
||||
// A对B的映射: nickname -> macB|permission
|
||||
Boolean perm = entity.getHasPermission();
|
||||
String permStr = (perm != null && perm) ? "1" : "0";
|
||||
result.get(macA).put(aliasAtoB, macB + "|" + permStr);
|
||||
}
|
||||
// B对A的映射: macA -> nickname(查反向记录)
|
||||
String aliasBtoA = reverseMap.get(macA + ":" + macB);
|
||||
if (aliasBtoA != null && !aliasBtoA.isEmpty()) {
|
||||
result.computeIfAbsent(macB, k -> new HashMap<>());
|
||||
result.get(macB).put(macA, aliasBtoA);
|
||||
}
|
||||
}
|
||||
|
||||
redisUtils.set(RedisKeys.getAddressBookKey(), result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAlias(String macAddress, String targetMac, String alias) {
|
||||
deviceAddressBookDao.updateAlias(macAddress, targetMac, alias);
|
||||
String finalAlias = generateUniqueAlias(macAddress, targetMac, alias);
|
||||
deviceAddressBookDao.updateAlias(macAddress, targetMac, finalAlias);
|
||||
refreshCache();
|
||||
}
|
||||
|
||||
@@ -132,20 +155,23 @@ public class DeviceAddressBookServiceImpl implements DeviceAddressBookService {
|
||||
QueryWrapper<DeviceAddressBookEntity> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("mac_address", macAddress).eq("target_mac", targetMac);
|
||||
DeviceAddressBookEntity record = deviceAddressBookDao.selectOne(wrapper);
|
||||
System.out.println("saveOrUpdate - mac=" + macAddress + ", targetMac=" + targetMac + ", alias=" + alias + ", record=" + (record == null ? "null" : "not null"));
|
||||
if (record == null) {
|
||||
DeviceAddressBookEntity entity = new DeviceAddressBookEntity();
|
||||
entity.setMacAddress(macAddress);
|
||||
entity.setTargetMac(targetMac);
|
||||
// 如果 alias 为空,就用默认使用设备名称
|
||||
// 如果 alias 为空,就默认使用设备名称
|
||||
if (StringUtils.isBlank(alias)) {
|
||||
alias = deviceService.getDeviceByMacAddress(targetMac).getAlias();
|
||||
}
|
||||
// 检查重名
|
||||
alias = generateUniqueAlias(macAddress, targetMac, alias);
|
||||
entity.setAlias(alias);
|
||||
entity.setHasPermission(hasPermission);
|
||||
deviceAddressBookDao.insert(entity);
|
||||
} else {
|
||||
if (alias != null) {
|
||||
deviceAddressBookDao.updateAlias(macAddress, targetMac, alias);
|
||||
updateAlias(macAddress, targetMac, alias);
|
||||
}
|
||||
if (hasPermission != null) {
|
||||
deviceAddressBookDao.updatePermission(macAddress, targetMac, hasPermission);
|
||||
@@ -153,4 +179,95 @@ public class DeviceAddressBookServiceImpl implements DeviceAddressBookService {
|
||||
}
|
||||
refreshCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteByMacAddresses(List<String> macAddresses) {
|
||||
if (macAddresses == null || macAddresses.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
deviceAddressBookDao.deleteByMacAddresses(macAddresses);
|
||||
refreshCache();
|
||||
}
|
||||
|
||||
private Map<String, Object> errorResult(String message) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("status", "error");
|
||||
result.put("message", message);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, Object> postToMqtt(String path, Map<String, Object> body, String action) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("status", "error");
|
||||
|
||||
String mqttGatewayUrl = sysParamsService.getValue("server.mqtt_manager_api", true);
|
||||
String mqttSignatureKey = sysParamsService.getValue("server.mqtt_signature_key", true);
|
||||
|
||||
if (StringUtils.isBlank(mqttGatewayUrl) || "null".equals(mqttGatewayUrl)
|
||||
|| StringUtils.isBlank(mqttSignatureKey) || "null".equals(mqttSignatureKey)) {
|
||||
result.put("message", action + "失败,网关配置缺失");
|
||||
return result;
|
||||
}
|
||||
|
||||
String dateStr = new java.text.SimpleDateFormat("yyyy-MM-dd").format(new Date());
|
||||
try {
|
||||
java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
|
||||
byte[] hash = md.digest((dateStr + mqttSignatureKey).getBytes(StandardCharsets.UTF_8));
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : hash) {
|
||||
String hex = Integer.toHexString(0xff & b);
|
||||
if (hex.length() == 1) {
|
||||
hexString.append('0');
|
||||
}
|
||||
hexString.append(hex);
|
||||
}
|
||||
String token = hexString.toString();
|
||||
|
||||
String url = "http://" + mqttGatewayUrl + path;
|
||||
String response = HttpRequest.post(url)
|
||||
.header("Authorization", "Bearer " + token)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(JSONUtil.toJsonStr(body))
|
||||
.timeout(5000)
|
||||
.execute()
|
||||
.body();
|
||||
|
||||
if (StringUtils.isNotBlank(response)) {
|
||||
Map<String, Object> gwResult = JSONUtil.parseObj(response);
|
||||
result.put("status", gwResult.get("status"));
|
||||
result.put("message", gwResult.get("message"));
|
||||
}
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
result.put("message", action + "失败,请稍后再试");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private String formatMacAsDeviceName(String mac) {
|
||||
if (StringUtils.isBlank(mac) || mac.length() < 2) {
|
||||
return mac;
|
||||
}
|
||||
String lastTwo = mac.substring(mac.length() - 2);
|
||||
return "尾号为" + lastTwo + "的设备";
|
||||
}
|
||||
|
||||
private String generateUniqueAlias(String macAddress, String targetMac, String alias) {
|
||||
QueryWrapper<DeviceAddressBookEntity> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("mac_address", macAddress);
|
||||
List<DeviceAddressBookEntity> existing = deviceAddressBookDao.selectList(wrapper);
|
||||
List<String> existNames = existing.stream()
|
||||
.map(DeviceAddressBookEntity::getAlias)
|
||||
.filter(a -> a != null && !a.isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
if (!existNames.contains(alias)) {
|
||||
return alias;
|
||||
}
|
||||
int suffix = 1;
|
||||
String newAlias;
|
||||
while (existNames.contains(newAlias = alias + suffix)) {
|
||||
suffix++;
|
||||
}
|
||||
return newAlias;
|
||||
}
|
||||
}
|
||||
+22
-67
@@ -6,6 +6,7 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -63,6 +64,7 @@ import xiaozhi.modules.device.dto.DeviceReportReqDTO;
|
||||
import xiaozhi.modules.device.dto.DeviceReportRespDTO;
|
||||
import xiaozhi.modules.device.entity.DeviceEntity;
|
||||
import xiaozhi.modules.device.entity.OtaEntity;
|
||||
import xiaozhi.modules.device.service.DeviceAddressBookService;
|
||||
import xiaozhi.modules.device.service.DeviceService;
|
||||
import xiaozhi.modules.device.service.OtaService;
|
||||
import xiaozhi.modules.device.vo.UserShowDeviceListVO;
|
||||
@@ -80,6 +82,7 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
|
||||
private final SysParamsService sysParamsService;
|
||||
private final RedisUtils redisUtils;
|
||||
private final OtaService otaService;
|
||||
private final DeviceAddressBookService deviceAddressBookService;
|
||||
|
||||
@Async
|
||||
public void updateDeviceConnectionInfo(String agentId, String deviceId, String appVersion) {
|
||||
@@ -314,11 +317,12 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
|
||||
|
||||
@Override
|
||||
public void unbindDevice(Long userId, String deviceId) {
|
||||
// 先查询设备信息,获取agentId
|
||||
// 先查询设备信息,获取agentId和macAddress
|
||||
DeviceEntity device = baseDao.selectById(deviceId);
|
||||
if (device == null) {
|
||||
return;
|
||||
}
|
||||
String macAddress = device.getMacAddress();
|
||||
if (StringUtils.isNotBlank(device.getAgentId())) {
|
||||
// 清除智能体设备数量缓存
|
||||
redisUtils.delete(RedisKeys.getAgentDeviceCountById(device.getAgentId()));
|
||||
@@ -328,6 +332,9 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
|
||||
wrapper.eq("user_id", userId);
|
||||
wrapper.eq("id", deviceId);
|
||||
baseDao.delete(wrapper);
|
||||
|
||||
// 删除设备相关的通讯录权限记录
|
||||
deviceAddressBookService.deleteByMacAddresses(Collections.singletonList(macAddress));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -346,9 +353,23 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
|
||||
|
||||
@Override
|
||||
public void deleteByAgentId(String agentId) {
|
||||
// 先查询该智能体下的所有设备,获取mac地址用于删除通讯录记录
|
||||
QueryWrapper<DeviceEntity> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("agent_id", agentId);
|
||||
List<DeviceEntity> devices = baseDao.selectList(queryWrapper);
|
||||
|
||||
// 删除设备
|
||||
UpdateWrapper<DeviceEntity> wrapper = new UpdateWrapper<>();
|
||||
wrapper.eq("agent_id", agentId);
|
||||
baseDao.delete(wrapper);
|
||||
|
||||
// 批量删除这些设备相关的所有通讯录权限记录
|
||||
if (!devices.isEmpty()) {
|
||||
List<String> macAddresses = devices.stream()
|
||||
.map(DeviceEntity::getMacAddress)
|
||||
.collect(Collectors.toList());
|
||||
deviceAddressBookService.deleteByMacAddresses(macAddresses);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -891,70 +912,4 @@ public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity>
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> forwardCallRequest(String callerMac, String targetMac, String callerNickname) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("status", "error");
|
||||
result.put("message", "网关配置缺失");
|
||||
|
||||
// 从系统参数获取网关配置
|
||||
String mqttGatewayUrl = sysParamsService.getValue("server.mqtt_manager_api", true);
|
||||
String mqttSignatureKey = sysParamsService.getValue("server.mqtt_signature_key", true);
|
||||
|
||||
if (StringUtils.isBlank(mqttGatewayUrl) || "null".equals(mqttGatewayUrl)) {
|
||||
log.error("MQTT网关地址未配置");
|
||||
result.put("message", "MQTT网关地址未配置");
|
||||
return result;
|
||||
}
|
||||
if (StringUtils.isBlank(mqttSignatureKey) || "null".equals(mqttSignatureKey)) {
|
||||
log.error("MQTT签名密钥未配置");
|
||||
result.put("message", "MQTT签名密钥未配置");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 生成token: SHA256(date + secret)
|
||||
String dateStr = new java.text.SimpleDateFormat("yyyy-MM-dd").format(new Date());
|
||||
try {
|
||||
java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
|
||||
byte[] hash = md.digest((dateStr + mqttSignatureKey).getBytes(StandardCharsets.UTF_8));
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : hash) {
|
||||
String hex = Integer.toHexString(0xff & b);
|
||||
if (hex.length() == 1) {
|
||||
hexString.append('0');
|
||||
}
|
||||
hexString.append(hex);
|
||||
}
|
||||
String token = hexString.toString();
|
||||
|
||||
// 构建请求体
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("caller_mac", callerMac);
|
||||
body.put("target_mac", targetMac);
|
||||
body.put("caller_nickname", callerNickname);
|
||||
|
||||
// 发送请求并获取响应
|
||||
String url = "http://" + mqttGatewayUrl + "/api/call/request";
|
||||
String response = cn.hutool.http.HttpRequest.post(url)
|
||||
.header("Authorization", "Bearer " + token)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(JSONUtil.toJsonStr(body))
|
||||
.timeout(5000)
|
||||
.execute()
|
||||
.body();
|
||||
|
||||
// 解析网关响应
|
||||
if (StringUtils.isNotBlank(response)) {
|
||||
Map<String, Object> gwResult = JSONUtil.parseObj(response);
|
||||
result.put("status", gwResult.get("status"));
|
||||
result.put("message", gwResult.get("message"));
|
||||
}
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("转发呼叫请求失败: {}", e.getMessage());
|
||||
result.put("message", "呼叫请求转发失败: " + e.getMessage());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,8 +87,7 @@ public class ShiroConfig {
|
||||
filterMap.put("/user/retrieve-password", "anon");
|
||||
// 将config路径使用server服务过滤器
|
||||
filterMap.put("/config/**", "server");
|
||||
filterMap.put("/device/address-book/lookup", "server");
|
||||
filterMap.put("/device/call/forward", "server");
|
||||
filterMap.put("/device/address-book/call", "server");
|
||||
filterMap.put("/agent/chat-history/report", "server");
|
||||
filterMap.put("/agent/chat-history/download/**", "anon");
|
||||
filterMap.put("/agent/chat-summary/**", "server");
|
||||
|
||||
@@ -25,4 +25,15 @@
|
||||
INSERT INTO ai_device_address_book (mac_address, target_mac, alias, has_permission, creator, create_date, updater, update_date)
|
||||
VALUES (#{macAddress}, #{targetMac}, #{alias}, #{hasPermission}, #{creator}, NOW(), #{updater}, NOW())
|
||||
</insert>
|
||||
|
||||
<delete id="deleteByMacAddresses">
|
||||
DELETE FROM ai_device_address_book WHERE mac_address IN
|
||||
<foreach collection="macAddresses" item="mac" open="(" separator="," close=")">
|
||||
#{mac}
|
||||
</foreach>
|
||||
OR target_mac IN
|
||||
<foreach collection="macAddresses" item="mac" open="(" separator="," close=")">
|
||||
#{mac}
|
||||
</foreach>
|
||||
</delete>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user