20 · 程序集速查表

相关:README 的四层架构图 · 第 03 章 我该从哪一章开始看

这一章是什么

一页看全 15 个程序集。 查不到东西的时候翻这里。

每条包含:在哪一层、依赖谁、核心类型、对应的章。


一、四层总览

第 4 层  宿主 / 集成层 ── 已经装好的那套东西
  Hmi.Shell(WPF 壳)      Hmi.HostBridge(消息路由)
  Hmi.Mcp.Host           Hmi.RuntimeCore.Host      Hmi.Supervisor
              ↑ 依赖
第 3 层  组合层 ── 把下面的拼成完整能力
  Hmi.Automation(组态 API)  Hmi.Backend(运行引擎)  Hmi.ScriptRuntime(脚本宿主)
              ↑ 依赖
第 2 层  领域库层 ── 各自管一块
  Hmi.Project   Hmi.Drivers   Hmi.Scripting
  Hmi.Historian Hmi.Alarms    Hmi.Security
              ↑ 依赖
第 1 层  内核层 ── 最底下的地基
  Hmi.Core(实时库 + 点模型 + 变化分发)

规则:上层能用下层,下层不认识上层。所以 Hmi.Core 不知道什么是"工程"。


二、15 个程序集逐条

第 1 层 · 内核层

Hmi.Core

一句话 实时库 + 点模型 + 变化分发。所有东西的地基
依赖 无(最底层)
目标框架 net8.0
章 04 · 05

核心类型(15 个公开类型):

类型 干什么
RtdbCore 实时库 —— 内存里的点值表。按 Id 读写,订阅变化
Tag 一个点的运行时形态(值 + 质量 + 时间戳)
TagValue 值(联合体,能装 double/int/bool/string)
Quality 质量戳(良好/坏/不确定)
TagDataType 数据类型枚举
TagClassification 点的分类(采集点 / 内部变量)
DeliveryMode 投递车道:Droppable(界面用)/ Lossless(报警历史用)
ITagSubscriber 订阅者接口,OnTagChanged(batch)
ChangeDispatcher 变化分发器
SubscriptionRegistry 订阅登记
ByteOrderCodec / ScalingHelper / DeadbandHelper 字节序 / 量程换算 / 死区
UiStateStore 界面状态
Branding 品牌信息

⭐ DeliveryMode 是理解实时库的关键:界面订阅用 Droppable(堵了就丢,保最新); 报警和历史用 Lossless(一条都不能少)。两条车道分开,互不影响。


第 2 层 · 领域库层

Hmi.Project

一句话 工程模型 + 磁盘读写。工程文件长什么样就是它定的
依赖 Hmi.Core、Drivers.Abstractions
公开类型数 108(最多的一个)
章 06

核心类型:

类型 干什么
ProjectLoader 加载/保存工程目录。Load(dir) / Save(proj, dir)
LoadedProject 内存里的完整工程(Project + Screens + Tags + Channels + …)
ProjectModel 工程元信息(名/版本/启动画面)
ScreenModel 一个画面
ElementModel 元素基类(30 多个派生:Button / Bar / Trend / Tank / Valve …)
TagDef 点的定义(不是值)
ChannelDef / DeviceDef 通道 / 设备定义
RecipeModel / RecipeItem 配方
AlarmConfigModel / HistoryConfigModel 报警配置 / 历史配置
ProjectScripts / ScreenScripts / ElementEvents 三个层级的脚本
ScriptModule 脚本模块
ReportModel 报表定义
LanguageTable / TranslationEntry 多语言
ProjectArchive / ProjectPackage .hmiproj 归档 / .hmipkg 封包
RtdbBridge 把 TagDef[] 建成 Tag[] 给实时库
CustomButtonSkin 自定义按钮皮肤
NotifyConfig / SmtpMailSender 邮件通知

Hmi.Drivers

一句话 采集框架 —— 采集循环、块读规划、重连、插件加载
依赖 Hmi.Core、Drivers.Abstractions
章 07 · 08 · 09

核心类型:

