# C# 工业开发知识体系与 .NET 8 指南

> 定位：面向上位机、设备集成、数据采集、HMI、MES 边缘服务和工业运维平台的技术参考。
>
> 资料核对日期：2026-10-01
>
> 核心结论：C# 适合做工业软件的集成、编排、界面、数据和服务层；硬实时控制、运动闭环和安全联锁应交给 PLC、运动控制器或安全控制器。

## 1. 工业开发先建立正确边界

### 1.1 C# 能做什么

- 设备通信：PLC、仪器仪表、机器人、视觉、变频器、扫码器、称重模块。
- 数据采集：周期采集、事件采集、批次采集、历史归档、质量标记。
- HMI/上位机：状态监控、手动操作、报警确认、配方管理、权限管理、报表。
- 工艺编排：工序状态机、设备握手、任务队列、批次追踪、异常恢复。
- 数据服务：Web API、OPC UA 网关、MQTT 边缘发布、MES/ERP/WMS 对接。
- 视觉与 AI 集成：相机 SDK、图像预处理、模型推理、结果回写 PLC。
- 运维平台：日志、审计、远程诊断、配置管理、版本管理、健康检查。

### 1.2 C# 不应直接承担什么

- 微秒级或严格确定性的运动控制闭环。
- 安全急停、安全门、双手按钮等功能安全逻辑。
- 断电后必须可靠保持的保护动作。
- 依赖 Windows 调度精度的硬实时控制。
- 未经验证就直接写入危险设备的关键输出。

建议架构：

```text
传感器/执行器
    -> PLC/运动控制器/安全控制器
    -> 工业网络与协议
    -> C# 采集与设备抽象层
    -> 工艺状态机/报警/配方/任务层
    -> HMI、数据库、MES、Web API、报表
```

## 2. 硬件知识地图

### 2.1 传感器

常见类型：

- 数字量：接近、光电、限位、门磁、按钮、继电器反馈。
- 模拟量：0-10 V、4-20 mA、热电偶、热电阻、压力、流量、液位。
- 编码器：增量式、绝对值、多圈编码器。
- 视觉：工业相机、镜头、光源、触发器、采集卡。
- 识别：条码、二维码、RFID、OCR。
- 工艺传感器：温度、压力、流量、振动、电流、扭矩、位移。

注意：模拟量不是“拿到一个数字就能用”。必须确认量程、单位、线性换算、采样周期、滤波、断线诊断和质量位。

常见换算：

```text
engineeringValue = rawValue / rawFullScale * engineeringFullScale
```

4-20 mA 传感器通常要处理 4 mA 的零点，不应简单按 0-20 mA 换算。

### 2.2 PLC 与控制器

PLC 重点关注：

- 扫描周期和任务优先级。
- 输入刷新、输出刷新和通信区更新时机。
- 保持性变量、掉电保持和冷启动行为。
- 程序状态、故障状态、通信状态。
- 变量地址、数据块结构、字节序和类型映射。
- 固件版本、工程版本和设备型号兼容性。

C# 对 PLC 的合理职责是读取状态、下发经过授权的命令、管理任务和记录结果，不要把 PLC 当作普通数据库随意轮询或写值。

### 2.3 变频器、伺服和运动控制

关键概念：

- 使能、准备、运行、故障、急停和复位状态。
- 目标速度、实际速度、目标位置、实际位置。
- 加减速时间、限位、回零、软限位、误差窗口。
- 运动模式：点位、速度、转矩、同步、电子齿轮。
- 安全扭矩关闭等功能安全信号。

工业软件通常通过 PLC 或运动控制 API 间接控制，不建议由桌面程序直接实现运动闭环。

### 2.4 工业相机与视觉

典型流程：

1. 相机枚举与连接。
2. 设置曝光、增益、触发模式和采集格式。
3. 软触发或硬触发采图。
4. 图像缓冲区转为算法输入。
5. 执行定位、测量、缺陷检测或 OCR。
6. 输出结果、置信度、耗时和原图索引。
7. 将 OK/NG、坐标或缺陷码回写控制系统。

注意：相机 SDK 通常包含非托管资源，必须处理释放、回调线程、缓冲区生命周期和设备断开重连。

### 2.5 工业计算机与网络

工业 PC 重点：

