427 lines
15 KiB
Markdown
427 lines
15 KiB
Markdown
|
|
# Design Document: Infrared Camera Data Query Enhancement
|
|||
|
|
|
|||
|
|
## Overview
|
|||
|
|
|
|||
|
|
This design enhances the `FindDatas` method in `MeasuresTemperatureResultAppService` to query temperature measurement data from infrared cameras stored in the `OriginalInspectionStoreResult` MongoDB collection. The enhancement introduces intelligent camera identification, fuzzy equipment name matching with 85% similarity threshold, and structured parsing of temperature data from result strings.
|
|||
|
|
|
|||
|
|
The design maintains backward compatibility with existing thermal imaging device queries while adding support for infrared camera data sources.
|
|||
|
|
|
|||
|
|
## Architecture
|
|||
|
|
|
|||
|
|
### High-Level Flow
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
FindDatas Request
|
|||
|
|
↓
|
|||
|
|
[1] Apply Infrared Camera Filter (CamName contains "热成像" OR ends with 'B')
|
|||
|
|
↓
|
|||
|
|
[2] Query OriginalInspectionStoreResult with time/filters
|
|||
|
|
↓
|
|||
|
|
[3] For each result:
|
|||
|
|
├─ Apply Equipment Fuzzy Matching (85% similarity)
|
|||
|
|
├─ Parse Temperature Data from Result field
|
|||
|
|
└─ Create MeasureTemperatureResultOutput records
|
|||
|
|
↓
|
|||
|
|
[4] Apply Name Filter (if specified)
|
|||
|
|
↓
|
|||
|
|
[5] Sort, Paginate, Return Results
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Integration Points
|
|||
|
|
|
|||
|
|
- **Existing Method**: `FindMeasureTempertureResults` - Currently handles thermal imaging devices (DevType 12, 22)
|
|||
|
|
- **New Data Source**: `OriginalInspectionStoreResult` collection - Contains infrared camera inspection data
|
|||
|
|
- **Shared Output**: `MeasureTemperatureResultOutput` - Common DTO for all temperature results
|
|||
|
|
|
|||
|
|
## Components and Interfaces
|
|||
|
|
|
|||
|
|
### Modified Method Signature
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
[HttpPost, Description("查询温度测量结果")]
|
|||
|
|
[Abp.Domain.Uow.UnitOfWork(true)]
|
|||
|
|
[AbpAllowAnonymous]
|
|||
|
|
[ShowApi]
|
|||
|
|
public RequestPageResult<MeasureTemperatureResultOutput> FindDatas(
|
|||
|
|
PageSearchCondition<MeasureTemperatureResultSearchConditonInput> searchCondition)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### New Helper Methods
|
|||
|
|
|
|||
|
|
#### 1. IsInfraredCamera
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
/// <summary>
|
|||
|
|
/// Determines if a camera name indicates an infrared camera
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="camName">Camera name from OriginalInspectionStoreResult</param>
|
|||
|
|
/// <returns>True if camera is infrared type</returns>
|
|||
|
|
private bool IsInfraredCamera(string camName)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Logic:**
|
|||
|
|
- Returns `true` if `camName` contains "热成像"
|
|||
|
|
- Returns `true` if `camName` ends with 'B'
|
|||
|
|
- Returns `false` otherwise
|
|||
|
|
- Handles null/empty strings safely
|
|||
|
|
|
|||
|
|
#### 2. CalculateSimilarity (Enhanced)
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
/// <summary>
|
|||
|
|
/// Calculates string similarity using Levenshtein distance algorithm
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="source">Source string</param>
|
|||
|
|
/// <param name="target">Target string</param>
|
|||
|
|
/// <returns>Similarity score between 0.0 and 1.0</returns>
|
|||
|
|
private double CalculateSimilarity(string source, string target)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Current Implementation Issue:**
|
|||
|
|
The existing implementation uses simple character matching which is not accurate for 85% similarity requirements.
|
|||
|
|
|
|||
|
|
**Enhanced Logic:**
|
|||
|
|
- Use Levenshtein distance algorithm for accurate similarity calculation
|
|||
|
|
- Formula: `similarity = 1.0 - (levenshteinDistance / maxLength)`
|
|||
|
|
- Handle null/empty strings by returning 0.0
|
|||
|
|
- Case-insensitive comparison
|
|||
|
|
|
|||
|
|
#### 3. ParseTemperatureFromInfraredResult
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
/// <summary>
|
|||
|
|
/// Parses temperature data from infrared camera result string
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="data">Original inspection store result</param>
|
|||
|
|
/// <param name="equipmentInfo">Associated equipment (may be null)</param>
|
|||
|
|
/// <returns>List of temperature measurement outputs</returns>
|
|||
|
|
private List<MeasureTemperatureResultOutput> ParseTemperatureFromInfraredResult(
|
|||
|
|
OriginalInspectionStoreResult data,
|
|||
|
|
EquipmentInfo equipmentInfo)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Logic:**
|
|||
|
|
- Split `Result` field by delimiters: `,`, `,`, `\r\n`, `\n`
|
|||
|
|
- For each segment:
|
|||
|
|
- Check if contains `:` or `:`
|
|||
|
|
- If yes: split into name and value parts
|
|||
|
|
- Extract numeric temperature using regex: `@"-?\d+(?:\.\d+)?"`
|
|||
|
|
- Create `MeasureTemperatureResultOutput` with parsed data
|
|||
|
|
- Handle missing/invalid data gracefully
|
|||
|
|
- Log parsing failures with original Result string
|
|||
|
|
|
|||
|
|
#### 4. MatchesEquipmentByName
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
/// <summary>
|
|||
|
|
/// Checks if inspection data matches equipment using fuzzy name matching
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="data">Original inspection store result</param>
|
|||
|
|
/// <param name="equipment">Equipment to match against</param>
|
|||
|
|
/// <param name="threshold">Similarity threshold (default 0.85)</param>
|
|||
|
|
/// <returns>True if names match with sufficient similarity</returns>
|
|||
|
|
private bool MatchesEquipmentByName(
|
|||
|
|
OriginalInspectionStoreResult data,
|
|||
|
|
EquipmentInfo equipment,
|
|||
|
|
double threshold = 0.85)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Logic:**
|
|||
|
|
- Check `data.EquipmentInfoName` against `equipment.Name`
|
|||
|
|
- Check `data.Name` against `equipment.Name`
|
|||
|
|
- Return `true` if either similarity >= threshold
|
|||
|
|
- Return `false` if both similarities < threshold
|
|||
|
|
|
|||
|
|
## Data Models
|
|||
|
|
|
|||
|
|
### Input: MeasureTemperatureResultSearchConditonInput
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public class MeasureTemperatureResultSearchConditonInput
|
|||
|
|
{
|
|||
|
|
public Guid? EquipmentInfoId { get; set; }
|
|||
|
|
public string Name { get; set; }
|
|||
|
|
public DateTime? StartTime { get; set; }
|
|||
|
|
public DateTime? EndTime { get; set; }
|
|||
|
|
// ... other existing properties
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Source: OriginalInspectionStoreResult
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public class OriginalInspectionStoreResult
|
|||
|
|
{
|
|||
|
|
public string CamName { get; set; } // Camera identifier
|
|||
|
|
public string PresetCode { get; set; } // Preset position code
|
|||
|
|
public string Result { get; set; } // Temperature data string
|
|||
|
|
public DateTime Time { get; set; } // Measurement time
|
|||
|
|
public string CaptureTime { get; set; } // Capture timestamp
|
|||
|
|
public string Status { get; set; } // Status code
|
|||
|
|
public string Message { get; set; } // Result message
|
|||
|
|
public string Name { get; set; } // Item name
|
|||
|
|
public string EquipmentInfoName { get; set; } // Equipment name
|
|||
|
|
public Guid? EquipmentInfoId { get; set; } // Equipment ID
|
|||
|
|
// ... other properties
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Output: MeasureTemperatureResultOutput
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
public class MeasureTemperatureResultOutput
|
|||
|
|
{
|
|||
|
|
public Guid Id { get; set; }
|
|||
|
|
public Guid MeasureTemperaturePointId { get; set; }
|
|||
|
|
public int Number { get; set; }
|
|||
|
|
public string Name { get; set; }
|
|||
|
|
public float? TemperatureValue { get; set; }
|
|||
|
|
public string Message { get; set; }
|
|||
|
|
public DateTime? MeasureTime { get; set; }
|
|||
|
|
public int Status { get; set; }
|
|||
|
|
public Guid? EquipmentInfoId { get; set; }
|
|||
|
|
public string EquipmentInfoName { get; set; }
|
|||
|
|
// ... other properties
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Correctness Properties
|
|||
|
|
|
|||
|
|
*A property is a characteristic or behavior that should hold true across all valid executions of a system—essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
|
|||
|
|
|
|||
|
|
### Property 1: Infrared Camera Identification Completeness
|
|||
|
|
|
|||
|
|
*For any* OriginalInspectionStoreResult record where CamName contains "热成像" or ends with 'B', the IsInfraredCamera method should return true.
|
|||
|
|
|
|||
|
|
**Validates: Requirements 1.1, 1.2, 1.3**
|
|||
|
|
|
|||
|
|
### Property 2: Similarity Calculation Symmetry
|
|||
|
|
|
|||
|
|
*For any* two non-empty strings A and B, CalculateSimilarity(A, B) should equal CalculateSimilarity(B, A).
|
|||
|
|
|
|||
|
|
**Validates: Requirements 2.4**
|
|||
|
|
|
|||
|
|
### Property 3: Similarity Score Bounds
|
|||
|
|
|
|||
|
|
*For any* two strings A and B, CalculateSimilarity(A, B) should return a value between 0.0 and 1.0 inclusive.
|
|||
|
|
|
|||
|
|
**Validates: Requirements 2.4**
|
|||
|
|
|
|||
|
|
### Property 4: Equipment Matching Threshold
|
|||
|
|
|
|||
|
|
*For any* OriginalInspectionStoreResult and Equipment pair, if either EquipmentInfoName or Name has similarity >= 0.85 with Equipment.Name, then MatchesEquipmentByName should return true.
|
|||
|
|
|
|||
|
|
**Validates: Requirements 2.5, 2.6**
|
|||
|
|
|
|||
|
|
### Property 5: Valid Temperature Data Parsing
|
|||
|
|
|
|||
|
|
*For any* Result string containing segments in format "name:value" where value is numeric, ParseTemperatureFromInfraredResult should extract at least one MeasureTemperatureResultOutput with non-null TemperatureValue.
|
|||
|
|
|
|||
|
|
**Validates: Requirements 3.1, 3.2, 3.3, 3.5, 3.6**
|
|||
|
|
|
|||
|
|
### Property 6: Invalid Segment Skipping
|
|||
|
|
|
|||
|
|
*For any* Result string containing segments without colons, ParseTemperatureFromInfraredResult should skip those segments and continue processing remaining segments.
|
|||
|
|
|
|||
|
|
**Validates: Requirements 3.4, 3.7**
|
|||
|
|
|
|||
|
|
### Property 7: Filter Application Order
|
|||
|
|
|
|||
|
|
*For any* query with time range, equipment filter, and name filter, the System should apply filters in order: infrared camera → time range → equipment matching → temperature parsing → name filtering.
|
|||
|
|
|
|||
|
|
**Validates: Requirements 4.1, 4.2, 4.3, 4.4, 4.5**
|
|||
|
|
|
|||
|
|
### Property 8: Null Safety in Similarity Calculation
|
|||
|
|
|
|||
|
|
*For any* call to CalculateSimilarity where either parameter is null or empty, the method should return 0.0 without throwing exceptions.
|
|||
|
|
|
|||
|
|
**Validates: Requirements 5.2**
|
|||
|
|
|
|||
|
|
### Property 9: Parsing Error Isolation
|
|||
|
|
|
|||
|
|
*For any* OriginalInspectionStoreResult with invalid Result format, parsing failures should not prevent processing of other records in the result set.
|
|||
|
|
|
|||
|
|
**Validates: Requirements 5.1, 5.5**
|
|||
|
|
|
|||
|
|
## Error Handling
|
|||
|
|
|
|||
|
|
### Exception Scenarios
|
|||
|
|
|
|||
|
|
1. **MongoDB Query Failures**
|
|||
|
|
- Catch: `MongoException`, `TimeoutException`
|
|||
|
|
- Action: Log error with query details, return error response
|
|||
|
|
- User Message: "数据库查询失败,请稍后重试"
|
|||
|
|
|
|||
|
|
2. **Temperature Parsing Failures**
|
|||
|
|
- Catch: `FormatException`, `RegexMatchTimeoutException`
|
|||
|
|
- Action: Log warning with Result string, skip record, continue
|
|||
|
|
- No user-facing error (graceful degradation)
|
|||
|
|
|
|||
|
|
3. **Similarity Calculation Errors**
|
|||
|
|
- Catch: `ArgumentException`, `NullReferenceException`
|
|||
|
|
- Action: Return 0.0 similarity, log warning
|
|||
|
|
- Continue processing
|
|||
|
|
|
|||
|
|
4. **Equipment Lookup Failures**
|
|||
|
|
- Catch: `InvalidOperationException`
|
|||
|
|
- Action: Log warning, skip equipment matching for that record
|
|||
|
|
- Continue with other records
|
|||
|
|
|
|||
|
|
### Logging Strategy
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
// Error level - Critical failures
|
|||
|
|
Log4Helper.Error(this.GetType(), "查询红外测温数据失败", ex);
|
|||
|
|
|
|||
|
|
// Warning level - Recoverable issues
|
|||
|
|
Log4Helper.Warn(this.GetType(), $"解析温度数据失败: {data.Result}", ex);
|
|||
|
|
|
|||
|
|
// Info level - Normal operations
|
|||
|
|
Log4Helper.Info(this.GetType(), $"查询到 {count} 条红外测温数据");
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Testing Strategy
|
|||
|
|
|
|||
|
|
### Unit Tests
|
|||
|
|
|
|||
|
|
Unit tests will verify specific examples and edge cases:
|
|||
|
|
|
|||
|
|
1. **IsInfraredCamera Tests**
|
|||
|
|
- Test camera name containing "热成像"
|
|||
|
|
- Test camera name ending with 'B'
|
|||
|
|
- Test camera name with both conditions
|
|||
|
|
- Test camera name with neither condition
|
|||
|
|
- Test null/empty camera names
|
|||
|
|
|
|||
|
|
2. **CalculateSimilarity Tests**
|
|||
|
|
- Test identical strings (should return 1.0)
|
|||
|
|
- Test completely different strings (should return close to 0.0)
|
|||
|
|
- Test strings with 85% similarity
|
|||
|
|
- Test null and empty string handling
|
|||
|
|
- Test case sensitivity
|
|||
|
|
|
|||
|
|
3. **ParseTemperatureFromInfraredResult Tests**
|
|||
|
|
- Test valid format: "2BL_C相连接点:-12.5℃"
|
|||
|
|
- Test multiple temperature points separated by commas
|
|||
|
|
- Test mixed valid and invalid segments
|
|||
|
|
- Test empty Result string
|
|||
|
|
- Test Result with no colons
|
|||
|
|
- Test negative temperatures
|
|||
|
|
- Test decimal temperatures
|
|||
|
|
|
|||
|
|
4. **MatchesEquipmentByName Tests**
|
|||
|
|
- Test exact name match
|
|||
|
|
- Test 85% similarity match
|
|||
|
|
- Test 84% similarity (should not match)
|
|||
|
|
- Test null equipment names
|
|||
|
|
- Test matching via EquipmentInfoName
|
|||
|
|
- Test matching via Name field
|
|||
|
|
|
|||
|
|
### Property-Based Tests
|
|||
|
|
|
|||
|
|
Property-based tests will verify universal properties across randomized inputs. Each test will run a minimum of 100 iterations.
|
|||
|
|
|
|||
|
|
1. **Property Test: Similarity Symmetry**
|
|||
|
|
- **Property 2: Similarity Calculation Symmetry**
|
|||
|
|
- **Validates: Requirements 2.4**
|
|||
|
|
- Generate random string pairs
|
|||
|
|
- Verify CalculateSimilarity(A, B) == CalculateSimilarity(B, A)
|
|||
|
|
|
|||
|
|
2. **Property Test: Similarity Bounds**
|
|||
|
|
- **Property 3: Similarity Score Bounds**
|
|||
|
|
- **Validates: Requirements 2.4**
|
|||
|
|
- Generate random string pairs
|
|||
|
|
- Verify 0.0 <= CalculateSimilarity(A, B) <= 1.0
|
|||
|
|
|
|||
|
|
3. **Property Test: Infrared Camera Identification**
|
|||
|
|
- **Property 1: Infrared Camera Identification Completeness**
|
|||
|
|
- **Validates: Requirements 1.1, 1.2, 1.3**
|
|||
|
|
- Generate camera names with "热成像" or ending with 'B'
|
|||
|
|
- Verify IsInfraredCamera returns true for all
|
|||
|
|
|
|||
|
|
4. **Property Test: Temperature Parsing Completeness**
|
|||
|
|
- **Property 5: Valid Temperature Data Parsing**
|
|||
|
|
- **Validates: Requirements 3.1, 3.2, 3.3, 3.5, 3.6**
|
|||
|
|
- Generate Result strings with valid "name:value" format
|
|||
|
|
- Verify at least one temperature point is extracted
|
|||
|
|
|
|||
|
|
5. **Property Test: Invalid Segment Handling**
|
|||
|
|
- **Property 6: Invalid Segment Skipping**
|
|||
|
|
- **Validates: Requirements 3.4, 3.7**
|
|||
|
|
- Generate Result strings with mix of valid and invalid segments
|
|||
|
|
- Verify invalid segments are skipped without errors
|
|||
|
|
|
|||
|
|
### Integration Tests
|
|||
|
|
|
|||
|
|
Integration tests will verify end-to-end functionality:
|
|||
|
|
|
|||
|
|
1. **Full Query Flow Test**
|
|||
|
|
- Insert test data into OriginalInspectionStoreResult
|
|||
|
|
- Call FindDatas with various filters
|
|||
|
|
- Verify correct results returned
|
|||
|
|
- Verify pagination works correctly
|
|||
|
|
|
|||
|
|
2. **Equipment Matching Integration Test**
|
|||
|
|
- Create equipment with specific name
|
|||
|
|
- Insert inspection data with similar names
|
|||
|
|
- Verify fuzzy matching works at 85% threshold
|
|||
|
|
|
|||
|
|
3. **Multi-Source Query Test**
|
|||
|
|
- Verify thermal imaging and infrared camera data can coexist
|
|||
|
|
- Verify both data sources are queried correctly
|
|||
|
|
|
|||
|
|
### Test Framework
|
|||
|
|
|
|||
|
|
- **Unit Testing**: xUnit or NUnit
|
|||
|
|
- **Property-Based Testing**: FsCheck (for C#)
|
|||
|
|
- **Mocking**: Moq for repository mocking
|
|||
|
|
- **Test Data**: Builder pattern for creating test entities
|
|||
|
|
|
|||
|
|
### Test Configuration
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
[Property(MaxTest = 100)]
|
|||
|
|
public Property SimilarityIsSymmetric()
|
|||
|
|
{
|
|||
|
|
return Prop.ForAll<string, string>((a, b) =>
|
|||
|
|
{
|
|||
|
|
var sim1 = CalculateSimilarity(a, b);
|
|||
|
|
var sim2 = CalculateSimilarity(b, a);
|
|||
|
|
return Math.Abs(sim1 - sim2) < 0.0001;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Implementation Notes
|
|||
|
|
|
|||
|
|
### Performance Considerations
|
|||
|
|
|
|||
|
|
1. **Levenshtein Distance Optimization**
|
|||
|
|
- Use iterative algorithm with O(n*m) complexity
|
|||
|
|
- Consider caching for repeated comparisons
|
|||
|
|
- Early exit if strings differ significantly in length
|
|||
|
|
|
|||
|
|
2. **MongoDB Query Optimization**
|
|||
|
|
- Add index on `CamName` field for faster filtering
|
|||
|
|
- Add index on `Time` field for time range queries
|
|||
|
|
- Use projection to retrieve only needed fields
|
|||
|
|
|
|||
|
|
3. **Batch Processing**
|
|||
|
|
- Process temperature parsing in parallel if result set is large
|
|||
|
|
- Consider streaming results for very large datasets
|
|||
|
|
|
|||
|
|
### Backward Compatibility
|
|||
|
|
|
|||
|
|
- Existing `FindMeasureTempertureResults` logic remains unchanged
|
|||
|
|
- New infrared camera logic is additive
|
|||
|
|
- Both thermal imaging and infrared data sources work independently
|
|||
|
|
- Shared output DTO ensures consistent API response
|
|||
|
|
|
|||
|
|
### Configuration
|
|||
|
|
|
|||
|
|
Consider adding configuration for:
|
|||
|
|
- Similarity threshold (default 0.85, configurable)
|
|||
|
|
- Infrared camera name patterns (extensible list)
|
|||
|
|
- Temperature parsing regex patterns
|
|||
|
|
- Logging verbosity levels
|