Merge branch 'device-microservice'
All checks were successful
ZhenTu-BE/pipeline/head This commit looks good

This commit is contained in:
2025-09-04 12:38:29 +08:00
6 changed files with 321 additions and 0 deletions

View File

@@ -76,4 +76,11 @@ public interface DeviceV2Client {
@RequestParam(value = "type", required = false) String type,
@RequestParam(value = "isActive", required = false) Integer isActive,
@RequestParam(value = "scenicId", required = false) Long scenicId);
/**
* 根据配置条件筛选设备
*/
@PostMapping("/filter-by-configs")
CommonResponse<FilterDevicesByConfigsResponse> filterDevicesByConfigs(
@RequestBody FilterDevicesByConfigsRequest request);
}

View File

@@ -0,0 +1,29 @@
package com.ycwl.basic.integration.device.dto.device;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 配置筛选条件
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ConfigFilter {
/**
* 配置键名
*/
private String configKey;
/**
* 配置值(某些操作符不需要,如 is_null、is_not_null)
*/
private Object configValue;
/**
* 比较操作符
* 支持: eq, ne, like, gt, lt, gte, lte, in, not_in, is_null, is_not_null
*/
private String operator;
}

View File

@@ -0,0 +1,41 @@
package com.ycwl.basic.integration.device.dto.device;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
/**
* 根据配置筛选设备请求
*/
@Data
@NoArgsConstructor
public class FilterDevicesByConfigsRequest {
/**
* 页码,默认1
*/
private Integer page = 1;
/**
* 每页数量,默认10
*/
private Integer pageSize = 10;
/**
* 配置筛选条件列表,至少包含一个条件
*/
private List<ConfigFilter> configFilters;
/**
* 多个条件间的逻辑关系,默认"AND"
* 支持: "AND", "OR"
*/
private String filterLogic = "AND";
/**
* 设备基本信息筛选条件
* 可包含: name, no, type, isActive, scenicId
*/
private Map<String, Object> deviceFilters;
}

View File

@@ -0,0 +1,31 @@
package com.ycwl.basic.integration.device.dto.device;
import lombok.Data;
import java.util.List;
/**
* 根据配置筛选设备响应数据
*/
@Data
public class FilterDevicesByConfigsResponse {
/**
* 设备列表
*/
private List<DeviceV2WithConfigDTO> list;
/**
* 总数
*/
private String total;
/**
* 页码
*/
private Integer page;
/**
* 每页数量
*/
private Integer pageSize;
}

View File