- CPU 核数、内存、SSD 寿命、风扇和温度。
- 网口数量、网卡芯片、串口数量、隔离与防护。
- Windows IoT/Windows Pro/Linux 的驱动和供应商支持。
- UPS、看门狗、自动开机、断电恢复。
- BIOS 启动策略、磁盘镜像和远程维护。

网络重点：

- 控制网、设备网、管理网和办公网分区。
- 固定 IP、交换机端口、VLAN、防火墙和时间同步。
- 不要让设备控制端口直接暴露到公网。
- 不要假设“能 Ping 通”就表示协议可用。

## 3. 工业通信协议

### 3.1 协议选型维度

选协议时至少问清楚：

- 是否需要确定性和实时性？
- 是读状态，还是需要写控制命令？
- 是否需要语义模型、设备发现和安全？
- 是否跨品牌、跨平台、跨语言？
- 数据量、采样周期、设备数量和网络拓扑如何？
- 设备是否已有成熟 SDK 或驱动？
- 故障时能否诊断、重连和恢复？
- 谁负责协议主站/客户端，谁负责从站/服务端？

### 3.2 Modbus RTU/TCP

特点：简单、普及、易调试，但语义弱，很多数据需要查设备手册。

- Modbus RTU：通常基于 RS-485，半双工，需关注站号、波特率、校验、终端电阻。
- Modbus TCP：基于 TCP，默认端口通常为 502，需关注 Unit ID、寄存器地址和连接数。
- 常见数据：线圈、离散输入、保持寄存器、输入寄存器。
- 常见坑：地址从 0 开始还是从 1 开始；40001 是否代表偏移 0；16 位寄存器拼 32 位值的顺序；浮点数和字节序。

建议封装：

```csharp
public interface IModbusDevice
{
    Task<ushort[]> ReadHoldingRegistersAsync(
        ushort address,
        ushort count,
        CancellationToken cancellationToken);
}
```

不要让业务层直接传裸地址。使用变量映射表：

```text
Temperature -> HoldingRegister 100 -> Int16 -> scale 0.1 -> °C
```

### 3.3 OPC UA

OPC UA 不只是一个传输协议，还提供地址空间、类型、语义、服务和安全模型，适合设备到 SCADA/MES/边缘平台的数据互操作。

核心概念：

- Client/Server：客户端浏览、读取、写入、订阅服务器节点。
- PubSub：发布者将数据发布给订阅者，适合更大规模的数据分发。
- NodeId、BrowseName、DataType、Object、Variable、Method。
- Endpoint、ApplicationUri、证书、Trust List、Security Policy。
- Subscription、MonitoredItem、采样周期、发布周期、队列和丢弃策略。

注意：

- 不要只按 NodeId 硬编码而不验证命名空间和设备型号。
- 证书信任、时钟同步和安全策略必须纳入部署流程。
- 订阅回调不应直接修改 UI 或执行耗时业务。
- 监控项数量、采样周期、队列大小要根据服务器能力压测。
- 写入前应做权限、范围、设备状态和操作确认。

### 3.4 MQTT

MQTT 适合边缘到平台的轻量消息传递，不等于实时控制协议。

核心概念：

- Broker、Publisher、Subscriber、Topic。
- QoS 0/1/2。
- Retained Message、Last Will、Keep Alive。
- Client ID、用户名密码、TLS、证书。
- Topic 命名、版本、设备标识和消息 schema。

建议消息内容包含：

```json
{
  "deviceId": "line-01-plc-01",
  "timestamp": "2026-10-01T12:00:00Z",
  "sequence": 12345,
  "quality": "Good",
  "values": {
    "temperature": 36.5,
    "running": true
  }
}
```

常见坑：QoS 1 可能重复投递；订阅重连后是否补数据；时间戳来自设备还是服务器；消息版本升级是否兼容；保留消息可能把旧状态误认为当前状态。

### 3.5 RS-232/RS-485 与串口协议

串口本身只定义电气和传输基础，不定义业务消息。实际项目通常是“串口 + 厂商协议”。

必须确认：

- COM 口、波特率、数据位、停止位、校验位、流控。
- 帧头、长度、命令码、地址、数据区、校验和、帧尾。
- 读取超时、帧间隔、半双工切换、最大帧长。
- 设备是否主动上报，是否需要轮询。

不要把一次 `ReadAsync` 当作一次完整报文。TCP 和串口都可能出现拆包、粘包或半帧。

### 3.6 EtherNet/IP、PROFINET、EtherCAT

