Files
WCTDataMiner/docs/data-model/entities/Ploss记录.md
2026-08-14 15:35:48 +08:00

8.7 KiB
Raw Blame History

ploss_record 实体

所属模块:数据模型概览


1. 表定义

表名ploss_record

描述:存储 Ploss FOD 格式解析数据,对应两行日志格式:

pow_loss = X, delta_p = Y
FOD-> (1) (2) ... (16)

2. 字段定义

列名 类型 约束 说明
id UUID PK, NOT NULL 主键
scenario_id UUID FK, NOT NULL 关联测试场景
pow_loss INT NULL 第一行:功率损耗值
delta_p INT NULL 第一行:功率差值
field_1 INT NOT NULL Field1语义待定义
field_2 INT NOT NULL Field2语义待定义
field_3 INT NOT NULL Field3语义待定义
field_4 INT NOT NULL Field4: RX power - 接收端功率
field_5 INT NOT NULL Field5: TX power - 发射端功率
field_6 INT NOT NULL Field6语义待定义
field_7 INT NOT NULL Field7语义待定义
field_8 INT NOT NULL Field8语义待定义
field_9 INT NOT NULL, DEFAULT 0 Field9: ploss - 功率损耗计算值
field_10 INT NOT NULL, DEFAULT 0 Field10: threshold - 阈值
field_11 INT NOT NULL Field11: 触发次数 - 当 Field9 > Field10 时计数超过5次触发FOD保护
field_12 INT NOT NULL Field12: PFOD result 标志 - 触发时置位
field_13 INT NOT NULL, DEFAULT 0 Field13语义待定义
field_14 INT NOT NULL, DEFAULT 0 Field14语义待定义
field_15 INT NOT NULL, DEFAULT 0 Field15语义待定义
field_16 INT NOT NULL, DEFAULT 0 Field16语义待定义
is_deleted BOOLEAN NOT NULL, DEFAULT FALSE 软删除标记
created_at TIMESTAMP NOT NULL, DEFAULT NOW() 创建时间

字段语义PlossRecord 实体注释为准。


3. 外键

外键 引用表 说明
scenario_id test_scenario.id 关联测试场景(必需)

4. 派生字段

注意:以下字段不落库,查询时动态计算

字段 计算公式 说明
margin field_10 - field_9 安全余量(>0 安全,<0 危险)

使用限制Margin 属性通过 EF Core Ignore() 排除映射,仅用于内存计算。不可在数据库查询中直接使用(如 WHERE Margin > 0),需改用 WHERE (field_10 - field_9) > 0 或先加载到内存再计算。


5. 索引

索引名 字段 用途
idx_ploss_scenario scenario_id 按测试场景查询
idx_ploss_field_2 field_2 字段查询
idx_ploss_field_7 field_7 字段查询
idx_ploss_field_8 field_8 字段查询
idx_ploss_field_10 field_10 字段查询
idx_ploss_pow_loss pow_loss 第一行损耗值查询
idx_ploss_delta_p delta_p 第一行功率差值查询

6. EF Core 模型

实体类

// Domain/Local/PlossRecord.cs
namespace Gpulse.WCT.DataAnalyzer.Core.Domain.Local;

public class PlossRecord
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public Guid ScenarioId { get; set; }

    // ===== 第一行字段nullable兼容旧数据 =====
    /// <summary>功率损耗值(来自第一行)</summary>
    public int? PowLoss { get; set; }

    /// <summary>功率差值(来自第一行)</summary>
    public int? DeltaP { get; set; }

    // ===== 第二行字段16个通用字段均支持负数 =====
    public int Field1 { get; set; }
    public int Field2 { get; set; }
    public int Field3 { get; set; }

    /// <summary>Field4: RX power - 接收端功率</summary>
    public int Field4 { get; set; }

    /// <summary>Field5: TX power - 发射端功率</summary>
    public int Field5 { get; set; }

    public int Field6 { get; set; }
    public int Field7 { get; set; }
    public int Field8 { get; set; }

    /// <summary>Field9: ploss - 功率损耗计算值</summary>
    public int Field9 { get; set; }

    /// <summary>Field10: threshold - 阈值</summary>
    public int Field10 { get; set; }

    /// <summary>Field11: 触发次数 - 当 Field9 > Field10ploss 大于阈值时计数超过5次触发FOD保护</summary>
    public int Field11 { get; set; }

    /// <summary>Field12: PFOD result 标志 - 触发时置位</summary>
    public int Field12 { get; set; }

    public int Field13 { get; set; }
    public int Field14 { get; set; }
    public int Field15 { get; set; }
    public int Field16 { get; set; }

    public bool IsDeleted { get; set; } = false;
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;

    // Navigation Properties
    public TestScenario Scenario { get; set; } = null!;

    /// <summary>派生属性:安全余量(不落库) = Field10 - Field9</summary>
    public int Margin => Field10 - Field9;
}