类型 干什么
ChannelRuntime 一个通道的运行时(连设备、跑采集循环)
ChannelScheduler 调度多个通道
BlockPlanner / BlockPlan 块读规划 —— 把散点合并成连续块一次读
BackoffPolicy 重连退避策略
ProtocolRegistry 协议登记表
ProtocolPluginLoader / PluginManifest 插件加载 / plugin.json 清单
SimulationDriver / SimulationPackage 内置模拟驱动
Unpacker 拆包

⚠ Hmi.Drivers 只是框架。真正的协议实现在 Drivers.* 子项目里(见第四节)。

Drivers.Abstractions

一句话 写驱动要实现的接口都在这
依赖 Hmi.Core
章 07 · 09

核心类型:

类型 干什么
IProtocolDriver 驱动主接口:连接、读块、写、断开
IProtocolPackage 插件包接口:声明自己提供哪些驱动
IAddressParser 地址解析(把 "40001+2" 解析成寄存器号)
IConnectionSchemaProvider 声明支持哪些连接方式(TCP/串口)及参数
ProtocolLimits 协议限制(一次最多读多少寄存器/位)
ProtocolAbi ABI 版本 —— Version = 1。版本不匹配的插件拒载
DeviceConfig / ChannelConfig 设备/通道配置
ConnectionKind / ConnectionParam / TransportSchema 连接方式与参数
RegisterWidth / ByteOrderCodec 寄存器宽度 / 字节序
WriteSource 写来源(区分谁写的)

⭐ ProtocolAbi.Version 是插件兼容性的关键。宿主 ABI 版本变了, 老插件会被拒绝加载(而不是崩溃)。

Hmi.Scripting

一句话 脚本引擎 —— 编译脚本、拦住危险操作、给脚本提供函数库
依赖 Hmi.Core
公开类型数 36
章 11 · 13

核心类型:

类型 干什么
ScriptEngine 编译 + 执行脚本(Roslyn CSharpScript)
ScriptSafetyAnalyzer 安全检查 —— 黑名单拦危险 API
ScriptGlobals 脚本的全局上下文
ScriptCompileResult / ScriptRunResult / ScriptRunOutcome 编译/运行结果(5 种结果之一)
ScriptDiagnostic / ScriptDiagnosticSeverity 编译诊断
ScriptApiUnavailableException "宿主没接上这个能力"(不是脚本写错了)
16 个函数库门面 TagApi LogApi SysApi Math2Api StringApi BitApi FileApi CsvApi TimerApi AlarmApi HistoryApi UiApi DbApi CommApi RecipeApi ReportApi
对应的服务接口 IAlarmService IHistoryService IUiService IDbService ICommService IRecipeService IReportService ITagGateway
TagMeta 点的元数据(单位/量程/可写)

⭐ ScriptApiUnavailableException 的语义很重要:它表示宿主没接上能力, 不是你的脚本写错了。看到这个异常要去查宿主装配,不要去改脚本。

Hmi.Historian

一句话 历史库 —— 把值记到 SQLite,按时间查回来
依赖 Hmi.Core
章 14

核心类型:

类型 干什么
IHistorian 历史库接口(写记录 / 查范围 / 聚合)
SqliteHistorian SQLite 实现。表 hist(tag_id, ts_utc, val, q),WAL 模式。攒批在这里:BatchSize=1000 / FlushIntervalMs=1000
HistorianRecorder 规则判定器(RTDB 订阅者):按每点 TagHistoryRule 决定这条要不要落,落就交给 IHistorian。只做轻量判定 + 入队,重活在写线程
HistoryRecordMode 记录模式枚举
TagHistoryRule 记录规则:OnChange / Timed / Both
AggFunc 聚合函数:Avg / Max / Min / Sum / Count
RetentionSweeper 过期数据清理(按保留天数)
IHistorianMaintenance 维护接口

⭐ 攒批在 SqliteHistorian 里,不在 HistorianRecorder —— 两者职责别混: HistorianRecorder 只判定"这条该不该记"(死区/定时),SqliteHistorian 才负责攒够再刷盘。 一条一条写 SQLite 会慢死,所以攒到 1000 条或 1 秒批量写。

Hmi.Alarms

一句话 报警引擎 —— 判超限、管状态流转、记报警记录
依赖 Hmi.Core
章 14

核心类型:

