feat(device): 新增批量配置设备参数接口

- 新增 BatchUpdateResponse 和 ProcessedConfigItem 类用于批量更新响应
- 修改 DeviceConfigV2Client 接口返回类型为 BatchUpdateResponse
- 在 DeviceConfigIntegrationService 中实现新的批量更新逻辑
- 更新 DeviceIntegrationExample 和 CLAUDE.md 文档,添加新的批量配置示例
This commit is contained in:
2025-09-01 23:15:02 +08:00
parent 0bcf2aaccf
commit ad7d1042f4
6 changed files with 409 additions and 25 deletions

View File

@@ -163,11 +163,28 @@ configService.setDeviceFramerate(deviceId, 60);
// Get flat configuration // Get flat configuration
Map<String, Object> config = configService.getDeviceFlatConfig(deviceId); Map<String, Object> config = configService.getDeviceFlatConfig(deviceId);
// Batch update configurations // Batch update configurations (simple way)
Map<String, Object> batchConfigs = new HashMap<>(); Map<String, Object> batchConfigs = new HashMap<>();
batchConfigs.put("brightness", "50"); batchConfigs.put("brightness", "50");
batchConfigs.put("contrast", "80"); batchConfigs.put("contrast", "80");
configService.batchFlatUpdateDeviceConfig(deviceId, batchConfigs); configService.batchFlatUpdateDeviceConfig(deviceId, batchConfigs);
// New batch configuration API with detailed results
BatchDeviceConfigRequest request = configService.createBatchConfigBuilder()
.addVideoConfig("4K", 30, "H265") // Add video configuration
.addNetworkConfig("192.168.1.100", 554, "RTSP") // Add network configuration
.addAuthConfig("admin", "password") // Add authentication configuration
.addConfig("recording_enabled", "true") // Use default configuration
.addConfig("custom_setting", "value", "string", "Custom setting") // Custom configuration
.build();
BatchUpdateResponse result = configService.batchUpdateDeviceConfigWithResult(deviceId, request);
if (result.getFailed() > 0) {
// Handle partial failure
result.getProcessedItems().stream()
.filter(item -> "failed".equals(item.getStatus()))
.forEach(item -> log.warn("Config {} failed: {}", item.getConfigKey(), item.getMessage()));
}
``` ```
#### Device Management Patterns #### Device Management Patterns
@@ -193,6 +210,57 @@ for (DeviceV2DTO device : activeDevices.getList()) {
} }
``` ```
### Enhanced Batch Configuration API
Device Integration now supports an enhanced batch configuration API that provides detailed processing results and supports default configuration rules.
#### Default Configuration Rules
The system uses `device_id = 0` configurations as default templates:
- **Configurations with defaults**: System enforces default `config_type` and `description`, only `configValue` is updated
- **Configurations without defaults**: Allows custom `config_type` and `description`
#### Usage Examples
```java
// 1. Using Builder Pattern
BatchDeviceConfigRequest request = configService.createBatchConfigBuilder()
.addVideoConfig("1920x1080", 30, "H264") // Video settings
.addNetworkConfig("192.168.1.100", 554, "RTSP") // Network settings
.addAuthConfig("admin", "password123") // Authentication
.addConfig("recording_enabled", "true") // Use default config rule
.addConfig("custom_path", "/data", "string", "Storage path") // Custom config
.build();
BatchUpdateResponse result = configService.batchUpdateDeviceConfigWithResult(deviceId, request);
// 2. Processing Results
log.info("Batch update: {} success, {} failed", result.getSuccess(), result.getFailed());
for (ProcessedConfigItem item : result.getProcessedItems()) {
if ("success".equals(item.getStatus())) {
log.info("✅ {} updated (action: {}, hasDefault: {})",
item.getConfigKey(), item.getAction(), item.getHasDefault());
} else {
log.warn("❌ {} failed: {}", item.getConfigKey(), item.getMessage());
}
}
// 3. Error Handling
if (result.getFailed() > 0) {
result.getErrors().forEach(error -> log.warn("Error: {}", error));
}
```
#### Response Format
- **200 OK**: All configurations updated successfully
- **202 Accepted**: Partial success (some configurations failed)
- **400 Bad Request**: All configurations failed
Each processed item includes:
- `status`: "success" or "failed"
- `action`: "create" or "update"
- `hasDefault`: Whether default configuration rules were applied
- `finalType`/`finalDescription`: Actually used type and description
### Device Types ### Device Types
- **IPC**: IP Camera devices for video monitoring - **IPC**: IP Camera devices for video monitoring
- **CUSTOM**: Custom device types for sensors, controllers, etc. - **CUSTOM**: Custom device types for sensors, controllers, etc.

