You've already forked FrameTour-BE
feat(integration): 添加设备服务集成模块
- 新增设备服务配置和相关客户端接口 - 实现设备和设备配置的管理功能- 添加设备监控和状态管理示例 - 优化错误处理和故障恢复机制
This commit is contained in:
104
CLAUDE.md
104
CLAUDE.md
@@ -122,6 +122,15 @@ mvn test -DskipTests=false
|
||||
3. 使用 `@Scheduled` 进行基于 cron 的执行
|
||||
4. 遵循现有的错误处理和日志记录模式
|
||||
|
||||
### 多端API架构
|
||||
应用程序通过路径前缀区分不同的客户端:
|
||||
- **移动端**: `/api/mobile/*` - 针对移动应用优化的接口
|
||||
- **PC管理端**: `/api/*` - Web管理面板接口
|
||||
- **任务处理**: `/task/*` - 后台任务和渲染服务接口
|
||||
- **外部集成**: 专用集成接口(打印机、代理、viid、vpt、wvp等)
|
||||
|
||||
每个端点都有对应的Controller包结构,确保API的职责分离和维护性。
|
||||
|
||||
## 价格查询系统 (Pricing Module)
|
||||
|
||||
### 核心架构
|
||||
@@ -187,4 +196,97 @@ ProductType枚举定义了支持的商品类型:
|
||||
- 单元测试:每个服务类都有对应测试类
|
||||
- 配置验证测试:DefaultConfigValidationTest验证default配置
|
||||
- JSON序列化测试:验证复杂对象的数据库存储
|
||||
- 分页功能测试:验证PageHelper集成
|
||||
- 分页功能测试:验证PageHelper集成
|
||||
|
||||
## 关键架构模式
|
||||
|
||||
### Repository 层模式
|
||||
项目使用Repository层抽象数据访问逻辑:
|
||||
- Repository接口定义数据访问契约
|
||||
- Mapper接口处理MyBatis Plus的数据库映射
|
||||
- Service层通过Repository访问数据,避免直接依赖Mapper
|
||||
|
||||
### 异常处理架构
|
||||
- **全局异常处理**: `CustomExceptionHandle` 提供统一的异常处理和响应格式
|
||||
- **业务异常**: 自定义异常类继承RuntimeException,携带业务错误码
|
||||
- **集成异常**: `IntegrationException` 专门处理外部服务调用异常
|
||||
|
||||
### 配置驱动的扩展性
|
||||
通过配置文件驱动的多供应商支持:
|
||||
- 存储:本地、AWS S3、阿里云 OSS
|
||||
- 支付:微信支付、聪明支付
|
||||
- 人脸识别:阿里云、百度
|
||||
每个供应商通过统一接口访问,配置切换无需代码修改。
|
||||
|
||||
### 业务层架构
|
||||
- **Service层**: 核心业务逻辑实现
|
||||
- **Biz层**: 高级业务流程编排,组合多个Service
|
||||
- **Controller层**: HTTP请求处理和响应转换
|
||||
- **Repository层**: 数据访问抽象
|
||||
|
||||
### 认证和会话管理
|
||||
- **JWT**: 使用jjwt库进行身份验证
|
||||
- **Redis**: 存储会话信息和缓存
|
||||
- **BaseContextHandler**: 提供当前用户上下文访问
|
||||
|
||||
## 微服务集成架构 (Integration Package)
|
||||
|
||||
### 核心架构
|
||||
位于 `com.ycwl.basic.integration` 包,使用 Spring Cloud OpenFeign 和 Nacos 实现外部微服务集成。
|
||||
|
||||
#### 通用基础设施
|
||||
- **IntegrationProperties**: 所有集成的集中配置管理
|
||||
- **FeignErrorDecoder**: 自定义错误解码器,统一错误处理
|
||||
- **IntegrationException**: 标准化集成异常
|
||||
- **CommonResponse/PageResponse**: 外部服务响应包装器
|
||||
|
||||
#### 已实现的服务集成
|
||||
- **Scenic Integration** (`integration.scenic`): ZT-Scenic 微服务集成
|
||||
- **Device Integration** (`integration.device`): ZT-Device 微服务集成
|
||||
|
||||
#### 集成模式
|
||||
每个外部服务按以下结构组织:
|
||||
```
|
||||
service/
|
||||
├── client/ # Feign 客户端
|
||||
├── config/ # 服务特定配置
|
||||
├── dto/ # 数据传输对象
|
||||
├── service/ # 业务逻辑层
|
||||
└── example/ # 使用示例
|
||||
```
|
||||
|
||||
### 配置管理
|
||||
```yaml
|
||||
integration:
|
||||
scenic:
|
||||
enabled: true
|
||||
serviceName: zt-scenic
|
||||
connectTimeout: 5000
|
||||
readTimeout: 10000
|
||||
device:
|
||||
enabled: true
|
||||
serviceName: zt-device
|
||||
connectTimeout: 5000
|
||||
readTimeout: 10000
|
||||
```
|
||||
|
||||
### 使用模式
|
||||
所有集成服务使用统一的 `handleResponse` 模式进行错误处理,确保一致的异常包装和日志记录。
|
||||
|
||||
### 测试集成服务
|
||||
```bash
|
||||
# 运行特定集成测试
|
||||
mvn test -Dtest=ScenicIntegrationServiceTest
|
||||
mvn test -Dtest=DeviceIntegrationServiceTest
|
||||
|
||||
# 运行所有集成测试
|
||||
mvn test -Dtest="com.ycwl.basic.integration.*Test"
|
||||
```
|
||||
|
||||
### 调试集成问题
|
||||
启用 Feign 客户端日志:
|
||||
```yaml
|
||||
logging:
|
||||
level:
|
||||
com.ycwl.basic.integration: DEBUG
|
||||
```
|
397
src/main/java/com/ycwl/basic/integration/CLAUDE.md
Normal file
397
src/main/java/com/ycwl/basic/integration/CLAUDE.md
Normal file
@@ -0,0 +1,397 @@
|
||||
# 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
|
||||
```yaml
|
||||
integration:
|
||||
scenic:
|
||||
enabled: true
|
||||
serviceName: zt-scenic
|
||||
connectTimeout: 5000
|
||||
readTimeout: 10000
|
||||
retryEnabled: false
|
||||
maxRetries: 3
|
||||
```
|
||||
|
||||
### Usage Examples
|
||||
|
||||
#### Basic Scenic Operations
|
||||
```java
|
||||
@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
|
||||
```java
|
||||
@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
|
||||
```yaml
|
||||
integration:
|
||||
device:
|
||||
enabled: true
|
||||
serviceName: zt-device
|
||||
connectTimeout: 5000
|
||||
readTimeout: 10000
|
||||
retryEnabled: false
|
||||
maxRetries: 3
|
||||
```
|
||||
|
||||
### Usage Examples
|
||||
|
||||
#### Basic Device Operations
|
||||
```java
|
||||
@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
|
||||
```java
|
||||
@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
|
||||
Map<String, Object> batchConfigs = new HashMap<>();
|
||||
batchConfigs.put("brightness", "50");
|
||||
batchConfigs.put("contrast", "80");
|
||||
configService.batchFlatUpdateDeviceConfig(deviceId, batchConfigs);
|
||||
```
|
||||
|
||||
#### Device Management Patterns
|
||||
```java
|
||||
// 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...
|
||||
}
|
||||
```
|
||||
|
||||
### 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:
|
||||
```java
|
||||
@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
|
||||
```java
|
||||
@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
|
||||
```java
|
||||
@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`:
|
||||
```java
|
||||
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
|
||||
```yaml
|
||||
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:
|
||||
```java
|
||||
@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
|
||||
```bash
|
||||
# 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`:
|
||||
```yaml
|
||||
logging:
|
||||
level:
|
||||
com.ycwl.basic.integration: DEBUG
|
||||
```
|
||||
|
||||
2. Check Nacos service discovery in development
|
||||
3. Verify service configurations and timeouts
|
||||
4. 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
|
@@ -16,6 +16,11 @@ public class IntegrationProperties {
|
||||
*/
|
||||
private ScenicConfig scenic = new ScenicConfig();
|
||||
|
||||
/**
|
||||
* 设备服务配置
|
||||
*/
|
||||
private DeviceConfig device = new DeviceConfig();
|
||||
|
||||
@Data
|
||||
public static class ScenicConfig {
|
||||
/**
|
||||
@@ -40,4 +45,29 @@ public class IntegrationProperties {
|
||||
private boolean retryEnabled = false;
|
||||
private int maxRetries = 3;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class DeviceConfig {
|
||||
/**
|
||||
* 是否启用设备服务集成
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* 服务名称
|
||||
*/
|
||||
private String serviceName = "zt-device";
|
||||
|
||||
/**
|
||||
* 超时配置(毫秒)
|
||||
*/
|
||||
private int connectTimeout = 5000;
|
||||
private int readTimeout = 10000;
|
||||
|
||||
/**
|
||||
* 重试配置
|
||||
*/
|
||||
private boolean retryEnabled = false;
|
||||
private int maxRetries = 3;
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
package com.ycwl.basic.integration.device.client;
|
||||
|
||||
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||
import com.ycwl.basic.integration.device.dto.config.*;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@FeignClient(name = "zt-device", contextId = "device-config-v2", path = "/api/device/config/v2")
|
||||
public interface DeviceConfigV2Client {
|
||||
|
||||
/**
|
||||
* 获取设备所有配置
|
||||
*/
|
||||
@GetMapping("/{deviceId}")
|
||||
CommonResponse<List<DeviceConfigV2DTO>> getDeviceConfigs(@PathVariable("deviceId") Long deviceId);
|
||||
|
||||
/**
|
||||
* 根据设备编号获取设备所有配置
|
||||
*/
|
||||
@GetMapping("/no/{no}")
|
||||
CommonResponse<List<DeviceConfigV2DTO>> getDeviceConfigsByNo(@PathVariable("no") String no);
|
||||
|
||||
/**
|
||||
* 获取设备特定配置
|
||||
*/
|
||||
@GetMapping("/{deviceId}/key/{configKey}")
|
||||
CommonResponse<DeviceConfigV2DTO> getDeviceConfigByKey(@PathVariable("deviceId") Long deviceId,
|
||||
@PathVariable("configKey") String configKey);
|
||||
|
||||
/**
|
||||
* 获取设备扁平化配置
|
||||
*/
|
||||
@GetMapping("/{deviceId}/flat")
|
||||
CommonResponse<Map<String, Object>> getDeviceFlatConfig(@PathVariable("deviceId") Long deviceId);
|
||||
|
||||
/**
|
||||
* 根据设备编号获取设备扁平化配置
|
||||
*/
|
||||
@GetMapping("/no/{no}/flat")
|
||||
CommonResponse<Map<String, Object>> getDeviceFlatConfigByNo(@PathVariable("no") String no);
|
||||
|
||||
/**
|
||||
* 创建设备配置
|
||||
*/
|
||||
@PostMapping("/{deviceId}")
|
||||
CommonResponse<DeviceConfigV2DTO> createDeviceConfig(@PathVariable("deviceId") Long deviceId,
|
||||
@RequestBody CreateDeviceConfigRequest request);
|
||||
|
||||
/**
|
||||
* 更新设备配置
|
||||
*/
|
||||
@PutMapping("/{deviceId}/{id}")
|
||||
CommonResponse<String> updateDeviceConfig(@PathVariable("deviceId") Long deviceId,
|
||||
@PathVariable("id") Long id,
|
||||
@RequestBody UpdateDeviceConfigRequest request);
|
||||
|
||||
/**
|
||||
* 删除设备配置
|
||||
*/
|
||||
@DeleteMapping("/{deviceId}/{id}")
|
||||
CommonResponse<String> deleteDeviceConfig(@PathVariable("deviceId") Long deviceId,
|
||||
@PathVariable("id") Long id);
|
||||
|
||||
/**
|
||||
* 批量更新设备配置
|
||||
*/
|
||||
@PostMapping("/{deviceId}/batch")
|
||||
CommonResponse<String> batchUpdateDeviceConfig(@PathVariable("deviceId") Long deviceId,
|
||||
@RequestBody BatchDeviceConfigRequest request);
|
||||
|
||||
/**
|
||||
* 扁平化批量更新设备配置
|
||||
*/
|
||||
@PostMapping("/{deviceId}/batch-flat")
|
||||
CommonResponse<String> batchFlatUpdateDeviceConfig(@PathVariable("deviceId") Long deviceId,
|
||||
@RequestBody Map<String, Object> configs);
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
package com.ycwl.basic.integration.device.client;
|
||||
|
||||
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||
import com.ycwl.basic.integration.device.dto.device.*;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@FeignClient(name = "zt-device", contextId = "device-v2", path = "/api/device/v2")
|
||||
public interface DeviceV2Client {
|
||||
|
||||
/**
|
||||
* 获取设备核心信息
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
CommonResponse<DeviceV2DTO> getDevice(@PathVariable("id") Long id);
|
||||
|
||||
/**
|
||||
* 根据设备编号获取设备核心信息
|
||||
*/
|
||||
@GetMapping("/no/{no}")
|
||||
CommonResponse<DeviceV2DTO> getDeviceByNo(@PathVariable("no") String no);
|
||||
|
||||
/**
|
||||
* 获取设备详细信息(含配置)
|
||||
*/
|
||||
@GetMapping("/{id}/with-config")
|
||||
CommonResponse<DeviceV2WithConfigDTO> getDeviceWithConfig(@PathVariable("id") Long id);
|
||||
|
||||
/**
|
||||
* 根据设备编号获取设备详细信息(含配置)
|
||||
*/
|
||||
@GetMapping("/no/{no}/with-config")
|
||||
CommonResponse<DeviceV2WithConfigDTO> getDeviceByNoWithConfig(@PathVariable("no") String no);
|
||||
|
||||
/**
|
||||
* 创建设备
|
||||
*/
|
||||
@PostMapping("/")
|
||||
CommonResponse<DeviceV2DTO> createDevice(@RequestBody CreateDeviceRequest request);
|
||||
|
||||
/**
|
||||
* 更新设备
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
CommonResponse<String> updateDevice(@PathVariable("id") Long id,
|
||||
@RequestBody UpdateDeviceRequest request);
|
||||
|
||||
/**
|
||||
* 删除设备
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
CommonResponse<String> deleteDevice(@PathVariable("id") Long id);
|
||||
|
||||
/**
|
||||
* 分页获取设备列表(核心信息)
|
||||
*/
|
||||
@GetMapping("/")
|
||||
CommonResponse<DeviceV2ListResponse> listDevices(
|
||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(value = "name", required = false) String name,
|
||||
@RequestParam(value = "no", required = false) String no,
|
||||
@RequestParam(value = "type", required = false) String type,
|
||||
@RequestParam(value = "isActive", required = false) Integer isActive,
|
||||
@RequestParam(value = "scenicId", required = false) Long scenicId);
|
||||
|
||||
/**
|
||||
* 分页获取设备列表(含配置)
|
||||
*/
|
||||
@GetMapping("/with-config")
|
||||
CommonResponse<DeviceV2WithConfigListResponse> listDevicesWithConfig(
|
||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(value = "name", required = false) String name,
|
||||
@RequestParam(value = "no", required = false) String no,
|
||||
@RequestParam(value = "type", required = false) String type,
|
||||
@RequestParam(value = "isActive", required = false) Integer isActive,
|
||||
@RequestParam(value = "scenicId", required = false) Long scenicId);
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package com.ycwl.basic.integration.device.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "integration.device")
|
||||
public class DeviceIntegrationConfig {
|
||||
|
||||
public DeviceIntegrationConfig() {
|
||||
log.info("ZT-Device集成配置初始化完成");
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package com.ycwl.basic.integration.device.dto.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class BatchDeviceConfigRequest {
|
||||
private List<BatchDeviceConfigItem> configs;
|
||||
|
||||
@Data
|
||||
public static class BatchDeviceConfigItem {
|
||||
private String configKey;
|
||||
private String configValue;
|
||||
private String configType;
|
||||
private String description;
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.integration.device.dto.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CreateDeviceConfigRequest {
|
||||
private String configKey;
|
||||
private String configValue;
|
||||
private String configType;
|
||||
private String description;
|
||||
private Integer isActive;
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package com.ycwl.basic.integration.device.dto.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class DeviceConfigV2DTO {
|
||||
@JsonProperty("id")
|
||||
private Long id;
|
||||
|
||||
@JsonProperty("deviceId")
|
||||
private Long deviceId;
|
||||
|
||||
@JsonProperty("configKey")
|
||||
private String configKey;
|
||||
|
||||
@JsonProperty("configValue")
|
||||
private String configValue;
|
||||
|
||||
@JsonProperty("configType")
|
||||
private String configType;
|
||||
|
||||
@JsonProperty("description")
|
||||
private String description;
|
||||
|
||||
@JsonProperty("isActive")
|
||||
private Integer isActive;
|
||||
|
||||
@JsonProperty("createTime")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@JsonProperty("updateTime")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package com.ycwl.basic.integration.device.dto.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class UpdateDeviceConfigRequest {
|
||||
private String configKey;
|
||||
private String configValue;
|
||||
private String configType;
|
||||
private String description;
|
||||
private Integer isActive;
|
||||
|
||||
// 支持灵活的字段更新
|
||||
public static UpdateDeviceConfigRequest fromMap(Map<String, Object> updates) {
|
||||
UpdateDeviceConfigRequest request = new UpdateDeviceConfigRequest();
|
||||
if (updates.containsKey("configKey")) {
|
||||
request.setConfigKey((String) updates.get("configKey"));
|
||||
}
|
||||
if (updates.containsKey("configValue")) {
|
||||
request.setConfigValue((String) updates.get("configValue"));
|
||||
}
|
||||
if (updates.containsKey("configType")) {
|
||||
request.setConfigType((String) updates.get("configType"));
|
||||
}
|
||||
if (updates.containsKey("description")) {
|
||||
request.setDescription((String) updates.get("description"));
|
||||
}
|
||||
if (updates.containsKey("isActive")) {
|
||||
request.setIsActive((Integer) updates.get("isActive"));
|
||||
}
|
||||
return request;
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.integration.device.dto.device;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CreateDeviceRequest {
|
||||
private String name;
|
||||
private String no;
|
||||
private String type;
|
||||
private Integer isActive;
|
||||
private Long scenicId;
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
package com.ycwl.basic.integration.device.dto.device;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class DeviceV2DTO {
|
||||
@JsonProperty("id")
|
||||
private Long id;
|
||||
|
||||
@JsonProperty("name")
|
||||
private String name;
|
||||
|
||||
@JsonProperty("no")
|
||||
private String no;
|
||||
|
||||
@JsonProperty("type")
|
||||
private String type; // IPC, CUSTOM
|
||||
|
||||
@JsonProperty("isActive")
|
||||
private Integer isActive;
|
||||
|
||||
@JsonProperty("scenicId")
|
||||
private Long scenicId;
|
||||
|
||||
@JsonProperty("createTime")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@JsonProperty("updateTime")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime updateTime;
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.ycwl.basic.integration.device.dto.device;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class DeviceV2ListResponse {
|
||||
private List<DeviceV2DTO> list;
|
||||
private Long total;
|
||||
private Integer page;
|
||||
private Integer pageSize;
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.integration.device.dto.device;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DeviceV2WithConfigDTO extends DeviceV2DTO {
|
||||
private Map<String, Object> config;
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.ycwl.basic.integration.device.dto.device;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class DeviceV2WithConfigListResponse {
|
||||
private List<DeviceV2WithConfigDTO> list;
|
||||
private Long total;
|
||||
private Integer page;
|
||||
private Integer pageSize;
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.ycwl.basic.integration.device.dto.device;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UpdateDeviceRequest {
|
||||
private String name;
|
||||
private String no;
|
||||
private String type;
|
||||
private Integer isActive;
|
||||
private Long scenicId;
|
||||
}
|
@@ -0,0 +1,243 @@
|
||||
package com.ycwl.basic.integration.device.example;
|
||||
|
||||
import com.ycwl.basic.integration.device.dto.device.*;
|
||||
import com.ycwl.basic.integration.device.dto.config.*;
|
||||
import com.ycwl.basic.integration.device.service.DeviceConfigIntegrationService;
|
||||
import com.ycwl.basic.integration.device.service.DeviceIntegrationService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Device Integration 使用示例
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class DeviceIntegrationExample {
|
||||
|
||||
private final DeviceIntegrationService deviceService;
|
||||
private final DeviceConfigIntegrationService deviceConfigService;
|
||||
|
||||
/**
|
||||
* 基本设备操作示例
|
||||
*/
|
||||
public void basicDeviceOperations() {
|
||||
log.info("=== 基本设备操作示例 ===");
|
||||
|
||||
// 1. 创建IPC摄像头设备
|
||||
DeviceV2DTO ipcDevice = deviceService.createIpcDevice(
|
||||
"前门摄像头", "CAM001", 1001L);
|
||||
log.info("创建IPC设备: {}", ipcDevice);
|
||||
|
||||
// 2. 创建自定义设备
|
||||
DeviceV2DTO customDevice = deviceService.createCustomDevice(
|
||||
"温度传感器", "TEMP001", 1001L);
|
||||
log.info("创建自定义设备: {}", customDevice);
|
||||
|
||||
// 3. 根据ID获取设备信息
|
||||
DeviceV2DTO device = deviceService.getDevice(ipcDevice.getId());
|
||||
log.info("获取设备信息: {}", device);
|
||||
|
||||
// 4. 根据设备编号获取设备信息
|
||||
DeviceV2DTO deviceByNo = deviceService.getDeviceByNo("CAM001");
|
||||
log.info("根据编号获取设备: {}", deviceByNo);
|
||||
|
||||
// 5. 获取设备详细信息(含配置)
|
||||
DeviceV2WithConfigDTO deviceWithConfig = deviceService.getDeviceWithConfig(ipcDevice.getId());
|
||||
log.info("获取设备配置: {}", deviceWithConfig);
|
||||
|
||||
// 6. 分页查询景区设备列表
|
||||
DeviceV2ListResponse deviceList = deviceService.getScenicIpcDevices(1001L, 1, 10);
|
||||
log.info("景区IPC设备列表: 总数={}, 当前页={}", deviceList.getTotal(), deviceList.getList().size());
|
||||
|
||||
// 7. 启用/禁用设备
|
||||
deviceService.enableDevice(ipcDevice.getId());
|
||||
log.info("设备已启用");
|
||||
|
||||
deviceService.disableDevice(customDevice.getId());
|
||||
log.info("设备已禁用");
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备配置管理示例
|
||||
*/
|
||||
public void deviceConfigurationOperations() {
|
||||
log.info("=== 设备配置管理示例 ===");
|
||||
|
||||
// 假设已有设备ID
|
||||
Long deviceId = 1L;
|
||||
|
||||
// 1. 配置摄像头基本参数
|
||||
deviceConfigService.configureCameraBasicParams(
|
||||
deviceId, "192.168.1.100", "1920x1080", 30, "RTSP");
|
||||
log.info("摄像头基本参数已配置");
|
||||
|
||||
// 2. 配置摄像头完整参数(包含认证)
|
||||
deviceConfigService.configureCameraFullParams(
|
||||
deviceId, "192.168.1.101", "3840x2160", 25, "RTSP", "admin", "password123");
|
||||
log.info("摄像头完整参数已配置");
|
||||
|
||||
// 3. 单独设置特定配置
|
||||
deviceConfigService.setDeviceIpAddress(deviceId, "192.168.1.102");
|
||||
deviceConfigService.setDeviceResolution(deviceId, "2560x1440");
|
||||
deviceConfigService.setDeviceFramerate(deviceId, 60);
|
||||
log.info("单独配置项已更新");
|
||||
|
||||
// 4. 获取设备所有配置
|
||||
List<DeviceConfigV2DTO> configs = deviceConfigService.getDeviceConfigs(deviceId);
|
||||
log.info("设备配置列表: {}", configs.size());
|
||||
|
||||
// 5. 获取扁平化配置
|
||||
Map<String, Object> flatConfig = deviceConfigService.getDeviceFlatConfig(deviceId);
|
||||
log.info("扁平化配置: {}", flatConfig);
|
||||
|
||||
// 6. 获取特定配置值
|
||||
String ipAddress = deviceConfigService.getDeviceIpAddress(deviceId);
|
||||
String resolution = deviceConfigService.getDeviceResolution(deviceId);
|
||||
log.info("IP地址: {}, 分辨率: {}", ipAddress, resolution);
|
||||
|
||||
// 7. 批量更新配置
|
||||
Map<String, Object> batchConfigs = new HashMap<>();
|
||||
batchConfigs.put("brightness", "50");
|
||||
batchConfigs.put("contrast", "80");
|
||||
batchConfigs.put("quality", "high");
|
||||
deviceConfigService.batchFlatUpdateDeviceConfig(deviceId, batchConfigs);
|
||||
log.info("批量配置已更新");
|
||||
}
|
||||
|
||||
/**
|
||||
* 摄像头管理示例
|
||||
*/
|
||||
public void cameraManagementExample() {
|
||||
log.info("=== 摄像头管理示例 ===");
|
||||
|
||||
Long scenicId = 1001L;
|
||||
|
||||
// 1. 批量创建摄像头
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
DeviceV2DTO camera = deviceService.createIpcDevice(
|
||||
"摄像头" + i, "CAM00" + i, scenicId);
|
||||
|
||||
// 配置每个摄像头的基本参数
|
||||
deviceConfigService.configureCameraFullParams(
|
||||
camera.getId(),
|
||||
"192.168.1." + (100 + i),
|
||||
"1920x1080",
|
||||
30,
|
||||
"RTSP",
|
||||
"admin",
|
||||
"camera" + i
|
||||
);
|
||||
log.info("创建并配置摄像头: {}", camera.getName());
|
||||
}
|
||||
|
||||
// 2. 获取景区所有摄像头状态
|
||||
DeviceV2WithConfigListResponse camerasWithConfig =
|
||||
deviceService.listDevicesWithConfig(1, 100, null, null, "IPC", 1, scenicId);
|
||||
|
||||
log.info("景区摄像头总数: {}", camerasWithConfig.getTotal());
|
||||
for (DeviceV2WithConfigDTO camera : camerasWithConfig.getList()) {
|
||||
log.info("摄像头: {}, IP: {}",
|
||||
camera.getName(),
|
||||
camera.getConfig().get("ip_address"));
|
||||
}
|
||||
|
||||
// 3. 批量更新摄像头分辨率
|
||||
for (DeviceV2WithConfigDTO camera : camerasWithConfig.getList()) {
|
||||
deviceConfigService.setDeviceResolution(camera.getId(), "2560x1440");
|
||||
}
|
||||
log.info("所有摄像头分辨率已更新为 2560x1440");
|
||||
}
|
||||
|
||||
/**
|
||||
* 设备监控和状态管理示例
|
||||
*/
|
||||
public void deviceMonitoringExample() {
|
||||
log.info("=== 设备监控和状态管理示例 ===");
|
||||
|
||||
Long scenicId = 1001L;
|
||||
|
||||
// 1. 获取景区所有激活设备
|
||||
DeviceV2ListResponse activeDevices = deviceService.getScenicActiveDevices(scenicId, 1, 50);
|
||||
log.info("景区激活设备数量: {}", activeDevices.getTotal());
|
||||
|
||||
// 2. 按设备类型分类统计
|
||||
Map<String, Integer> deviceTypeCount = new HashMap<>();
|
||||
for (DeviceV2DTO device : activeDevices.getList()) {
|
||||
deviceTypeCount.merge(device.getType(), 1, Integer::sum);
|
||||
}
|
||||
log.info("设备类型统计: {}", deviceTypeCount);
|
||||
|
||||
// 3. 检查设备配置完整性
|
||||
for (DeviceV2DTO device : activeDevices.getList()) {
|
||||
try {
|
||||
Map<String, Object> config = deviceConfigService.getDeviceFlatConfig(device.getId());
|
||||
boolean hasIpConfig = config.containsKey("ip_address");
|
||||
log.info("设备 {} 配置状态: IP配置={}", device.getName(), hasIpConfig ? "已配置" : "未配置");
|
||||
} catch (Exception e) {
|
||||
log.warn("获取设备 {} 配置失败: {}", device.getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 按设备编号搜索
|
||||
try {
|
||||
DeviceV2WithConfigDTO deviceByNo = deviceService.getDeviceWithConfigByNo("CAM001");
|
||||
log.info("根据编号找到设备: {} (配置项数量: {})",
|
||||
deviceByNo.getName(),
|
||||
deviceByNo.getConfig().size());
|
||||
} catch (Exception e) {
|
||||
log.warn("未找到设备编号 CAM001: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误处理和故障恢复示例
|
||||
*/
|
||||
public void errorHandlingExample() {
|
||||
log.info("=== 错误处理和故障恢复示例 ===");
|
||||
|
||||
// 1. 尝试获取不存在的设备
|
||||
try {
|
||||
deviceService.getDevice(99999L);
|
||||
} catch (Exception e) {
|
||||
log.warn("获取不存在设备的预期错误: {}", e.getMessage());
|
||||
}
|
||||
|
||||
// 2. 尝试获取不存在的配置
|
||||
try {
|
||||
deviceConfigService.getDeviceConfigByKey(1L, "non_existent_key");
|
||||
} catch (Exception e) {
|
||||
log.warn("获取不存在配置的预期错误: {}", e.getMessage());
|
||||
}
|
||||
|
||||
// 3. 创建设备时的参数验证
|
||||
try {
|
||||
CreateDeviceRequest invalidRequest = new CreateDeviceRequest();
|
||||
// 缺少必要字段
|
||||
deviceService.createDevice(invalidRequest);
|
||||
} catch (Exception e) {
|
||||
log.warn("创建设备参数错误: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行所有示例
|
||||
*/
|
||||
public void runAllExamples() {
|
||||
try {
|
||||
basicDeviceOperations();
|
||||
deviceConfigurationOperations();
|
||||
cameraManagementExample();
|
||||
deviceMonitoringExample();
|
||||
errorHandlingExample();
|
||||
log.info("=== 所有示例执行完成 ===");
|
||||
} catch (Exception e) {
|
||||
log.error("示例执行过程中发生错误", e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,188 @@
|
||||
package com.ycwl.basic.integration.device.service;
|
||||
|
||||
import com.ycwl.basic.integration.common.exception.IntegrationException;
|
||||
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||
import com.ycwl.basic.integration.device.client.DeviceConfigV2Client;
|
||||
import com.ycwl.basic.integration.device.dto.config.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DeviceConfigIntegrationService {
|
||||
|
||||
private final DeviceConfigV2Client deviceConfigV2Client;
|
||||
|
||||
public List<DeviceConfigV2DTO> getDeviceConfigs(Long deviceId) {
|
||||
log.info("获取设备配置列表, deviceId: {}", deviceId);
|
||||
CommonResponse<List<DeviceConfigV2DTO>> response = deviceConfigV2Client.getDeviceConfigs(deviceId);
|
||||
return handleResponse(response, "获取设备配置列表失败");
|
||||
}
|
||||
|
||||
public List<DeviceConfigV2DTO> getDeviceConfigsByNo(String deviceNo) {
|
||||
log.info("根据设备编号获取配置列表, deviceNo: {}", deviceNo);
|
||||
CommonResponse<List<DeviceConfigV2DTO>> response = deviceConfigV2Client.getDeviceConfigsByNo(deviceNo);
|
||||
return handleResponse(response, "根据设备编号获取配置列表失败");
|
||||
}
|
||||
|
||||
public DeviceConfigV2DTO getDeviceConfigByKey(Long deviceId, String configKey) {
|
||||
log.info("根据键获取设备配置, deviceId: {}, configKey: {}", deviceId, configKey);
|
||||
CommonResponse<DeviceConfigV2DTO> response = deviceConfigV2Client.getDeviceConfigByKey(deviceId, configKey);
|
||||
return handleResponse(response, "根据键获取设备配置失败");
|
||||
}
|
||||
|
||||
public Map<String, Object> getDeviceFlatConfig(Long deviceId) {
|
||||
log.info("获取设备扁平化配置, deviceId: {}", deviceId);
|
||||
CommonResponse<Map<String, Object>> response = deviceConfigV2Client.getDeviceFlatConfig(deviceId);
|
||||
return handleResponse(response, "获取设备扁平化配置失败");
|
||||
}
|
||||
|
||||
public Map<String, Object> getDeviceFlatConfigByNo(String deviceNo) {
|
||||
log.info("根据设备编号获取扁平化配置, deviceNo: {}", deviceNo);
|
||||
CommonResponse<Map<String, Object>> response = deviceConfigV2Client.getDeviceFlatConfigByNo(deviceNo);
|
||||
return handleResponse(response, "根据设备编号获取扁平化配置失败");
|
||||
}
|
||||
|
||||
public DeviceConfigV2DTO createDeviceConfig(Long deviceId, CreateDeviceConfigRequest request) {
|
||||
log.info("创建设备配置, deviceId: {}, configKey: {}", deviceId, request.getConfigKey());
|
||||
CommonResponse<DeviceConfigV2DTO> response = deviceConfigV2Client.createDeviceConfig(deviceId, request);
|
||||
return handleResponse(response, "创建设备配置失败");
|
||||
}
|
||||
|
||||
public void updateDeviceConfig(Long deviceId, Long configId, UpdateDeviceConfigRequest request) {
|
||||
log.info("更新设备配置, deviceId: {}, configId: {}", deviceId, configId);
|
||||
CommonResponse<String> response = deviceConfigV2Client.updateDeviceConfig(deviceId, configId, request);
|
||||
handleResponse(response, "更新设备配置失败");
|
||||
}
|
||||
|
||||
public void deleteDeviceConfig(Long deviceId, Long configId) {
|
||||
log.info("删除设备配置, deviceId: {}, configId: {}", deviceId, configId);
|
||||
CommonResponse<String> response = deviceConfigV2Client.deleteDeviceConfig(deviceId, configId);
|
||||
handleResponse(response, "删除设备配置失败");
|
||||
}
|
||||
|
||||
public void batchUpdateDeviceConfig(Long deviceId, BatchDeviceConfigRequest request) {
|
||||
log.info("批量更新设备配置, deviceId: {}, configs count: {}", deviceId, request.getConfigs().size());
|
||||
CommonResponse<String> response = deviceConfigV2Client.batchUpdateDeviceConfig(deviceId, request);
|
||||
handleResponse(response, "批量更新设备配置失败");
|
||||
}
|
||||
|
||||
public void batchFlatUpdateDeviceConfig(Long deviceId, Map<String, Object> configs) {
|
||||
log.info("扁平化批量更新设备配置, deviceId: {}, configs count: {}", deviceId, configs.size());
|
||||
CommonResponse<String> response = deviceConfigV2Client.batchFlatUpdateDeviceConfig(deviceId, configs);
|
||||
handleResponse(response, "扁平化批量更新设备配置失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置设备IP地址
|
||||
*/
|
||||
public void setDeviceIpAddress(Long deviceId, String ipAddress) {
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
config.put("ip_address", ipAddress);
|
||||
batchFlatUpdateDeviceConfig(deviceId, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置设备分辨率
|
||||
*/
|
||||
public void setDeviceResolution(Long deviceId, String resolution) {
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
config.put("resolution", resolution);
|
||||
batchFlatUpdateDeviceConfig(deviceId, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置设备帧率
|
||||
*/
|
||||
public void setDeviceFramerate(Long deviceId, Integer framerate) {
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
config.put("framerate", framerate.toString());
|
||||
batchFlatUpdateDeviceConfig(deviceId, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置设备协议
|
||||
*/
|
||||
public void setDeviceProtocol(Long deviceId, String protocol) {
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
config.put("protocol", protocol);
|
||||
batchFlatUpdateDeviceConfig(deviceId, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置设备认证信息
|
||||
*/
|
||||
public void setDeviceAuth(Long deviceId, String username, String password) {
|
||||
Map<String, Object> config = new HashMap<>();
|
||||
config.put("username", username);
|
||||
config.put("password", password);
|
||||
batchFlatUpdateDeviceConfig(deviceId, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置摄像头基本参数
|
||||
*/
|
||||
public void configureCameraBasicParams(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) {
|
||||
Map<String, Object> 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);
|
||||
batchFlatUpdateDeviceConfig(deviceId, configs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备特定配置值
|
||||
*/
|
||||
public String getDeviceConfigValue(Long deviceId, String configKey) {
|
||||
DeviceConfigV2DTO config = getDeviceConfigByKey(deviceId, configKey);
|
||||
return config != null ? config.getConfigValue() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备IP地址
|
||||
*/
|
||||
public String getDeviceIpAddress(Long deviceId) {
|
||||
return getDeviceConfigValue(deviceId, "ip_address");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取设备分辨率
|
||||
*/
|
||||
public String getDeviceResolution(Long deviceId) {
|
||||
return getDeviceConfigValue(deviceId, "resolution");
|
||||
}
|
||||
|
||||
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, "zt-device");
|
||||
}
|
||||
return response.getData();
|
||||
}
|
||||
}
|
@@ -0,0 +1,146 @@
|
||||
package com.ycwl.basic.integration.device.service;
|
||||
|
||||
import com.ycwl.basic.integration.common.exception.IntegrationException;
|
||||
import com.ycwl.basic.integration.common.response.CommonResponse;
|
||||
import com.ycwl.basic.integration.device.client.DeviceV2Client;
|
||||
import com.ycwl.basic.integration.device.dto.device.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DeviceIntegrationService {
|
||||
|
||||
private final DeviceV2Client deviceV2Client;
|
||||
|
||||
public DeviceV2DTO getDevice(Long deviceId) {
|
||||
log.info("获取设备信息, deviceId: {}", deviceId);
|
||||
CommonResponse<DeviceV2DTO> response = deviceV2Client.getDevice(deviceId);
|
||||
return handleResponse(response, "获取设备信息失败");
|
||||
}
|
||||
|
||||
public DeviceV2DTO getDeviceByNo(String deviceNo) {
|
||||
log.info("根据设备编号获取设备信息, deviceNo: {}", deviceNo);
|
||||
CommonResponse<DeviceV2DTO> response = deviceV2Client.getDeviceByNo(deviceNo);
|
||||
return handleResponse(response, "根据设备编号获取设备信息失败");
|
||||
}
|
||||
|
||||
public DeviceV2WithConfigDTO getDeviceWithConfig(Long deviceId) {
|
||||
log.info("获取设备配置信息, deviceId: {}", deviceId);
|
||||
CommonResponse<DeviceV2WithConfigDTO> response = deviceV2Client.getDeviceWithConfig(deviceId);
|
||||
return handleResponse(response, "获取设备配置信息失败");
|
||||
}
|
||||
|
||||
public DeviceV2WithConfigDTO getDeviceWithConfigByNo(String deviceNo) {
|
||||
log.info("根据设备编号获取设备配置信息, deviceNo: {}", deviceNo);
|
||||
CommonResponse<DeviceV2WithConfigDTO> response = deviceV2Client.getDeviceByNoWithConfig(deviceNo);
|
||||
return handleResponse(response, "根据设备编号获取设备配置信息失败");
|
||||
}
|
||||
|
||||
public DeviceV2DTO createDevice(CreateDeviceRequest request) {
|
||||
log.info("创建设备, name: {}, no: {}, type: {}", request.getName(), request.getNo(), request.getType());
|
||||
CommonResponse<DeviceV2DTO> response = deviceV2Client.createDevice(request);
|
||||
return handleResponse(response, "创建设备失败");
|
||||
}
|
||||
|
||||
public void updateDevice(Long deviceId, UpdateDeviceRequest request) {
|
||||
log.info("更新设备信息, deviceId: {}", deviceId);
|
||||
CommonResponse<String> response = deviceV2Client.updateDevice(deviceId, request);
|
||||
handleResponse(response, "更新设备信息失败");
|
||||
}
|
||||
|
||||
public void deleteDevice(Long deviceId) {
|
||||
log.info("删除设备, deviceId: {}", deviceId);
|
||||
CommonResponse<String> response = deviceV2Client.deleteDevice(deviceId);
|
||||
handleResponse(response, "删除设备失败");
|
||||
}
|
||||
|
||||
public DeviceV2ListResponse listDevices(Integer page, Integer pageSize, String name, String no,
|
||||
String type, Integer isActive, Long scenicId) {
|
||||
log.info("分页查询设备列表, page: {}, pageSize: {}, name: {}, no: {}, type: {}, isActive: {}, scenicId: {}",
|
||||
page, pageSize, name, no, type, isActive, scenicId);
|
||||
CommonResponse<DeviceV2ListResponse> response = deviceV2Client.listDevices(
|
||||
page, pageSize, name, no, type, isActive, scenicId);
|
||||
return handleResponse(response, "分页查询设备列表失败");
|
||||
}
|
||||
|
||||
public DeviceV2WithConfigListResponse listDevicesWithConfig(Integer page, Integer pageSize, String name, String no,
|
||||
String type, Integer isActive, Long scenicId) {
|
||||
log.info("分页查询设备带配置列表, page: {}, pageSize: {}, name: {}, no: {}, type: {}, isActive: {}, scenicId: {}",
|
||||
page, pageSize, name, no, type, isActive, scenicId);
|
||||
CommonResponse<DeviceV2WithConfigListResponse> response = deviceV2Client.listDevicesWithConfig(
|
||||
page, pageSize, name, no, type, isActive, scenicId);
|
||||
return handleResponse(response, "分页查询设备带配置列表失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建IPC摄像头设备
|
||||
*/
|
||||
public DeviceV2DTO createIpcDevice(String name, String deviceNo, Long scenicId) {
|
||||
CreateDeviceRequest request = new CreateDeviceRequest();
|
||||
request.setName(name);
|
||||
request.setNo(deviceNo);
|
||||
request.setType("IPC");
|
||||
request.setIsActive(1);
|
||||
request.setScenicId(scenicId);
|
||||
return createDevice(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建自定义设备
|
||||
*/
|
||||
public DeviceV2DTO createCustomDevice(String name, String deviceNo, Long scenicId) {
|
||||
CreateDeviceRequest request = new CreateDeviceRequest();
|
||||
request.setName(name);
|
||||
request.setNo(deviceNo);
|
||||
request.setType("CUSTOM");
|
||||
request.setIsActive(1);
|
||||
request.setScenicId(scenicId);
|
||||
return createDevice(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用设备
|
||||
*/
|
||||
public void enableDevice(Long deviceId) {
|
||||
UpdateDeviceRequest request = new UpdateDeviceRequest();
|
||||
request.setIsActive(1);
|
||||
updateDevice(deviceId, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用设备
|
||||
*/
|
||||
public void disableDevice(Long deviceId) {
|
||||
UpdateDeviceRequest request = new UpdateDeviceRequest();
|
||||
request.setIsActive(0);
|
||||
updateDevice(deviceId, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取景区的IPC设备列表
|
||||
*/
|
||||
public DeviceV2ListResponse getScenicIpcDevices(Long scenicId, Integer page, Integer pageSize) {
|
||||
return listDevices(page, pageSize, null, null, "IPC", 1, scenicId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取景区的所有激活设备
|
||||
*/
|
||||
public DeviceV2ListResponse getScenicActiveDevices(Long scenicId, Integer page, Integer pageSize) {
|
||||
return listDevices(page, pageSize, null, null, null, 1, scenicId);
|
||||
}
|
||||
|
||||
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, "zt-device");
|
||||
}
|
||||
return response.getData();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user