15 KiB
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:
OriginalInspectionStoreResultcollection - Contains infrared camera inspection data - Shared Output:
MeasureTemperatureResultOutput- Common DTO for all temperature results
Components and Interfaces
Modified Method Signature
[HttpPost, Description("查询温度测量结果")]
[Abp.Domain.Uow.UnitOfWork(true)]
[AbpAllowAnonymous]
[ShowApi]
public RequestPageResult<MeasureTemperatureResultOutput> FindDatas(
PageSearchCondition<MeasureTemperatureResultSearchConditonInput> searchCondition)
New Helper Methods
1. IsInfraredCamera
/// <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
trueifcamNamecontains "热成像" - Returns
trueifcamNameends with 'B' - Returns
falseotherwise - Handles null/empty strings safely
2. CalculateSimilarity (Enhanced)
/// <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
/// <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
Resultfield 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
MeasureTemperatureResultOutputwith parsed data
- Check if contains
- Handle missing/invalid data gracefully
- Log parsing failures with original Result string
4. MatchesEquipmentByName
/// <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.EquipmentInfoNameagainstequipment.Name - Check
data.Nameagainstequipment.Name - Return
trueif either similarity >= threshold - Return
falseif both similarities < threshold
Data Models
Input: MeasureTemperatureResultSearchConditonInput
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
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
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
-
MongoDB Query Failures
- Catch:
MongoException,TimeoutException - Action: Log error with query details, return error response
- User Message: "数据库查询失败,请稍后重试"
- Catch:
-
Temperature Parsing Failures
- Catch:
FormatException,RegexMatchTimeoutException - Action: Log warning with Result string, skip record, continue
- No user-facing error (graceful degradation)
- Catch:
-
Similarity Calculation Errors
- Catch:
ArgumentException,NullReferenceException - Action: Return 0.0 similarity, log warning
- Continue processing
- Catch:
-
Equipment Lookup Failures
- Catch:
InvalidOperationException - Action: Log warning, skip equipment matching for that record
- Continue with other records
- Catch:
Logging Strategy
// 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:
-
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
-
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
-
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
-
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.
-
Property Test: Similarity Symmetry
- Property 2: Similarity Calculation Symmetry
- Validates: Requirements 2.4
- Generate random string pairs
- Verify CalculateSimilarity(A, B) == CalculateSimilarity(B, A)
-
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
-
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
-
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
-
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:
-
Full Query Flow Test
- Insert test data into OriginalInspectionStoreResult
- Call FindDatas with various filters
- Verify correct results returned
- Verify pagination works correctly
-
Equipment Matching Integration Test
- Create equipment with specific name
- Insert inspection data with similar names
- Verify fuzzy matching works at 85% threshold
-
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
[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
-
Levenshtein Distance Optimization
- Use iterative algorithm with O(n*m) complexity
- Consider caching for repeated comparisons
- Early exit if strings differ significantly in length
-
MongoDB Query Optimization
- Add index on
CamNamefield for faster filtering - Add index on
Timefield for time range queries - Use projection to retrieve only needed fields
- Add index on
-
Batch Processing
- Process temperature parsing in parallel if result set is large
- Consider streaming results for very large datasets
Backward Compatibility
- Existing
FindMeasureTempertureResultslogic 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