# 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 FindDatas( PageSearchCondition searchCondition) ``` ### New Helper Methods #### 1. IsInfraredCamera ```csharp /// /// Determines if a camera name indicates an infrared camera /// /// Camera name from OriginalInspectionStoreResult /// True if camera is infrared type 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 /// /// Calculates string similarity using Levenshtein distance algorithm /// /// Source string /// Target string /// Similarity score between 0.0 and 1.0 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 /// /// Parses temperature data from infrared camera result string /// /// Original inspection store result /// Associated equipment (may be null) /// List of temperature measurement outputs private List 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 /// /// Checks if inspection data matches equipment using fuzzy name matching /// /// Original inspection store result /// Equipment to match against /// Similarity threshold (default 0.85) /// True if names match with sufficient similarity 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((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