2026-01-06 22:59:58 +08:00

15 KiB
Raw Blame History

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

[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 true if camName contains "热成像"
  • Returns true if camName ends with 'B'
  • Returns false otherwise
  • 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 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

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

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

  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

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

[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