类型 干什么
AlarmEngine 报警引擎主体
AlarmEvaluationTicker 周期评估(定时检查所有点)
AlarmState 状态机:Normal → ActiveUnacked → ActiveAcked → ClearedUnacked → Normal
AlarmLevel 级别
AnalogLimit / DigitalAlarm 模拟量限值 / 开关量报警
TagAlarmConfig / AlarmConfigModel 按点的报警配置
AlarmRecord / AlarmItem 报警记录
IAlarmStore / InMemoryAlarmStore / SqliteAlarmStore 存储(内存/持久)
IClock / SystemClock 时钟抽象(测试能拨快时间)
AlarmConfigCsv 配置 CSV 导入导出

Hmi.Security

一句话 账号、角色、权限。不依赖任何 Hmi.*,能单独摘出去用
依赖 无
章 19

核心类型(9 个,全在这里了):

类型 干什么
AuthService 主入口:登录/登出/权限判定/账号管理
Permission 8 个权限位的位标志枚举
Role 角色(名 + 等级 + 权限位)
UserAccount 账号(带口令哈希,别整个序列化发前端)
LoginCandidate 登录器候选(只有 3 个字段,结构上不可能泄漏哈希)
PasswordHasher PBKDF2-HMAC-SHA256,10 万次迭代
IUserStore / SqliteUserStore 账号库存储
AuthResult 结果(和 AutomationResult 同口径)

第 3 层 · 组合层

Hmi.Automation

一句话 组态 + 感知的统一 API。界面/MCP/外部程序共用同一个入口
依赖 Hmi.Core、Hmi.Project、Hmi.Drivers + 三个驱动实现
章 15 · 16

核心类型:

类型 干什么
ProjectAutomation 实现类。Open(dir) 静态工厂
IProjectAutomation 132 个方法的接口
AutomationResult 统一返回 {Ok, Message, Data},失败不抛异常
AuditEntry 审计记录(每个写操作一条)
IScriptCompiler 脚本编译校验器接口
ScriptFunctionCatalog 脚本函数目录:15 库 / 176 函数
LibraryEntry / FunctionEntry 目录的条目类型

⚠ 这个程序集刻意不引用 Hmi.Scripting —— 编译校验通过 IScriptCompiler 接口注入,避免循环依赖。

Hmi.Backend

一句话 运行数据引擎 —— 把工程真正跑起来
依赖 Hmi.Core、Hmi.Project、Hmi.Drivers + 驱动实现
公开类型数 只有 3 个
章 10

核心类型(全在这了):

类型 干什么
RuntimeHost 运行宿主:建实时库、起采集循环、写点、查在线
DriverFactory 按协议名造驱动实例
IBackendDataService 后端数据服务接口

⭐ 公开类型只有 3 个,但这是整个"让工程跑起来"的核心。 RuntimeHost 的关键成员:Rtdb(实时库)、Start() / StopAsync()、 WriteTag(name, value)、IsDeviceOnline(deviceName)、ReconnectChannel(name)、 CycleOverrun 事件。

Hmi.ScriptRuntime

一句话 运行时脚本宿主 —— 把脚本挂到工程上,周期跑、事件跑
依赖 Hmi.Core、Hmi.Scripting、Hmi.Historian、Hmi.Alarms、Hmi.Project、Hmi.Automation
公开类型数 29
章 12

核心类型:

类型 干什么
ScriptRuntimeHost 脚本运行时宿主(起停、调度)
ScriptRuntimeBuilder 装配器
ScriptDispatcher 脚本派发
RuntimeDataServices Compose(...) —— 一键叠上历史 + 报警 + 脚本
RoslynScriptChecker IScriptCompiler 的实现(给 AttachCompiler 用)
RuntimeWriteGate ⭐ 写门禁:脚本只放行内部变量,采集点写入抛异常
RtdbTagGateway 脚本读写实时库的通道
LinkedVariableMirror 连接变量镜像
HistorianHistoryService / AlarmEngineService 给脚本用的历史/报警服务
ScriptUiService 给脚本用的界面服务
SqliteDbService 给脚本用的数据库服务
CommService / RecipeService / RecipeControlService 通信/配方服务
AlarmNotifier 报警往外发通知(邮件)
ReportGenerator / ReportTable 报表生成
ScriptModuleCompiler / ScriptValidator / ScriptBuildReport 模块编译与校验
UiReferenceRewriter 界面引用改写
ScriptLogSink 日志转发

