Files
FrameTour-BE/src/main/java/com/ycwl/basic/integration/CLAUDE.md
Jerry Yan ad7d1042f4 feat(device): 新增批量配置设备参数接口
- 新增 BatchUpdateResponse 和 ProcessedConfigItem 类用于批量更新响应
- 修改 DeviceConfigV2Client 接口返回类型为 BatchUpdateResponse
- 在 DeviceConfigIntegrationService 中实现新的批量更新逻辑
- 更新 DeviceIntegrationExample 和 CLAUDE.md 文档,添加新的批量配置示例
2025-09-01 23:15:02 +08:00

15 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Integration Package Overview

The integration package (com.ycwl.basic.integration) is responsible for external microservice integrations using Spring Cloud OpenFeign and Nacos service discovery. It provides a standardized approach for calling external services with proper error handling, configuration management, and response processing.

Architecture

Core Components

Common Infrastructure (com.ycwl.basic.integration.common)

  • IntegrationProperties: Centralized configuration properties for all integrations
  • FeignConfig: Global Feign configuration with error decoder and request interceptors
  • FeignErrorDecoder: Custom error decoder that converts Feign errors to IntegrationException
  • IntegrationException: Standardized exception for integration failures
  • CommonResponse/PageResponse: Standard response wrappers for external service calls
  • ConfigValueUtil: Utility for handling configuration values

Service-Specific Integrations

Currently implemented:

  • Scenic Integration (com.ycwl.basic.integration.scenic): ZT-Scenic microservice integration
  • Device Integration (com.ycwl.basic.integration.device): ZT-Device microservice integration

Integration Pattern

Each external service integration follows this structure:

service/
├── client/          # Feign clients for HTTP calls
├── config/          # Service-specific configuration
├── dto/             # Data transfer objects
├── service/         # Service layer with business logic
└── example/         # Usage examples

Scenic Integration (ZT-Scenic Microservice)

Key Components

Feign Clients

  • ScenicV2Client: Main scenic operations (CRUD, filtering, listing)
  • ScenicConfigV2Client: Scenic configuration management
  • DefaultConfigClient: Default configuration operations

Services

  • ScenicIntegrationService: High-level scenic operations
  • ScenicConfigIntegrationService: Configuration management
  • DefaultConfigIntegrationService: Default configuration handling

Configuration

integration:
  scenic:
    enabled: true
    serviceName: zt-scenic
    connectTimeout: 5000
    readTimeout: 10000
    retryEnabled: false
    maxRetries: 3

Usage Examples

Basic Scenic Operations

@Autowired
private ScenicIntegrationService scenicService;

// Get scenic with configuration
ScenicV2WithConfigDTO scenic = scenicService.getScenicWithConfig(scenicId);

// Create new scenic
CreateScenicRequest request = new CreateScenicRequest();
request.setName("Test Scenic");
ScenicV2DTO result = scenicService.createScenic(request);

// Filter scenics
ScenicFilterRequest filterRequest = new ScenicFilterRequest();
// configure filters...
ScenicFilterPageResponse response = scenicService.filterScenics(filterRequest);

Configuration Management

@Autowired
private ScenicConfigIntegrationService configService;

// Get flat configuration
Map<String, Object> config = scenicService.getScenicFlatConfig(scenicId);

// Batch update configurations
BatchConfigRequest batchRequest = new BatchConfigRequest();
// configure batch updates...
configService.batchUpdateConfigs(scenicId, batchRequest);

Device Integration (ZT-Device Microservice)

Key Components

Feign Clients

  • DeviceV2Client: Main device operations (CRUD, filtering, listing)
  • DeviceConfigV2Client: Device configuration management

Services

  • DeviceIntegrationService: High-level device operations
  • DeviceConfigIntegrationService: Device configuration management

Configuration

integration:
  device:
    enabled: true
    serviceName: zt-device
    connectTimeout: 5000
    readTimeout: 10000
    retryEnabled: false
    maxRetries: 3

Usage Examples

Basic Device Operations

@Autowired
private DeviceIntegrationService deviceService;

// Create IPC camera device
DeviceV2DTO ipcDevice = deviceService.createIpcDevice("前门摄像头", "CAM001", scenicId);

// Get device with configuration
DeviceV2WithConfigDTO device = deviceService.getDeviceWithConfig(deviceId);

// Get device by number
DeviceV2DTO deviceByNo = deviceService.getDeviceByNo("CAM001");

// List scenic devices
DeviceV2ListResponse deviceList = deviceService.getScenicIpcDevices(scenicId, 1, 10);

// Enable/disable device
deviceService.enableDevice(deviceId);
deviceService.disableDevice(deviceId);

Device Configuration Management

@Autowired
private DeviceConfigIntegrationService configService;

// Configure camera basic parameters
configService.configureCameraBasicParams(deviceId, "192.168.1.100", "1920x1080", 30, "RTSP");

// Configure camera with authentication
configService.configureCameraFullParams(deviceId, "192.168.1.100", "1920x1080", 30, "RTSP", "admin", "password");

// Set specific configuration
configService.setDeviceIpAddress(deviceId, "192.168.1.101");
configService.setDeviceResolution(deviceId, "2560x1440");
configService.setDeviceFramerate(deviceId, 60);

// Get flat configuration
Map<String, Object> config = configService.getDeviceFlatConfig(deviceId);

// Batch update configurations (simple way)
Map<String, Object> 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

// Create and configure camera in one operation
DeviceV2DTO camera = deviceService.createIpcDevice("摄像头1", "CAM001", scenicId);
configService.configureCameraFullParams(camera.getId(), "192.168.1.100", "1920x1080", 30, "RTSP", "admin", "password");