- EtherNet/IP：常见于 Rockwell 生态，CIP 对象模型明显，设备和控制器能力依赖供应商。
- PROFINET：常见于 Siemens 生态，强调工业以太网和实时通信，很多配置依赖工程工具和设备描述文件。
- EtherCAT：适合运动控制和高性能 I/O，通常由专用主站栈、控制器或供应商 SDK 支持。

在 C# 中不要根据协议名称直接假设可以用通用 TCP 代码完成。优先使用设备厂商提供的官方 SDK、驱动或经过验证的主站组件。

### 3.7 HTTP、WebSocket、gRPC

适合：

- HTTP REST：MES、ERP、WMS、设备管理和配置接口。
- WebSocket：HMI 实时状态推送、报警推送和操作反馈。
- gRPC：边缘服务之间的高效内部调用。

不适合直接替代 PLC 的硬实时控制链路。

## 4. 典型应用场景

### 4.1 单机上位机

组成：设备通信、状态机、HMI、配方、报警、数据记录、权限。

推荐：WPF + MVVM + Generic Host + 设备抽象层 + SQLite/SQL Server。

### 4.2 产线监控与 SCADA 辅助系统

重点：多设备连接、统一标签模型、报警管理、历史趋势、权限、审计和高可用。

推荐：OPC UA/厂商驱动 + 边缘采集服务 + Web API + Web HMI 或 WPF HMI。

### 4.3 数据采集网关

重点：连接管理、采集调度、数据质量、缓存、断网续传、消息发布和配置热更新。

推荐分层：

```text
Device Adapter -> Normalized Tag Model -> Buffer/Store -> MQTT/HTTP/OPC UA
```

### 4.4 MES 工位程序

重点：工单、条码、物料、工艺参数、设备握手、质量结果、过站和追溯。

核心原则：先定义业务状态和设备握手协议，再写界面。

### 4.5 视觉检测工作站

重点：触发时序、图像缓存、算法超时、结果一致性、原图追溯和 NG 复判。

### 4.6 远程运维平台

重点：身份、授权、审计、版本、灰度升级、日志收集和远程诊断。危险操作必须有二次确认、权限和操作记录。

## 5. 推荐的软件架构

### 5.1 分层结构

```text
IndustrialApp
├── Presentation        WPF/WinForms/Web HMI
├── Application         用例、命令、查询、状态机
├── Domain              设备状态、工艺模型、报警、配方
├── Infrastructure      OPC UA、Modbus、串口、数据库、MQTT
├── Contracts            DTO、命令、事件、版本化消息
└── Host                 配置、DI、日志、健康检查、生命周期
```

### 5.2 设备抽象

业务层只依赖能力接口，不依赖具体厂商：

```csharp
public interface IDevice
{
    string DeviceId { get; }
    DeviceStatus Status { get; }
    Task ConnectAsync(CancellationToken cancellationToken);
    Task DisconnectAsync(CancellationToken cancellationToken);
}

public interface ITemperatureReader
{
    Task<Measurement<double>> ReadTemperatureAsync(
        CancellationToken cancellationToken);
}

public sealed record Measurement<T>(
    T Value,
    DateTimeOffset Timestamp,
    Quality Quality,
    string? Unit = null);

public enum Quality
{
    Good,
    Bad,
    Uncertain,
    Stale
}
```

这样可以用模拟设备做测试，也可以替换 Modbus、OPC UA 或厂商 SDK 实现。

### 5.3 状态机优先于布尔变量堆积

不建议：

```csharp
if (isReady && !isBusy && !hasAlarm && !isManual && ...)
{
}
```

建议明确状态和事件：

```text
Idle -> Preparing -> Ready -> Running -> Completed
                    |                 |
                    v                 v
                 Fault <----------- Aborted
```

状态转换必须记录：原状态、事件、目标状态、原因、操作者、时间和设备快照。

### 5.4 采集调度

每个设备应有独立的生命周期和取消令牌。不要在 UI 定时器里直接执行通信：

```csharp
public sealed class PollingWorker(
    IDeviceGateway gateway,
    ILogger<PollingWorker> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(500));

        while (await timer.WaitForNextTickAsync(stoppingToken))
        {
            try
            {
                await gateway.PollAsync(stoppingToken);
            }
            catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
            {
                break;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "设备采集周期失败");
            }
        }
    }
}
```