配置类

// Infrastructure/LocalData/Configurations/PlossRecordConfiguration.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Gpulse.WCT.DataAnalyzer.Core.Domain.Local;

namespace Gpulse.WCT.DataAnalyzer.Core.Infrastructure.LocalData.Configurations;

public class PlossRecordConfiguration : IEntityTypeConfiguration<PlossRecord>
{
    public void Configure(EntityTypeBuilder<PlossRecord> builder)
    {
        builder.ToTable("ploss_record");

        builder.HasKey(e => e.Id);
        builder.Property(e => e.Id).HasColumnName("id");

        builder.Property(e => e.ScenarioId)
            .IsRequired()
            .HasColumnName("scenario_id");

        // ===== 第一行字段nullable =====
        builder.Property(e => e.PowLoss).IsRequired(false).HasColumnName("pow_loss");
        builder.Property(e => e.DeltaP).IsRequired(false).HasColumnName("delta_p");

        // ===== 第二行字段(通用命名) =====
        builder.Property(e => e.Field1).IsRequired().HasColumnName("field_1");
        builder.Property(e => e.Field2).IsRequired().HasColumnName("field_2");
        builder.Property(e => e.Field3).IsRequired().HasColumnName("field_3");
        builder.Property(e => e.Field4).IsRequired().HasColumnName("field_4");
        builder.Property(e => e.Field5).IsRequired().HasColumnName("field_5");
        builder.Property(e => e.Field6).IsRequired().HasColumnName("field_6");
        builder.Property(e => e.Field7).IsRequired().HasColumnName("field_7");
        builder.Property(e => e.Field8).IsRequired().HasColumnName("field_8");
        builder.Property(e => e.Field9).IsRequired().HasDefaultValue(0).HasColumnName("field_9");
        builder.Property(e => e.Field10).IsRequired().HasDefaultValue(0).HasColumnName("field_10");
        builder.Property(e => e.Field11).IsRequired().HasColumnName("field_11");
        builder.Property(e => e.Field12).IsRequired().HasColumnName("field_12");
        builder.Property(e => e.Field13).IsRequired().HasDefaultValue(0).HasColumnName("field_13");
        builder.Property(e => e.Field14).IsRequired().HasDefaultValue(0).HasColumnName("field_14");
        builder.Property(e => e.Field15).IsRequired().HasDefaultValue(0).HasColumnName("field_15");
        builder.Property(e => e.Field16).IsRequired().HasDefaultValue(0).HasColumnName("field_16");

        builder.Property(e => e.IsDeleted)
            .IsRequired()
            .HasDefaultValue(false)
            .HasColumnName("is_deleted");

        builder.Property(e => e.CreatedAt)
            .IsRequired()
            .HasDefaultValueSql("datetime('now')")
            .HasColumnName("created_at");

        // 派生属性不落库
        builder.Ignore(e => e.Margin);

        // 索引
        builder.HasIndex(e => e.ScenarioId).HasDatabaseName("idx_ploss_scenario");
        builder.HasIndex(e => e.Field2).HasDatabaseName("idx_ploss_field_2");
        builder.HasIndex(e => e.Field7).HasDatabaseName("idx_ploss_field_7");
        builder.HasIndex(e => e.Field8).HasDatabaseName("idx_ploss_field_8");
        builder.HasIndex(e => e.Field10).HasDatabaseName("idx_ploss_field_10");
        builder.HasIndex(e => e.PowLoss).HasDatabaseName("idx_ploss_pow_loss");
        builder.HasIndex(e => e.DeltaP).HasDatabaseName("idx_ploss_delta_p");

        // 关系配置
        builder.HasOne(e => e.Scenario)
            .WithMany(e => e.PlossRecords)
            .HasForeignKey(e => e.ScenarioId)
            .OnDelete(DeleteBehavior.Cascade);

        // 全局查询过滤器
        builder.HasQueryFilter(e => !e.IsDeleted);
    }
}

7. 动态阈值表

阈值根据 RxPower 动态查表(不落库,业务规则)

Rx Power 区间 Threshold 备注
0-5000 mW 350 mW 低功率最敏感
5000-10000 mW 500 mW
10000-15000 mW 750 mW
15000-30000 mW 1000 mW
30000-50000 mW 1250 mW 高功率