// Get scenic camera status
DeviceV2WithConfigListResponse camerasWithConfig = 
    deviceService.listDevicesWithConfig(1, 100, null, null, "IPC", 1, scenicId);

// Batch update camera resolution
for (DeviceV2WithConfigDTO device : camerasWithConfig.getList()) {
    configService.setDeviceResolution(device.getId(), "2560x1440");
}

// Monitor device configuration completeness
for (DeviceV2DTO device : activeDevices.getList()) {
    Map<String, Object> config = configService.getDeviceFlatConfig(device.getId());
    boolean hasIpConfig = config.containsKey("ip_address");
    // log configuration status...
}

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

// 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.

Common Configuration Keys

  • ip_address: Device IP address
  • resolution: Video resolution (e.g., "1920x1080", "3840x2160")
  • framerate: Video frame rate (integer)
  • protocol: Communication protocol (e.g., "RTSP", "HTTP")
  • username: Authentication username
  • password: Authentication password
  • brightness: Display brightness (0-100)
  • contrast: Display contrast (0-100)
  • quality: Video quality ("low", "medium", "high")

Adding New Service Integrations

1. Create Package Structure

com.ycwl.basic.integration.{service-name}/
├── client/
├── config/
├── dto/
├── service/
└── example/

2. Add Configuration Properties

Update IntegrationProperties to include new service configuration:

@Data
public static class NewServiceConfig {
    private boolean enabled = true;
    private String serviceName = "service-name";
    private int connectTimeout = 5000;
    private int readTimeout = 10000;
    // other configs...
}

3. Create Feign Client

@FeignClient(name = "service-name", contextId = "service-context", path = "/api/path")
public interface NewServiceClient {
    @GetMapping("/endpoint")
    CommonResponse<ResponseDTO> getData(@PathVariable Long id);
    // other endpoints...
}

4. Implement Service Layer

@Service
@RequiredArgsConstructor
public class NewServiceIntegrationService {
    private final NewServiceClient client;
    
    public ResponseDTO getData(Long id) {
        CommonResponse<ResponseDTO> response = client.getData(id);
        return handleResponse(response, "Failed to get data");
    }
    
    private <T> T handleResponse(CommonResponse<T> response, String errorMessage) {
        if (response == null || !response.isSuccess()) {
            String msg = response != null && response.getMessage() != null 
                        ? response.getMessage() 
                        : errorMessage;
            Integer code = response != null ? response.getCode() : 5000;
            throw new IntegrationException(code, msg, "service-name");
        }
        return response.getData();
    }
}

Error Handling

IntegrationException

All integration failures are wrapped in IntegrationException:

public class IntegrationException extends RuntimeException {
    private final Integer code;
    private final String serviceName;
    // constructors and getters...
}

FeignErrorDecoder

Automatically converts Feign errors to IntegrationException:

  • Parses CommonResponse error format
  • Extracts service name from method key
  • Provides meaningful error messages

Configuration Management

Properties Structure

integration:
  scenic:
    enabled: true
    serviceName: zt-scenic
    connectTimeout: 5000
    readTimeout: 10000
    retryEnabled: false
    maxRetries: 3
  device:
    enabled: true
    serviceName: zt-device
    connectTimeout: 5000
    readTimeout: 10000
    retryEnabled: false
    maxRetries: 3

Configuration Refresh

Uses @RefreshScope to support dynamic configuration updates without restart.

Testing Integration Services

Unit Testing

Test service layers by mocking Feign clients:

@ExtendWith(MockitoExtension.class)
class ScenicIntegrationServiceTest {
    @Mock
    private ScenicV2Client scenicV2Client;
    
    @InjectMocks
    private ScenicIntegrationService scenicService;
    
    @Test
    void testGetScenic() {
        // Mock response
        CommonResponse<ScenicV2DTO> response = new CommonResponse<>();
        response.setSuccess(true);
        response.setData(new ScenicV2DTO());
        
        when(scenicV2Client.getScenic(1L)).thenReturn(response);
        
        // Test
        ScenicV2DTO result = scenicService.getScenic(1L);
        assertNotNull(result);
    }
}

Integration Testing

Use @SpringBootTest with test profiles and mock external services.

Common Development Tasks

Running Integration Tests

# Run specific integration test class
mvn test -Dtest=ScenicIntegrationServiceTest

# Run all integration tests
mvn test -Dtest="com.ycwl.basic.integration.*Test"

# Run device integration tests
mvn test -Dtest=DeviceIntegrationServiceTest
mvn test -Dtest="com.ycwl.basic.integration.device.*Test"

Adding New DTOs

  1. Create DTO classes in the appropriate dto package
  2. Follow existing patterns with proper Jackson annotations
  3. Use @JsonProperty for field mapping when needed

Debugging Integration Issues

  1. Enable Feign client logging in application-dev.yml:
logging:
  level:
    com.ycwl.basic.integration: DEBUG
  1. Check Nacos service discovery in development
  2. Verify service configurations and timeouts
  3. Review FeignErrorDecoder logs for detailed error information

Best Practices

Response Handling

  • Always use the handleResponse pattern for consistent error handling
  • Provide meaningful error messages for business context
  • Include service name in IntegrationException for debugging

Configuration

  • Use environment-specific configuration profiles
  • Set appropriate timeouts based on service characteristics
  • Enable retries only when safe (idempotent operations)

DTOs and Mapping

  • Keep DTOs simple and focused on data transfer
  • Use proper Jackson annotations for field mapping
  • Separate request/response DTOs for clarity

Service Layer Design

  • Keep integration services focused on external service calls
  • Handle response transformation and error conversion
  • Avoid business logic in integration services