注意：如果一次采集可能超过周期，必须防止任务重入；可以使用单线程队列、信号量或设备级锁。

## 6. 常用 C#/.NET 库

以下按用途分类，实际选型应以设备厂商兼容性和项目许可为准。

### 6.1 基础通信

- `System.IO.Ports`：串口基础能力。
- `System.Net.Sockets`：TCP/UDP 原始通信。
- `HttpClient`：HTTP/REST。
- `Grpc.Net.Client`：gRPC 客户端。
- `MQTTnet`：MQTT 客户端和服务端能力。
- `FluentModbus`、`NModbus`：Modbus 生态中常见的 .NET 方案，使用前检查版本和许可证。
- `OPCFoundation.NetStandard.Opc.Ua`：OPC UA .NET 标准栈生态。
- 厂商 SDK：优先级通常高于通用库，尤其是运动控制、视觉和专有总线。

### 6.2 UI

- WPF：Windows 工业上位机首选之一，适合 MVVM、数据绑定和复杂界面。
- WinForms：成熟、简单、适合已有系统和快速工具，但复杂界面维护成本会上升。
- Avalonia：跨平台桌面 UI 选择，需验证工业 SDK、驱动和现场环境兼容性。
- ASP.NET Core + Blazor/前端框架：适合 Web HMI、边缘管理和多终端访问。

### 6.3 数据与缓存

- `Microsoft.Data.Sqlite`：单机轻量数据库。
- `Microsoft.Data.SqlClient`：SQL Server。
- `Npgsql`：PostgreSQL。
- `Dapper`：轻量 SQL 映射。
- `Microsoft.EntityFrameworkCore`：领域模型和数据库映射。
- `InfluxDB.Client`、TimescaleDB 客户端：时序数据场景。
- Redis 客户端：分布式缓存、状态和队列辅助，不应替代可靠历史存储。

### 6.4 配置、日志与诊断

- `Microsoft.Extensions.Hosting`：Generic Host、依赖注入、配置、日志和生命周期。
- `Microsoft.Extensions.Options`：强类型配置。
- Serilog：结构化日志生态。
- OpenTelemetry：日志、指标、链路追踪。
- `HealthChecks`：服务和设备健康状态。
- `Polly`/`Microsoft.Extensions.Resilience`：重试、超时、熔断、限流等韧性策略。

### 6.5 图像与视觉

- OpenCvSharp：OpenCV 的 .NET 封装。
- Emgu CV：OpenCV 的另一种 .NET 封装。
- SkiaSharp：跨平台 2D 图像处理。
- ImageSharp：托管代码图像处理，注意许可证和性能需求。
- 厂商相机 SDK：海康、大恒、Basler、FLIR 等设备通常优先使用官方 SDK。

## 7. 工业项目主流开发流程

### 阶段 1：需求和边界

输出：设备清单、工艺流程、I/O 表、通信矩阵、报警表、权限表、数据字典、验收指标。

必须明确：

- 哪些信号只读，哪些信号可写。
- 哪些动作需要人工确认。
- 设备离线时系统行为。
- 急停和安全逻辑由谁负责。
- 数据保存多久，追溯粒度是什么。

### 阶段 2：通信验证

先用最小工具验证：

- 能否连接。
- 能否读取身份、状态和版本。
- 能否稳定读取关键点位。
- 能否写入一个安全的测试点。
- 断网、重启、拔线、设备忙和错误码如何表现。

不要一开始就写完整 HMI。

### 阶段 3：建立设备适配层

为每种设备实现统一接口，处理连接、重试、超时、映射、质量和诊断。

### 阶段 4：实现领域模型和状态机

先实现“设备状态、工艺步骤、命令、事件和异常”模型，再实现页面。

### 阶段 5：实现数据链路

区分：

- 实时状态：最新值和质量。
- 事件：状态变化、报警、操作。
- 历史数据：带时间戳的过程值。
- 追溯数据：产品、批次、工单、配方和结果。
- 审计数据：谁在什么时间执行了什么命令。

### 阶段 6：HMI 和权限

页面应展示状态、质量、更新时间和错误原因。所有写操作都要经过命令模型，不要让控件事件直接写 PLC。

### 阶段 7：故障和恢复

至少验证：