View File

@@ -68,7 +68,7 @@ public interface DeviceConfigV2Client {
* 批量更新设备配置 * 批量更新设备配置
*/ */
@PostMapping("/{deviceId}/batch") @PostMapping("/{deviceId}/batch")
CommonResponse<String> batchUpdateDeviceConfig(@PathVariable("deviceId") Long deviceId, CommonResponse<BatchUpdateResponse> batchUpdateDeviceConfig(@PathVariable("deviceId") Long deviceId,
@RequestBody BatchDeviceConfigRequest request); @RequestBody BatchDeviceConfigRequest request);
/** /**

View File

@@ -0,0 +1,36 @@
package com.ycwl.basic.integration.device.dto.config;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* 批量配置更新响应
*/
@Data
public class BatchUpdateResponse {
/**
* 成功处理的配置数量
*/
@JsonProperty("success")
private Integer success;
/**
* 失败的配置数量
*/
@JsonProperty("failed")
private Integer failed;
/**
* 处理详情列表
*/
@JsonProperty("processedItems")
private List<ProcessedConfigItem> processedItems;
/**
* 错误信息列表
*/
@JsonProperty("errors")
private List<String> errors;
}

View File

@@ -0,0 +1,52 @@
package com.ycwl.basic.integration.device.dto.config;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* 处理的配置项详情
*/
@Data
public class ProcessedConfigItem {
/**
* 配置键名
*/
@JsonProperty("configKey")
private String configKey;
/**
* 处理状态: success/failed
*/
@JsonProperty("status")
private String status;
/**
* 执行动作: create/update
*/
@JsonProperty("action")
private String action;
/**
* 是否有默认配置
*/
@JsonProperty("hasDefault")
private Boolean hasDefault;
/**
* 处理消息
*/
@JsonProperty("message")
private String message;
/**
* 最终使用的类型
*/
@JsonProperty("finalType")
private String finalType;
/**
* 最终使用的描述
*/
@JsonProperty("finalDescription")
private String finalDescription;
}

View File

@@ -101,13 +101,49 @@ public class DeviceIntegrationExample {
String resolution = deviceConfigService.getDeviceResolution(deviceId); String resolution = deviceConfigService.getDeviceResolution(deviceId);
log.info("IP地址: {}, 分辨率: {}", ipAddress, resolution); log.info("IP地址: {}, 分辨率: {}", ipAddress, resolution);
// 7. 批量更新配置 // 7. 批量更新配置(扁平化方式)
Map<String, Object> batchConfigs = new HashMap<>(); Map<String, Object> batchConfigs = new HashMap<>();
batchConfigs.put("brightness", "50"); batchConfigs.put("brightness", "50");
batchConfigs.put("contrast", "80"); batchConfigs.put("contrast", "80");
batchConfigs.put("quality", "high"); batchConfigs.put("quality", "high");
deviceConfigService.batchFlatUpdateDeviceConfig(deviceId, batchConfigs); deviceConfigService.batchFlatUpdateDeviceConfig(deviceId, batchConfigs);
log.info("批量配置已更新"); log.info("批量配置已更新");
// 8. 使用新的批量配置API(返回详细结果)
BatchDeviceConfigRequest.BatchDeviceConfigItem item1 = new BatchDeviceConfigRequest.BatchDeviceConfigItem();
item1.setConfigKey("resolution");
item1.setConfigValue("4K");
BatchDeviceConfigRequest.BatchDeviceConfigItem item2 = new BatchDeviceConfigRequest.BatchDeviceConfigItem();
item2.setConfigKey("custom_setting");
item2.setConfigValue("custom_value");
item2.setConfigType("string");
item2.setDescription("自定义设置");
BatchDeviceConfigRequest batchRequest = new BatchDeviceConfigRequest();
batchRequest.setConfigs(List.of(item1, item2));
BatchUpdateResponse result = deviceConfigService.batchUpdateDeviceConfigWithResult(deviceId, batchRequest);
log.info("批量配置更新结果: 成功={}, 失败={}", result.getSuccess(), result.getFailed());
for (ProcessedConfigItem processedItem : result.getProcessedItems()) {
log.info("配置项 {} 处理状态: {}, 动作: {}, 有默认配置: {}",
processedItem.getConfigKey(),
processedItem.getStatus(),
processedItem.getAction(),
processedItem.getHasDefault());
}
// 9. 使用配置构建器简化批量配置
BatchDeviceConfigRequest builderRequest = deviceConfigService.createBatchConfigBuilder()
.addVideoConfig("1920x1080", 30, "H264")
.addNetworkConfig("192.168.1.100", 554, "RTSP")
.addAuthConfig("admin", "password123")
.addConfig("custom_key", "custom_value", "string", "自定义配置")
.build();
BatchUpdateResponse builderResult = deviceConfigService.batchUpdateDeviceConfigWithResult(deviceId, builderRequest);
log.info("构建器批量配置更新结果: 成功={}, 失败={}", builderResult.getSuccess(), builderResult.getFailed());
} }
/** /**
@@ -195,6 +231,118 @@ public class DeviceIntegrationExample {
} }
} }
/**
* 新批量配置API使用示例
*/
public void batchConfigurationExample() {
log.info("=== 新批量配置API使用示例 ===");
Long deviceId = 1L;
// 1. 使用基础批量配置API
try {
// 创建批量配置请求
BatchDeviceConfigRequest.BatchDeviceConfigItem item1 = new BatchDeviceConfigRequest.BatchDeviceConfigItem();
item1.setConfigKey("resolution");
item1.setConfigValue("3840x2160");
BatchDeviceConfigRequest.BatchDeviceConfigItem item2 = new BatchDeviceConfigRequest.BatchDeviceConfigItem();
item2.setConfigKey("framerate");
item2.setConfigValue("60");
BatchDeviceConfigRequest.BatchDeviceConfigItem item3 = new BatchDeviceConfigRequest.BatchDeviceConfigItem();
item3.setConfigKey("custom_quality");
item3.setConfigValue("ultra");
item3.setConfigType("string");
item3.setDescription("自定义画质设置");
BatchDeviceConfigRequest request = new BatchDeviceConfigRequest();
request.setConfigs(List.of(item1, item2, item3));
// 调用批量配置API并获取详细结果
BatchUpdateResponse result = deviceConfigService.batchUpdateDeviceConfigWithResult(deviceId, request);
// 分析结果
log.info("批量配置更新完成 - 成功: {}, 失败: {}", result.getSuccess(), result.getFailed());
// 详细处理结果
for (ProcessedConfigItem item : result.getProcessedItems()) {
if ("success".equals(item.getStatus())) {
log.info("✅ 配置 {} 更新成功 - 动作: {}, 默认配置: {}, 最终类型: {}",
item.getConfigKey(),
item.getAction(),
item.getHasDefault() ? "" : "",
item.getFinalType());
} else {
log.warn("❌ 配置 {} 更新失败 - 原因: {}",
item.getConfigKey(),
item.getMessage());
}
}
// 错误信息
if (!result.getErrors().isEmpty()) {
log.warn("批量更新错误列表:");
result.getErrors().forEach(error -> log.warn(" - {}", error));
}
} catch (Exception e) {
log.error("批量配置更新异常", e);
}
// 2. 使用构建器模式简化批量配置
try {
log.info("--- 使用构建器模式 ---");
BatchDeviceConfigRequest builderRequest = deviceConfigService.createBatchConfigBuilder()
.addVideoConfig("1920x1080", 30, "H265") // 添加视频配置
.addNetworkConfig("192.168.1.200", 8554, "RTSP") // 添加网络配置
.addAuthConfig("operator", "newpassword") // 添加认证配置
.addConfig("recording_enabled", "true") // 使用默认配置的项
.addConfig("storage_path", "/data/recordings", "string", "录像存储路径") // 自定义配置项
.build();
BatchUpdateResponse builderResult = deviceConfigService.batchUpdateDeviceConfigWithResult(deviceId, builderRequest);
log.info("构建器模式批量配置结果 - 成功: {}, 失败: {}",
builderResult.getSuccess(), builderResult.getFailed());
} catch (Exception e) {
log.error("构建器模式批量配置异常", e);
}
// 3. 处理部分成功的情况
try {
log.info("--- 处理部分成功场景 ---");
BatchDeviceConfigRequest mixedRequest = deviceConfigService.createBatchConfigBuilder()
.addConfig("resolution", "1920x1080") // 正常配置
.addConfig("invalid_key_format", "test_value") // 可能失败的配置
.addConfig("", "empty_key_value") // 肯定失败的配置
.addConfig("max_connections", "100") // 正常配置
.build();
BatchUpdateResponse mixedResult = deviceConfigService.batchUpdateDeviceConfigWithResult(deviceId, mixedRequest);
if (mixedResult.getFailed() > 0) {
log.warn("存在部分失败的配置项:");
mixedResult.getProcessedItems().stream()
.filter(item -> "failed".equals(item.getStatus()))
.forEach(item -> log.warn(" - {}: {}", item.getConfigKey(), item.getMessage()));
log.info("成功配置的项:");
mixedResult.getProcessedItems().stream()
.filter(item -> "success".equals(item.getStatus()))
.forEach(item -> log.info(" - {}: {} ({})",
item.getConfigKey(),
item.getAction(),
item.getHasDefault() ? "使用默认规则" : "自定义配置"));
}
} catch (Exception e) {
log.error("混合配置场景异常", e);
}
}
/** /**
* 错误处理和故障恢复示例 * 错误处理和故障恢复示例
*/ */
@@ -232,6 +380,7 @@ public class DeviceIntegrationExample {
try { try {
basicDeviceOperations(); basicDeviceOperations();
deviceConfigurationOperations(); deviceConfigurationOperations();
batchConfigurationExample(); // 新增的批量配置示例
cameraManagementExample(); cameraManagementExample();
deviceMonitoringExample(); deviceMonitoringExample();
errorHandlingExample(); errorHandlingExample();

View File

@@ -67,10 +67,13 @@ public class DeviceConfigIntegrationService {
handleResponse(response, "删除设备配置失败"); handleResponse(response, "删除设备配置失败");
} }
public void batchUpdateDeviceConfig(Long deviceId, BatchDeviceConfigRequest request) { /**
* 批量更新设备配置
*/
public BatchUpdateResponse batchUpdateDeviceConfig(Long deviceId, BatchDeviceConfigRequest request) {
log.info("批量更新设备配置, deviceId: {}, configs count: {}", deviceId, request.getConfigs().size()); log.info("批量更新设备配置, deviceId: {}, configs count: {}", deviceId, request.getConfigs().size());
CommonResponse<String> response = deviceConfigV2Client.batchUpdateDeviceConfig(deviceId, request); CommonResponse<BatchUpdateResponse> response = deviceConfigV2Client.batchUpdateDeviceConfig(deviceId, request);
handleResponse(response, "批量更新设备配置失败"); return handleResponse(response, "批量更新设备配置失败");
} }
public void batchFlatUpdateDeviceConfig(Long deviceId, Map<String, Object> configs) { public void batchFlatUpdateDeviceConfig(Long deviceId, Map<String, Object> configs) {
@@ -126,30 +129,17 @@ public class DeviceConfigIntegrationService {
} }
/** /**
* 配置摄像头基本参数 * 配置摄像头参数
*/ */
public void configureCameraBasicParams(Long deviceId, String ipAddress, String resolution, public void configureCameraParams(Long deviceId, String ipAddress, String resolution,
Integer framerate, String protocol) {
Map<String, Object> configs = new HashMap<>();
configs.put("ip_address", ipAddress);
configs.put("resolution", resolution);
configs.put("framerate", framerate.toString());
configs.put("protocol", protocol);
batchFlatUpdateDeviceConfig(deviceId, configs);
}
/**
* 配置摄像头完整参数
*/
public void configureCameraFullParams(Long deviceId, String ipAddress, String resolution,
Integer framerate, String protocol, String username, String password) { Integer framerate, String protocol, String username, String password) {
Map<String, Object> configs = new HashMap<>(); Map<String, Object> configs = new HashMap<>();
configs.put("ip_address", ipAddress); configs.put("ip_address", ipAddress);
configs.put("resolution", resolution); configs.put("resolution", resolution);
configs.put("framerate", framerate.toString()); configs.put("framerate", framerate.toString());
configs.put("protocol", protocol); configs.put("protocol", protocol);
configs.put("username", username); if (username != null) configs.put("username", username);
configs.put("password", password); if (password != null) configs.put("password", password);
batchFlatUpdateDeviceConfig(deviceId, configs); batchFlatUpdateDeviceConfig(deviceId, configs);
} }
@@ -175,6 +165,95 @@ public class DeviceConfigIntegrationService {
return getDeviceConfigValue(deviceId, "resolution"); return getDeviceConfigValue(deviceId, "resolution");
} }
/**
* 创建批量配置请求构建器
*/
public BatchDeviceConfigRequestBuilder createBatchConfigBuilder() {
return new BatchDeviceConfigRequestBuilder();
}
/**
* 批量配置请求构建器
*/
public static class BatchDeviceConfigRequestBuilder {
private final BatchDeviceConfigRequest request = new BatchDeviceConfigRequest();
public BatchDeviceConfigRequestBuilder() {
request.setConfigs(new java.util.ArrayList<>());
}
/**
* 添加配置项(有默认配置的情况,只需提供key和value)
*/
public BatchDeviceConfigRequestBuilder addConfig(String configKey, String configValue) {
BatchDeviceConfigRequest.BatchDeviceConfigItem item = new BatchDeviceConfigRequest.BatchDeviceConfigItem();
item.setConfigKey(configKey);
item.setConfigValue(configValue);
request.getConfigs().add(item);
return this;
}
/**
* 添加配置项(完整参数,用于自定义配置)
*/
public BatchDeviceConfigRequestBuilder addConfig(String configKey, String configValue,
String configType, String description) {
BatchDeviceConfigRequest.BatchDeviceConfigItem item = new BatchDeviceConfigRequest.BatchDeviceConfigItem();
item.setConfigKey(configKey);
item.setConfigValue(configValue);
item.setConfigType(configType);
item.setDescription(description);
request.getConfigs().add(item);
return this;
}
/**
* 添加常用视频配置
*/
public BatchDeviceConfigRequestBuilder addVideoConfig(String resolution, Integer framerate, String codec) {
addConfig("resolution", resolution);
addConfig("framerate", framerate.toString());
if (codec != null) {
addConfig("codec", codec);
}
return this;
}
/**
* 添加网络配置
*/
public BatchDeviceConfigRequestBuilder addNetworkConfig(String ipAddress, Integer port, String protocol) {
addConfig("ip_address", ipAddress);
if (port != null) {
addConfig("port", port.toString());
}
if (protocol != null) {
addConfig("protocol", protocol);
}
return this;
}
/**
* 添加认证配置
*/
public BatchDeviceConfigRequestBuilder addAuthConfig(String username, String password) {
if (username != null) {
addConfig("username", username);
}
if (password != null) {
addConfig("password", password);
}
return this;
}
/**
* 构建请求对象
*/
public BatchDeviceConfigRequest build() {
return request;
}
}
private <T> T handleResponse(CommonResponse<T> response, String errorMessage) { private <T> T handleResponse(CommonResponse<T> response, String errorMessage) {
if (response == null || !response.isSuccess()) { if (response == null || !response.isSuccess()) {
String msg = response != null && response.getMessage() != null String msg = response != null && response.getMessage() != null