第 4 层 · 宿主 / 集成层

Hmi.HostBridge

一句话 前后端消息路由 —— 前端发来的 JSON 在这里分派给处理者
依赖 Hmi.Automation、Hmi.Backend、Hmi.Core、Hmi.Historian、Hmi.Project、Hmi.Security
公开类型数 33
章 17

核心类型:

类型 干什么
WebMessageRouter 路由器:HandleInbound(json) 是唯一入口
WebMessage / WebJson 消息信封 + 两套序列化配置
IWebMessageSink 出站唯一出口(Post(json))
AutomationRpcDispatcher 约 100 个组态 RPC
AuthRpcDispatcher 15 个认证/账号 RPC
AiRpcDispatcher 8 个 AI 助手 RPC
McpControlRpcDispatcher 5 个 MCP 控制 RPC
TagSubscriptionBridge 实时值订阅推送(tag-update)
HistoryQueryBridge 历史查询(query_history / aggregate_history)
UiOverrideBridge 界面覆盖配置
RuntimeLogWire 运行态日志回流(##RTLOG## 哨兵)
McpServerConfigStore / IMcpServerProcess / SystemMcpServerProcess MCP 子进程管理
UiLog 前端日志落盘(ui.log,4MB 轮转)
AiProviderStore / AiConversationStore / LlmClient AI 助手(多模型、会话、调用)
AiToolCatalog AI 可用的工具目录
AiContextCompactor 上下文压缩

Hmi.Shell

一句话 WPF 窗口壳 —— 一个窗口 + 一个 WebView2
依赖 Hmi.HostBridge、Hmi.Automation、Hmi.Project、Hmi.Backend、Hmi.ScriptRuntime
目标框架 ⚠ net8.0-windows(唯一一个,因为要 WPF)
章 17

核心类型:

类型 干什么
App 入口。解析命令行(--runtime)、读环境变量
MainWindow 主窗口:嵌 WebView2、虚拟域名映射、消息收发
WebView2Sink IWebMessageSink 的实现
AutoSaveCoordinator 自动保存(防抖 1.5 秒)
UiZoomStore 界面缩放记忆(ui-zoom.json)
ShellLog 壳日志(exe 同目录 shell.log)

Hmi.Mcp.Host

一句话 给外部 AI 的 MCP 服务器(独立 exe)
依赖 Hmi.Automation、Hmi.ScriptRuntime
章 18

核心类型:

类型 干什么
Program 入口:解析参数、选传输方式、起服务
McpArgs 命令行参数解析
McpProjectHost 打开工程 + 挂编译器
ProjectMcpTools 84 个工具(36 感知 + 48 组态)
McpToolFilter 工具过滤(readOnly / 白名单)
AlarmLimitArg / AlarmDigitalArg 报警配置的参数形状

Hmi.RuntimeCore.Host

一句话 运行内核进程(独立 exe)。客户机上可以只装它
依赖 Hmi.Core、Hmi.Project、Hmi.Backend、Hmi.ScriptRuntime
公开类型数 0(只有一个 Program)
章 17

命令行:Hmi.RuntimeCore.Host.exe <工程目录> [--crash-after-ready <ms>]

通信:stdio。就绪打 RUNTIMECORE READY,之后每秒 HEARTBEAT <n>。

退出码:0 干净停机 / 1 装配异常 / 2 缺参数。

Hmi.Supervisor

一句话 进程监督 —— 拉起子进程、看它活着没、崩了重启。不依赖任何 Hmi.*
依赖 无
公开类型数 3
章 17

核心类型(全在这了):

类型 干什么
ProcessSupervisor 管一群进程:StartSessionAsync / StopSessionAsync
ManagedProcess 管一个进程:启动、看是否卡死、停止
ServiceSpec 描述一个服务(exe 路径/参数/就绪标记/重启策略)

三、依赖速查表

程序集 依赖谁
Hmi.Core —
Hmi.Security —
Hmi.Supervisor —
Hmi.Project Core, Drivers.Abstractions
Hmi.Scripting Core
Hmi.Historian Core
Hmi.Alarms Core
Hmi.Drivers Core, Drivers.Abstractions
Drivers.Abstractions Core
Hmi.Automation Core, Project, Drivers, 三个驱动实现
Hmi.Backend Core, Project, Drivers, 三个驱动实现
Hmi.ScriptRuntime Core, Scripting, Historian, Alarms, Project, Automation
Hmi.HostBridge Automation, Backend, Core, Historian, Project, Security
Hmi.Shell HostBridge, Automation, Project, Backend, ScriptRuntime
Hmi.Mcp.Host Automation, ScriptRuntime
Hmi.RuntimeCore.Host Core, Project, Backend, ScriptRuntime

三个"独立户"(零依赖,能单独摘出去用):

  • Hmi.Core —— 要一个内存点值表就能用
  • Hmi.Security —— 要账号权限就能用
  • Hmi.Supervisor —— 要进程监督就能用

四、驱动子项目(在 Hmi.Drivers/ 下)

Hmi.Drivers 只是框架。真正的协议实现是并列的子项目,每个都能单独发布成插件包:

子项目 提供什么
Drivers.Abstractions 接口定义(不是实现)
Drivers.ModbusTcp Modbus TCP
Drivers.IoTClientPlc 国产 IoTClient 系(西门子 200SMART / 300/400 / 1200/1500、三菱 MC、欧姆龙 FINS)
Drivers.PanasonicMewtocol 松下 Mewtocol
Drivers.S7SmartClient 西门子 S7(独立实现)
Hmi.Drivers 框架本身(采集循环、块读规划、插件加载)

这 5 个子项目都只依赖 Hmi.Core + Drivers.Abstractions —— 所以第三方写插件时,只要引这两个就能编出插件包。


五、内置 8 种协议对照

协议名(驱动名) 走哪个子项目
Simulation Hmi.Drivers 内置
ModbusTcp Drivers.ModbusTcp
S7-200SMART Drivers.IoTClientPlc
S7-300/400 Drivers.IoTClientPlc
S7-1200/1500 Drivers.IoTClientPlc
Mitsubishi-MC Drivers.IoTClientPlc
Omron-FINS Drivers.IoTClientPlc
Panasonic-Mewtocol Drivers.PanasonicMewtocol

⚠ 协议清单有两份手抄(后端 BuiltInRegistry + 前端 mock MOCK_PROTOCOLS), 有测试跨语言钉死。改必须两边一起改。


六、快速定位:我想干 X,该看哪个程序集

我想… 程序集 章
读一个点的实时值 Hmi.Core(RtdbCore) 04
读/写工程文件 Hmi.Project(ProjectLoader) 06
把工程跑起来连 PLC Hmi.Backend(RuntimeHost) 10
支持一个新协议 Drivers.Abstractions + Hmi.Drivers 09
让脚本能编译、拦住危险操作 Hmi.Scripting 11
给脚本加一个新函数 Hmi.Scripting(函数库门面)+ Hmi.Automation(目录) 13
记历史数据 Hmi.Historian 14
做报警 Hmi.Alarms 14
做账号权限 Hmi.Security 19
程序化改工程 Hmi.Automation 15
给前端加一个 RPC Hmi.HostBridge 17
让 AI 连进来 Hmi.Mcp.Host 18
管子进程生死 Hmi.Supervisor 17

七、⭐ 改能力时的"四处"清单

加一个能力(比如"给元素加一个新属性"),通常不止改一处。以 describe_element_props 为例:

# 位置 改什么
1 Hmi.Project 属性定义本身(propSchema 的真源在前端)
2 Hmi.Automation IProjectAutomation + 实现
3 Hmi.HostBridge AutomationRpcDispatcher 的 RPC 名
4 Hmi.Mcp.Host ProjectMcpTools 的工具方法(工具级 + 参数级 [Description] 都要写)
5 前端 propSchema.js + mock 的 ELEMENT_TYPES
6 文档 本手册 + docs/ 下相关文档

⭐ "同一能力有第二出口(MCP/CLI/脚本)时,形状必须对齐"。 漏改一处不会报错,只会静默不生效 —— 这是这个项目最常见的坑。


本章类型清单以 src/ 下各 .csproj 与源码为准。程序集数量变了记得同步改这里。