- 设备启动顺序不同。
- 网络中断和恢复。
- PLC 重启。
- 程序重启。
- 数据库不可用。
- 消息 Broker 不可用。
- 采集超时。
- 返回非法数据。
- 操作员重复点击。
- 设备处于错误或手动模式。

### 阶段 8：现场 FAT/SAT

- FAT：工厂验收测试，模拟或实验室验证。
- SAT：现场验收测试，真实设备、真实网络和真实工艺验证。
- 记录软件版本、配置版本、固件版本、网络参数和测试证据。

### 阶段 9：发布和运维

建议具备：

- 可回滚安装包。
- 配置备份与校验。
- 数据库迁移脚本。
- 日志保留策略。
- 设备连接诊断页面。
- 版本和配置指纹。
- 远程升级前的备份与恢复方案。

## 8. 工业 C# 常见坑

### 8.1 把通信读取当成完整消息

TCP 和串口都是字节流或分段传输。必须实现缓冲区、帧边界、长度校验、校验和和超时。

### 8.2 UI 线程阻塞

不要在 UI 线程中同步等待设备响应、数据库查询或图像处理。使用异步 API 和后台服务，并通过线程安全方式更新 UI。

### 8.3 无限重试

设备离线时无限快速重试会造成日志爆炸、CPU 占用和网络拥塞。使用指数退避、上限、熔断和明确的恢复状态。

### 8.4 重试不可重试的写操作

读取通常可重试，但写命令可能已经在设备执行，客户端却因超时而不知道结果。对写操作使用命令 ID、幂等设计、状态确认和人工复核，不能盲目重发。

### 8.5 时间和时区混乱

设备时间、PLC 时间、工控机时间、数据库时间可能不同。建议内部统一 UTC 或明确的带时区 `DateTimeOffset`，展示层再转换。

### 8.6 字节序和数据类型错误

常见问题：

- 16 位寄存器拼 32 位整数时高低字顺序相反。
- 浮点数按错误字节序解析。
- 有符号数被当成无符号数。
- 位地址和字地址混淆。
- `REAL`、`LREAL`、`INT` 在 PLC 与 C# 之间不一致。

建立独立的协议编解码测试，不要靠现场试错。

### 8.7 采样周期不等于数据真实频率

程序每 100 ms 读取一次，不代表设备值每 100 ms 更新一次。必须了解设备刷新周期、网络延迟、服务器缓存和采样时间。

### 8.8 只记录当前值，不记录质量

“0”可能代表真实零值、通信失败、传感器断线或尚未初始化。所有测量值都应携带质量、时间戳和来源。

### 8.9 不区分命令、状态和事件

- 命令：希望设备做什么。
- 状态：设备当前是什么状态。
- 事件：某个时刻发生了什么。

三者混在一个布尔变量中，会导致重复执行和追溯困难。

### 8.10 资源释放不完整

串口、Socket、OPC UA Session、订阅、相机句柄、图像缓冲区、数据库连接都要有明确生命周期。支持取消、超时和应用关闭。

### 8.11 配置直接散落在代码里

设备地址、寄存器、轮询周期、超时、重试次数和量程应配置化，并经过校验。危险输出的默认值应保持安全状态。

### 8.12 日志不可诊断

日志至少包含：设备 ID、连接地址、操作类型、命令 ID、耗时、结果、错误码、重试次数和关联业务 ID。不要只写“连接失败”。

### 8.13 把数据库当作实时控制总线

数据库适合历史、追溯和业务状态，不适合替代 PLC 或实时消息链路。

### 8.14 忽略部署环境

开发机能运行，不代表工控机能运行。必须验证驱动、运行时、系统权限、杀毒软件、防火墙、DPI、字体、时区、串口号和用户登录方式。

## 9. .NET 8.0 新特性与工业项目价值

### 9.1 生命周期

.NET 8 于 2023-11-14 发布，是 LTS 版本。官方支持策略显示其支持到 2026-11-10。工业项目应锁定具体补丁版本，并制定升级和迁移计划。新建项目还要评估当前最新 LTS 版本是否更合适。

### 9.2 C# 12

#### 集合表达式

```csharp
int[] channels = [1, 2, 3, 4];
int[] allChannels = [.. channels, 5, 6];
```

适合配置通道、寄存器列表和测试数据。不要为了语法简洁而牺牲表达清晰度。

#### 主构造函数

```csharp
public sealed class DeviceClient(
    string deviceId,
    ILogger<DeviceClient> logger)
{
    public string DeviceId => deviceId;
}
```

