feat: 实现 FOD 日志数据采集 CLI 应用
This commit is contained in:
@@ -14,22 +14,24 @@
|
||||
|
||||
## 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 | SMALLINT | NOT NULL | 接收端功率(mW) |
|
||||
| tx_power | SMALLINT | NOT NULL | 发射端功率(mW) |
|
||||
| vcoil | SMALLINT | NOT NULL | 发射线圈电压 |
|
||||
| vin | SMALLINT | NOT NULL | 输入电压 |
|
||||
| isns | SMALLINT | 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 | SMALLINT | NOT NULL, DEFAULT 0 | 触发计数器 |
|
||||
| fod_result | SMALLINT | NOT NULL, DEFAULT 0 | FOD判定结果 |
|
||||
| trigger_count | INT | NOT NULL, DEFAULT 0 | 触发计数器 |
|
||||
| fod_result | INT | NOT NULL, DEFAULT 0 | FOD判定结果 |
|
||||
| protocol_type | TINYINT | NOT NULL | 充电协议类型 |
|
||||
| pwm_duty | SMALLINT | NOT NULL | PWM占空比 |
|
||||
| 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() | 创建时间 |
|
||||
@@ -52,6 +54,8 @@
|
||||
|------|----------|------|
|
||||
| margin | threshold - ploss | 安全余量(>0 安全,<0 危险) |
|
||||
|
||||
> **使用限制**:`Margin` 属性通过 EF Core `Ignore()` 排除映射,仅用于内存计算。不可在数据库查询中直接使用(如 `WHERE Margin > 0`),需改用 `WHERE (threshold - ploss) > 0` 或先加载到内存再计算。
|
||||
|
||||
---
|
||||
|
||||
## 5. 索引
|
||||
@@ -68,100 +72,151 @@
|
||||
|
||||
## 6. EF Core 模型
|
||||
|
||||
### 实体类
|
||||
|
||||
```csharp
|
||||
// Models/PlossRecord.cs
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace WCTDataMiner.Models;
|
||||
|
||||
[Table("ploss_record")]
|
||||
[Index(nameof(ScenarioId), Name = "idx_ploss_scenario")]
|
||||
[Index(nameof(RxPower), Name = "idx_ploss_rx_power")]
|
||||
[Index(nameof(Ploss), Name = "idx_ploss_ploss")]
|
||||
[Index(nameof(Threshold), Name = "idx_ploss_threshold")]
|
||||
[Index(nameof(FodResult), Name = "idx_ploss_fod_result")]
|
||||
public class PlossRecord
|
||||
{
|
||||
[Key]
|
||||
[Column("id")]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
[Required]
|
||||
[Column("scenario_id")]
|
||||
public Guid ScenarioId { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("rx_type")]
|
||||
public byte RxType { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("rx_power")]
|
||||
public short RxPower { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("tx_power")]
|
||||
public short TxPower { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("vcoil")]
|
||||
public short Vcoil { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("vin")]
|
||||
public short Vin { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("isns")]
|
||||
public short Isns { get; set; }
|
||||
|
||||
/// <summary>核心判定值:负数表示安全</summary>
|
||||
[Required]
|
||||
[Column("ploss")]
|
||||
public int Ploss { get; set; }
|
||||
|
||||
/// <summary>安全红线:当前功率段阈值</summary>
|
||||
[Required]
|
||||
[Column("threshold")]
|
||||
public int Threshold { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("trigger_count")]
|
||||
public short TriggerCount { get; set; } = 0;
|
||||
|
||||
[Required]
|
||||
[Column("fod_result")]
|
||||
public short FodResult { get; set; } = 0;
|
||||
|
||||
[Required]
|
||||
[Column("protocol_type")]
|
||||
public byte ProtocolType { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("pwm_duty")]
|
||||
public short PwmDuty { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("coil_index")]
|
||||
public byte CoilIndex { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("is_deleted")]
|
||||
public bool IsDeleted { get; set; } = false;
|
||||
|
||||
[Required]
|
||||
[Column("created_at")]
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
[ForeignKey(nameof(ScenarioId))]
|
||||
// Navigation Properties
|
||||
public TestScenario Scenario { get; set; } = null!;
|
||||
|
||||
/// <summary>派生属性:安全余量</summary>
|
||||
[NotMapped]
|
||||
/// <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. 动态阈值表
|
||||
|
||||
Reference in New Issue
Block a user