Files
WCTDataMiner/docs/data-model/entities/Ploss记录.md

244 lines
7.3 KiB
Markdown
Raw Normal View History

# ploss_record 实体
> 所属模块:[数据模型概览](../概览.md)
---
## 1. 表定义
**表名**`ploss_record`
**描述**:存储 Ploss FOD 格式解析数据,对应日志格式 `FOD-> (1)...(13)`
---
## 2. 字段定义
> **类型修正说明**:需求文档中 rx_power, tx_power, vcoil, vin, isns, pwm_duty 为 `uint16`0-65535但 SQLite 不支持无符号类型。实际数据如 vcoil=35377 超出了 SMALLINT-32768~32767范围因此这些字段使用 INT 类型存储。
| 列名 | 类型 | 约束 | 说明 |
|------|------|------|------|
| id | UUID | PK, NOT NULL | 主键 |
| scenario_id | UUID | FK, NOT NULL | 关联测试场景 |
| rx_type | TINYINT | NOT NULL | 接收端类型标识 |
| rx_power | INT | NOT NULL | 接收端功率mW原 uint16 |
| tx_power | INT | NOT NULL | 发射端功率mW原 uint16 |
| vcoil | INT | NOT NULL | 发射线圈电压,原 uint16 |
| vin | INT | NOT NULL | 输入电压,原 uint16 |
| isns | INT | NOT NULL | 输入电流采样值,原 uint16 |
| ploss | INT | NOT NULL | **核心值**:计算损耗(负数=安全) |
| threshold | INT | NOT NULL | **安全红线**:当前功率段阈值 |
| trigger_count | INT | NOT NULL, DEFAULT 0 | 触发计数器 |
| fod_result | INT | NOT NULL, DEFAULT 0 | FOD判定结果 |
| protocol_type | TINYINT | NOT NULL | 充电协议类型 |
| pwm_duty | INT | NOT NULL | PWM占空比原 uint16 |
| coil_index | TINYINT | NOT NULL | 充电线圈索引 |
| is_deleted | BOOLEAN | NOT NULL, DEFAULT FALSE | 软删除标记 |
| created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | 创建时间 |
---
## 3. 外键
| 外键 | 引用表 | 说明 |
|------|--------|------|
| scenario_id | test_scenario.id | 关联测试场景(必需) |
---
## 4. 派生字段
> **注意**:以下字段不落库,查询时动态计算
| 字段 | 计算公式 | 说明 |
|------|----------|------|
| margin | threshold - ploss | 安全余量(>0 安全,<0 危险) |
> **使用限制**`Margin` 属性通过 EF Core `Ignore()` 排除映射,仅用于内存计算。不可在数据库查询中直接使用(如 `WHERE Margin > 0`),需改用 `WHERE (threshold - ploss) > 0` 或先加载到内存再计算。
---
## 5. 索引
| 索引名 | 字段 | 用途 |
|--------|------|------|
| idx_ploss_scenario | scenario_id | 按测试场景查询 |
| idx_ploss_rx_power | rx_power | 阈值表匹配 |
| idx_ploss_ploss | ploss | 损耗值查询 |
| idx_ploss_threshold | threshold | 阈值查询 |
| idx_ploss_fod_result | fod_result | FOD结果筛选 |
---
## 6. EF Core 模型
### 实体类
```csharp
// Models/PlossRecord.cs
namespace WCTDataMiner.Models;
public class PlossRecord
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid ScenarioId { get; set; }
public byte RxType { get; set; }
public short RxPower { get; set; }
public short TxPower { get; set; }
public short Vcoil { get; set; }
public short Vin { get; set; }
public short Isns { get; set; }
/// <summary>核心判定值:负数表示安全</summary>
public int Ploss { get; set; }
/// <summary>安全红线:当前功率段阈值</summary>
public int Threshold { get; set; }
public short TriggerCount { get; set; } = 0;
public short FodResult { get; set; } = 0;
public byte ProtocolType { get; set; }
public short PwmDuty { get; set; }
public byte CoilIndex { get; set; }
public bool IsDeleted { get; set; } = false;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
// Navigation Properties
public TestScenario Scenario { get; set; } = null!;
/// <summary>派生属性:安全余量(不落库)</summary>
public int Margin => Threshold - Ploss;
}
```
### 配置类
```csharp
// Data/Configurations/PlossRecordConfiguration.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using WCTDataMiner.Models;
namespace WCTDataMiner.Data.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");
builder.Property(e => e.RxType)
.IsRequired()
.HasColumnName("rx_type");
builder.Property(e => e.RxPower)
.IsRequired()
.HasColumnName("rx_power");
builder.Property(e => e.TxPower)
.IsRequired()
.HasColumnName("tx_power");
builder.Property(e => e.Vcoil)
.IsRequired()
.HasColumnName("vcoil");
builder.Property(e => e.Vin)
.IsRequired()
.HasColumnName("vin");
builder.Property(e => e.Isns)
.IsRequired()
.HasColumnName("isns");
builder.Property(e => e.Ploss)
.IsRequired()
.HasColumnName("ploss");
builder.Property(e => e.Threshold)
.IsRequired()
.HasColumnName("threshold");
builder.Property(e => e.TriggerCount)
.IsRequired()
.HasDefaultValue((short)0)
.HasColumnName("trigger_count");
builder.Property(e => e.FodResult)
.IsRequired()
.HasDefaultValue((short)0)
.HasColumnName("fod_result");
builder.Property(e => e.ProtocolType)
.IsRequired()
.HasColumnName("protocol_type");
builder.Property(e => e.PwmDuty)
.IsRequired()
.HasColumnName("pwm_duty");
builder.Property(e => e.CoilIndex)
.IsRequired()
.HasColumnName("coil_index");
builder.Property(e => e.IsDeleted)
.IsRequired()
.HasDefaultValue(false)
.HasColumnName("is_deleted");
builder.Property(e => e.CreatedAt)
.IsRequired()
.HasDefaultValueSql("NOW()")
.HasColumnName("created_at");
// 派生属性不落库
builder.Ignore(e => e.Margin);
// 索引
builder.HasIndex(e => e.ScenarioId).HasDatabaseName("idx_ploss_scenario");
builder.HasIndex(e => e.RxPower).HasDatabaseName("idx_ploss_rx_power");
builder.HasIndex(e => e.Ploss).HasDatabaseName("idx_ploss_ploss");
builder.HasIndex(e => e.Threshold).HasDatabaseName("idx_ploss_threshold");
builder.HasIndex(e => e.FodResult).HasDatabaseName("idx_ploss_fod_result");
// 关系配置
builder.HasOne(e => e.Scenario)
.WithMany(e => e.PlossRecords)
.HasForeignKey(e => e.ScenarioId)
.IsRequired();
}
}
```
---
## 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 | 高功率 |
```csharp
// Services/ThresholdCalculator.cs
public static int GetThresholdByPower(int rxPower)
{
if (rxPower <= 5000) return 350;
if (rxPower <= 10000) return 500;
if (rxPower <= 15000) return 750;
if (rxPower <= 30000) return 1000;
return 1250;
}
```