适合依赖注入和只读依赖，但复杂初始化、继承和字段生命周期仍要保持可读。

#### 任意类型别名

C# 12 支持使用 `using` 给更多类型形式定义别名，可用于复杂协议类型，但团队需要统一命名规范。

#### Lambda 默认参数

适合测试、策略和小型回调；协议处理核心逻辑不应过度压缩成难调试的 Lambda。

### 9.3 Native AOT

.NET 8 为 ASP.NET Core 引入 Native AOT 支持。优势：

- 启动更快。
- 内存占用可能更低。
- 发布物可包含本机可执行文件。
- 适合边缘服务、轻量网关和大量部署实例。

限制：

- 反射、动态加载、运行时生成代码可能不兼容。
- 不是所有 ASP.NET Core 功能都支持。
- 发布时必须处理 trimming/AOT 警告。
- 部分厂商 SDK、视觉库和动态插件体系可能不适合 AOT。

建议：设备驱动插件、WPF HMI 和依赖大量反射的应用先用普通 CoreCLR；无 UI 的边缘采集服务、协议网关和小型 API 再评估 AOT。

### 9.4 `CreateSlimBuilder` 与 `CreateEmptyBuilder`

适合构建功能明确、依赖较少的边缘服务，减少默认组件和发布体积。但工业项目必须显式补齐日志、配置、证书、健康检查和诊断能力，不能只追求体积。

### 9.5 System.Text.Json 源代码生成

源代码生成可以减少反射开销，并改善 Native AOT 兼容性。适合固定的设备消息、遥测 DTO 和 API 契约：

```csharp
[JsonSerializable(typeof(DeviceTelemetry))]
internal partial class IndustrialJsonContext : JsonSerializerContext
{
}
```

对于版本化消息，建议显式定义兼容策略，不要把字段重命名当作无影响变更。

### 9.6 性能、GC 和运行时改进

.NET 8 延续了 JIT、GC、SIMD、Span、集合和基础库优化。工业项目的正确用法是先测量：

- 采集周期抖动。
- CPU 使用率。
- GC 次数和暂停。
- 消息吞吐。
- 图像处理耗时。
- 数据库写入延迟。

不要在没有基准测试的情况下到处使用 `unsafe`、对象池或手写序列化。

### 9.7 ASP.NET Core 8

工业服务中值得关注：

- Minimal API：适合轻量边缘 API。
- Native AOT Web API 模板：适合明确受限的服务。
- Blazor、SignalR：适合状态推送和实时 HMI 场景。
- 原生限流：保护设备 API 和管理 API。
- 更好的身份认证和授权能力。

设备写操作接口必须增加权限、审计、幂等和设备状态检查。

### 9.8 .NET 8 韧性能力

.NET 8 生态新增了 `Microsoft.Extensions.Resilience` 和 `Microsoft.Extensions.Http.Resilience`，底层与 Polly 生态协作，支持重试、超时、熔断、限流和回退。

工业项目注意：

- 读取类请求可以使用有限次数重试。
- 写命令不能默认套用所有重试策略。
- 总超时必须小于业务步骤的可接受时间。
- 熔断状态要显示给操作员并记录。
- 重试必须带日志和指标。

### 9.9 EF Core 8

EF Core 8 改进了复杂类型、原始类型集合、JSON 列映射、原生 SQL、延迟加载和模型能力，并新增 `HierarchyId` 支持。

工业项目建议：

- 实时测点历史写入不要无脑逐条 SaveChanges。
- 追溯表和配置表适合 EF Core。
- 高吞吐时序写入应评估批量写、专用时序库或队列。
- 迁移脚本必须经过离线备份和回滚验证。

### 9.10 容器镜像

.NET 8 提供更细分的容器镜像，包括 distroless、chiseled 和 AOT 相关变体。工业边缘部署使用容器时要验证：

- 串口和 USB 设备映射。
- 网卡和实时网络权限。
- 时区和 ICU 数据。
- 持久化目录。
- 现场升级和回滚。
- 容器运行时重启策略。

不要因为镜像更小就忽略诊断工具和现场维护能力。

## 10. 测试策略

### 10.1 单元测试

测试协议编解码、量程换算、状态机、报警规则、权限和重试策略。

### 10.2 模拟设备测试

实现 `FakeDevice`、故障注入和可控时钟，验证断线、延迟、非法值、重复消息和乱序消息。