@@ -0,0 +1,190 @@
package com.ycwl.basic.integration.device.example;
import com.ycwl.basic.integration.device.dto.device.*;
import com.ycwl.basic.integration.device.service.DeviceIntegrationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 设备配置筛选功能使用示例
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class DeviceFilterExample {
private final DeviceIntegrationService deviceIntegrationService;
/**
* 示例1: 查找高质量户外IPC设备
* 条件: 分辨率1920x1080,帧率>=30,位置包含"outdoor"
*/
public void findHighQualityOutdoorDevices() {
log.info("=== 查找高质量户外IPC设备 ===");
List<ConfigFilter> configFilters = Arrays.asList(
new ConfigFilter("resolution", "1920x1080", "eq"),
new ConfigFilter("framerate", 30, "gte"),
new ConfigFilter("location", "outdoor", "like")
);
Map<String, Object> deviceFilters = new HashMap<>();
deviceFilters.put("type", "IPC");
deviceFilters.put("isActive", 1);
FilterDevicesByConfigsRequest request = new FilterDevicesByConfigsRequest();
request.setPage(1);
request.setPageSize(20);
request.setConfigFilters(configFilters);
request.setFilterLogic("AND");
request.setDeviceFilters(deviceFilters);
try {
FilterDevicesByConfigsResponse response = deviceIntegrationService.filterDevicesByConfigs(request);
log.info("找到 {} 个高质量户外IPC设备", response.getTotal());
response.getList().forEach(device -> {
log.info("设备: {} ({}), 配置: {}", device.getName(), device.getNo(), device.getConfig());
});
} catch (Exception e) {
log.error("查找高质量户外IPC设备失败", e);
}
}
/**
* 示例2: 查找缺少关键配置的设备
* 条件: 缺少备份服务器或夜视功能配置
*/
public void findDevicesWithMissingConfigs() {
log.info("=== 查找缺少关键配置的设备 ===");
List<ConfigFilter> configFilters = Arrays.asList(
new ConfigFilter("backup_server", null, "is_null"),
new ConfigFilter("night_vision", null, "is_null")
);
FilterDevicesByConfigsRequest request = new FilterDevicesByConfigsRequest();
request.setConfigFilters(configFilters);
request.setFilterLogic("OR"); // 缺少任一配置即返回
request.setPageSize(50);
try {
FilterDevicesByConfigsResponse response = deviceIntegrationService.filterDevicesByConfigs(request);
log.info("找到 {} 个缺少关键配置的设备", response.getTotal());
response.getList().forEach(device -> {
Map<String, Object> config = device.getConfig();
boolean missingBackup = !config.containsKey("backup_server") || config.get("backup_server") == null;
boolean missingNightVision = !config.containsKey("night_vision") || config.get("night_vision") == null;
log.info("设备: {} ({}), 缺少配置: {}{}",
device.getName(), device.getNo(),
missingBackup ? "备份服务器 " : "",
missingNightVision ? "夜视功能 " : "");
});
} catch (Exception e) {
log.error("查找缺少关键配置的设备失败", e);
}
}
/**
* 示例3: 根据多个位置查找设备
* 条件: 位置在指定列表中
*/
public void findDevicesByMultipleLocations() {
log.info("=== 根据多个位置查找设备 ===");
List<String> locations = Arrays.asList("outdoor", "indoor", "parking");
List<ConfigFilter> configFilters = Arrays.asList(
new ConfigFilter("location", locations, "in")
);
FilterDevicesByConfigsRequest request = new FilterDevicesByConfigsRequest();
request.setConfigFilters(configFilters);
request.setPageSize(100);
try {
FilterDevicesByConfigsResponse response = deviceIntegrationService.filterDevicesByConfigs(request);
log.info("找到 {} 个设备在指定位置", response.getTotal());
response.getList().forEach(device -> {
Object location = device.getConfig().get("location");
log.info("设备: {} ({}), 位置: {}", device.getName(), device.getNo(), location);
});
} catch (Exception e) {
log.error("根据多个位置查找设备失败", e);
}
}
/**
* 示例4: 使用便捷方法查找设备
*/
public void useConvenienceMethods() {
log.info("=== 使用便捷方法查找设备 ===");
try {
// 查找缺少配置的设备
FilterDevicesByConfigsResponse response4 = deviceIntegrationService
.findDevicesWithMissingConfig("firmware_version", 1, 10);
log.info("缺少固件版本配置的设备数: {}", response4.getTotal());
} catch (Exception e) {
log.error("使用便捷方法查找设备失败", e);
}
}
/**
* 示例5: 性能监控查询
* 条件: CPU使用率>80% 或 内存使用率>85%
*/
public void findHighLoadDevices() {
log.info("=== 查找高负载设备 ===");
List<ConfigFilter> configFilters = Arrays.asList(
new ConfigFilter("cpu_usage", 80, "gt"),
new ConfigFilter("memory_usage", 85, "gt")
);
FilterDevicesByConfigsRequest request = new FilterDevicesByConfigsRequest();
request.setConfigFilters(configFilters);
request.setFilterLogic("OR");
request.setPageSize(50);
try {
FilterDevicesByConfigsResponse response = deviceIntegrationService.filterDevicesByConfigs(request);
log.info("找到 {} 个高负载设备", response.getTotal());
response.getList().forEach(device -> {
Map<String, Object> config = device.getConfig();
Object cpuUsage = config.get("cpu_usage");
Object memoryUsage = config.get("memory_usage");
log.info("高负载设备: {} ({}), CPU: {}%, 内存: {}%",
device.getName(), device.getNo(), cpuUsage, memoryUsage);
});
} catch (Exception e) {
log.error("查找高负载设备失败", e);
}
}
/**
* 运行所有示例
*/
public void runAllExamples() {
log.info("开始运行设备配置筛选示例...");
findHighQualityOutdoorDevices();
findDevicesWithMissingConfigs();
findDevicesByMultipleLocations();
useConvenienceMethods();
findHighLoadDevices();
log.info("所有示例运行完成");
}
}

View File

@@ -9,6 +9,8 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
@@ -205,6 +207,27 @@ public class DeviceIntegrationService {
return listDevices(page, pageSize, null, null, null, 1, scenicId);
}
/**
* 根据配置条件筛选设备
*/
public FilterDevicesByConfigsResponse filterDevicesByConfigs(FilterDevicesByConfigsRequest request) {
log.info("根据配置条件筛选设备, page: {}, pageSize: {}, filterLogic: {}, configFilters: {}",
request.getPage(), request.getPageSize(), request.getFilterLogic(), request.getConfigFilters());
CommonResponse<FilterDevicesByConfigsResponse> response = deviceV2Client.filterDevicesByConfigs(request);
return handleResponse(response, "根据配置条件筛选设备失败");
}
/**
* 查找缺少指定配置的设备
*/
public FilterDevicesByConfigsResponse findDevicesWithMissingConfig(String configKey, Integer page, Integer pageSize) {
FilterDevicesByConfigsRequest request = new FilterDevicesByConfigsRequest();
request.setPage(page != null ? page : 1);
request.setPageSize(pageSize != null ? pageSize : 20);
request.setConfigFilters(List.of(new ConfigFilter(configKey, null, "is_null")));
return filterDevicesByConfigs(request);
}
private <T> T handleResponse(CommonResponse<T> response, String errorMessage) {
if (response == null || !response.isSuccess()) {
String msg = response != null && response.getMessage() != null