diff --git a/src/main/java/com/ycwl/basic/integration/CLAUDE.md b/src/main/java/com/ycwl/basic/integration/CLAUDE.md index 2120cad..173da25 100644 --- a/src/main/java/com/ycwl/basic/integration/CLAUDE.md +++ b/src/main/java/com/ycwl/basic/integration/CLAUDE.md @@ -163,11 +163,28 @@ configService.setDeviceFramerate(deviceId, 60); // Get flat configuration Map config = configService.getDeviceFlatConfig(deviceId); -// Batch update configurations +// Batch update configurations (simple way) Map batchConfigs = new HashMap<>(); batchConfigs.put("brightness", "50"); batchConfigs.put("contrast", "80"); 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 @@ -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 - **IPC**: IP Camera devices for video monitoring - **CUSTOM**: Custom device types for sensors, controllers, etc. diff --git a/src/main/java/com/ycwl/basic/integration/device/client/DeviceConfigV2Client.java b/src/main/java/com/ycwl/basic/integration/device/client/DeviceConfigV2Client.java index 28046b8..c94ca1e 100644 --- a/src/main/java/com/ycwl/basic/integration/device/client/DeviceConfigV2Client.java +++ b/src/main/java/com/ycwl/basic/integration/device/client/DeviceConfigV2Client.java @@ -68,8 +68,8 @@ public interface DeviceConfigV2Client { * 批量更新设备配置 */ @PostMapping("/{deviceId}/batch") - CommonResponse batchUpdateDeviceConfig(@PathVariable("deviceId") Long deviceId, - @RequestBody BatchDeviceConfigRequest request); + CommonResponse batchUpdateDeviceConfig(@PathVariable("deviceId") Long deviceId, + @RequestBody BatchDeviceConfigRequest request); /** * 扁平化批量更新设备配置 diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/config/BatchUpdateResponse.java b/src/main/java/com/ycwl/basic/integration/device/dto/config/BatchUpdateResponse.java new file mode 100644 index 0000000..bd4b756 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/dto/config/BatchUpdateResponse.java @@ -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 processedItems; + + /** + * 错误信息列表 + */ + @JsonProperty("errors") + private List errors; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/dto/config/ProcessedConfigItem.java b/src/main/java/com/ycwl/basic/integration/device/dto/config/ProcessedConfigItem.java new file mode 100644 index 0000000..6911163 --- /dev/null +++ b/src/main/java/com/ycwl/basic/integration/device/dto/config/ProcessedConfigItem.java @@ -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; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java b/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java index ce2de85..04e01a9 100644 --- a/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java +++ b/src/main/java/com/ycwl/basic/integration/device/example/DeviceIntegrationExample.java @@ -101,13 +101,49 @@ public class DeviceIntegrationExample { String resolution = deviceConfigService.getDeviceResolution(deviceId); log.info("IP地址: {}, 分辨率: {}", ipAddress, resolution); - // 7. 批量更新配置 + // 7. 批量更新配置(扁平化方式) Map batchConfigs = new HashMap<>(); batchConfigs.put("brightness", "50"); batchConfigs.put("contrast", "80"); batchConfigs.put("quality", "high"); deviceConfigService.batchFlatUpdateDeviceConfig(deviceId, batchConfigs); 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 { basicDeviceOperations(); deviceConfigurationOperations(); + batchConfigurationExample(); // 新增的批量配置示例 cameraManagementExample(); deviceMonitoringExample(); errorHandlingExample(); diff --git a/src/main/java/com/ycwl/basic/integration/device/service/DeviceConfigIntegrationService.java b/src/main/java/com/ycwl/basic/integration/device/service/DeviceConfigIntegrationService.java index 0e2359a..4be322d 100644 --- a/src/main/java/com/ycwl/basic/integration/device/service/DeviceConfigIntegrationService.java +++ b/src/main/java/com/ycwl/basic/integration/device/service/DeviceConfigIntegrationService.java @@ -67,10 +67,13 @@ public class DeviceConfigIntegrationService { 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()); - CommonResponse response = deviceConfigV2Client.batchUpdateDeviceConfig(deviceId, request); - handleResponse(response, "批量更新设备配置失败"); + CommonResponse response = deviceConfigV2Client.batchUpdateDeviceConfig(deviceId, request); + return handleResponse(response, "批量更新设备配置失败"); } public void batchFlatUpdateDeviceConfig(Long deviceId, Map configs) { @@ -126,30 +129,17 @@ public class DeviceConfigIntegrationService { } /** - * 配置摄像头基本参数 + * 配置摄像头参数 */ - public void configureCameraBasicParams(Long deviceId, String ipAddress, String resolution, - Integer framerate, String protocol) { + public void configureCameraParams(Long deviceId, String ipAddress, String resolution, + Integer framerate, String protocol, String username, String password) { Map 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) { - Map configs = new HashMap<>(); - configs.put("ip_address", ipAddress); - configs.put("resolution", resolution); - configs.put("framerate", framerate.toString()); - configs.put("protocol", protocol); - configs.put("username", username); - configs.put("password", password); + if (username != null) configs.put("username", username); + if (password != null) configs.put("password", password); batchFlatUpdateDeviceConfig(deviceId, configs); } @@ -174,6 +164,95 @@ public class DeviceConfigIntegrationService { public String getDeviceResolution(Long deviceId) { 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 handleResponse(CommonResponse response, String errorMessage) { if (response == null || !response.isSuccess()) {