### 10.3 集成测试

使用真实 PLC、仪表或协议模拟器测试连接、读写、订阅、重连和版本兼容。

### 10.4 压力和长稳测试

至少覆盖 24 小时或更长时间：内存、句柄、线程、日志、数据库文件、网络重连和采集周期抖动。

### 10.5 现场验收测试

每个危险动作要有前置条件、执行步骤、预期结果、异常结果和恢复步骤。

## 11. 推荐项目目录

```text
src/
  IndustrialApp.Host/
  IndustrialApp.Presentation/
  IndustrialApp.Application/
  IndustrialApp.Domain/
  IndustrialApp.Infrastructure/
    Devices/
      Modbus/
      OpcUa/
      Serial/
      VendorSdk/
    Persistence/
    Messaging/
  IndustrialApp.Contracts/
tests/
  IndustrialApp.UnitTests/
  IndustrialApp.IntegrationTests/
  IndustrialApp.DeviceSimulation/
docs/
  io-list.md
  communication-matrix.md
  alarm-list.md
  deployment.md
  acceptance-test.md
```

## 12. 学习路线

### 第一阶段：C# 与 .NET 基础

- async/await、CancellationToken、Channel、线程安全。
- DI、配置、日志、Generic Host。
- Socket、串口、JSON、数据库。
- 单元测试和调试。

### 第二阶段：工业基础

- PLC 扫描周期、I/O、状态机、报警和联锁。
- 电气图、I/O 表、设备手册和网络拓扑。
- Modbus、OPC UA、MQTT、串口帧协议。
- 时间戳、质量码、单位和量程。

### 第三阶段：上位机工程

- WPF + MVVM。
- 设备抽象层和模拟设备。
- 采集调度、断线重连、缓存和追溯。
- 配方、权限、审计和报警。

### 第四阶段：平台化

- ASP.NET Core、SignalR、数据库、消息系统。
- OpenTelemetry、健康检查、容器和 CI/CD。
- 远程运维、版本控制、灰度升级。
- 安全分区、证书、最小权限和供应链安全。

## 13. 快速决策表

| 需求 | 优先考虑 | 关键提醒 |
|---|---|---|
| 单机 Windows 上位机 | WPF + Generic Host | UI 与通信解耦 |
| 老设备串口接入 | SerialPort + 自定义帧解析 | 不要假设一次读取就是一帧 |
| 简单仪表/PLC 点位 | Modbus RTU/TCP | 地址、字节序、缩放最容易错 |
| 跨品牌设备互操作 | OPC UA | 证书、命名空间、订阅和语义 |
| 边缘到云 | MQTT over TLS | QoS、重复消息、断网缓存 |
| 设备服务间调用 | gRPC/HTTP | 超时、幂等和版本兼容 |
| 实时网页状态 | SignalR/WebSocket | 不能代替硬实时控制 |
| 单机历史数据 | SQLite | 做备份、写入批处理和文件保护 |
| 企业追溯 | SQL Server/PostgreSQL | 事务、索引、归档和迁移 |
| 轻量边缘 API | ASP.NET Core Minimal API | 可评估 Native AOT |
| 复杂插件和厂商 SDK | 普通 .NET CoreCLR | 先确认反射和非托管兼容性 |

## 14. 参考资料

- .NET 8 新功能：https://learn.microsoft.com/dotnet/core/whats-new/dotnet-8/overview
- C# 12 新功能：https://learn.microsoft.com/dotnet/csharp/whats-new/csharp-12
- .NET Native AOT：https://learn.microsoft.com/dotnet/core/deploying/native-aot/
- ASP.NET Core Native AOT：https://learn.microsoft.com/aspnet/core/fundamentals/native-aot
- .NET 容器镜像：https://learn.microsoft.com/dotnet/core/docker/container-images
- SerialPort API：https://learn.microsoft.com/dotnet/api/system.io.ports.serialport
- OPC UA 概览：https://reference.opcfoundation.org/Core/Part1/v105/docs/4
- OPC Foundation：https://opcfoundation.org/
- .NET 支持策略：https://dotnet.microsoft.com/platform/support/policy/dotnet-core/

> 说明：协议和设备 SDK 的最终行为以具体厂商手册、固件版本、设备型号和现场测试结果为准。本文用于建立技术地图，不替代安全设计、设备认证和现场验收。
