上位机篇一:Launcher 才是程序总入口

IIoT.EdgeClient 的入口不是直接打开某个工序窗口,也不是让现场人员手动选择不同目录下的可执行文件。现场入口被收在 IIoT.Edge.Launcher 里,进入顺序分成两步:先在 Launcher 完成本地登录,再进入工序选择页启动对应的上位机实例。

这个设计对应的是现场维护方式。上位机平台面向的是多工序、多设备、多运行配置。每个工序都可能有自己的插件、PLC 配置、上传通道和本地运行数据目录;如果把入口分散到每个工序工程里,启动账号、运行路径、工序 profile、Shell 环境变量都会变成各自维护。Launcher 把入口统一起来,让现场只面对一个启动程序。

Launcher 登录页

这张登录页展示的是 Launcher 的第一层边界:登录发生在本地启动台,不等同于管理中台员工登录。页面右侧的“标准工序启动平台”说明区也能看出 Launcher 不是某个单独工序的界面,它负责把叠片、注液、匀浆这些工序放到同一个启动入口下。底部的工序标签不是业务运行状态,而是启动台可管理的工序类型提示。

本地登录和云端账号分开

Launcher 使用本地启动账号。代码里由 LauncherAccountCatalog 读取本地账号目录,LocalLauncherAuthService 负责验证,LauncherMainViewModel 组织登录状态和页面切换。真实账号文件是 launcher.accounts.json,开发环境可以生成本地账号文件,但这个文件不作为业务源码提交。

这条边界需要和管理中台账号分开。管理中台的人员、账号、角色、权限服务用于后台业务操作,例如管理设备、配方、角色和生产归档。Launcher 的账号用于控制本机启动台入口,解决的是“谁能在这台电脑上启动某个工序上位机”。两者都叫登录,但业务含义不同。

现场上位机还有设备身份链路:ClientCode 通过云端 bootstrap 换取 DeviceId。这也不属于 Launcher 登录。Launcher 登录只决定能否进入工序启动台;Shell 启动后,设备身份和云端上传再按机器 profile、ClientCode、bootstrap、DeviceId 的链路运行。

flowchart LR LocalLogin["Launcher 本地登录"] --> ProfilePage["工序选择页"] ProfilePage --> ShellStart["启动 IIoT.Edge.Shell.exe"] ShellStart --> MachineProfile["注入 Shell__MachineProfile"] MachineProfile --> Bootstrap["Shell 内执行设备 bootstrap"] Bootstrap --> DeviceId["获得 DeviceId 后进入上传链路"]

登录后才进入工序选择

Launcher 工序选择页

工序选择页展示的是 Launcher 的第二层边界:它不承载工序业务,只负责列出可启动 profile。当前 scripts/edge-runtime.publish.json 里有叠片、注液、匀浆三类 runtime 配置,对应 StackingLineInjectionLineHomogenizationLine 这些 MachineProfile。匀浆是当前落地最完整的插件,不代表平台只有匀浆;叠片和注液在平台上以 profile、插件和配置扩展位存在。

LauncherProfileCataloglauncher.profiles.json 读取工序卡片。每个 profile 包含 ProfileIdDisplayNameMachineProfileExecutablePathWorkingDirectory 等字段。现场人员点击卡片时,ShellLaunchService 启动配置里的 Shell 可执行文件,并把 Shell__MachineProfile 写入进程环境变量。Shell 进入运行阶段后,再根据该值加载对应机器配置。

这个做法让入口和运行分层。Launcher 不需要知道匀浆页面怎么画,也不需要知道注液和叠片后续会有哪些 PLC 点位;它只需要知道“启动哪个 Shell、注入哪个 MachineProfile”。工序差异进入 Shell 后由配置和插件处理。

Launcher 管入口,不管工序业务

Launcher 的职责可以拆成四类:

  • 本地启动账号:通过 LauncherAccountCatalogLocalLauncherAuthService 控制入口。
  • 工序 profile:通过 LauncherProfileCatalog 读取卡片。
  • Shell 启动:通过 ShellLaunchService 创建进程。
  • 环境注入:通过 Shell__MachineProfile 把工序运行配置传给 Shell。

这些职责都围绕“启动”展开。配方、产能、日志、Cloud 上传、MES 上传、PLC 周期任务、页面导航和诊断都不在 Launcher 内处理。Launcher 越少介入工序业务,平台入口越稳定;新增工序时,主要补 profile、配置和插件,而不是改启动台逻辑。

新增工序时入口不变

新增工序的路径在 IIoT.EdgeClient/docs/edge-runtime-deployment.md 里已经固化:补 runtime 配置、补机器配置、补插件包,生成 launcher.profiles.json 后,Launcher 工序选择页出现新的卡片。这个过程不需要为新工序复制一个新的启动程序。

这也是标准化上位机平台的第一步。现场人员只认 Launcher;平台负责人控制 Launcher 和 Shell;工序开发人员在插件边界内扩展业务。入口统一以后,后续的权限、部署、版本、诊断和截图验收才有稳定基准。

两个界面对应两个启动阶段

Launcher 的第一个界面是本地登录,第二个界面是工序选择。登录只负责进入本机启动台,不等同于管理中台员工登录。工序选择负责从 profile 列表中选择要启动的上位机实例,再由 ShellLaunchService 启动对应目录下的 IIoT.Edge.Shell.exe

这个设计把现场启动流程拆成了两步:先控制谁能使用本机启动台,再决定启动哪个工序运行实例。现场人员不需要自己找不同目录里的 exe,也不需要手动改配置文件。Launcher 把这些选择变成受控入口。

profile 是工序启动合同

launcher.profiles.json 来自 scripts/edge-runtime.publish.json,不是手写在 XAML 里的卡片。每个 profile 描述 profileId、MachineProfile、输出目录、配置文件、模块列表、显示名、说明、图标和主题色。Launcher 读取 profile 后展示工序卡片,点击卡片后启动对应 Shell。

这种方式把“新增工序入口”从 UI 代码里拿出来。后续新增注液或叠片时,启动项通过 profile 和发布脚本维护,而不是改 Launcher 页面。宿主的统一性也更容易保持:入口样式、登录流程、窗口行为都归 Launcher 管,工序差异归 profile 和插件管。

Shell__MachineProfile 决定运行身份

启动 Shell 时,ShellLaunchService 会把 Shell__MachineProfile 写入进程环境变量。Shell 启动后根据这个 profile 加载对应的 appsettings.machine.<Profile>.json 和模块启用配置。也就是说,Launcher 不是简单打开一个程序,而是在启动时明确告诉 Shell 当前要以哪种机器 profile 运行。

这个机制解决了多工序上位机的入口混乱问题。相同 Shell 可以承载不同 profile,不同 profile 决定启用哪些插件、加载哪些配置、连接哪些设备和页面。平台入口统一,工序运行独立。

posted @ 2026-04-30 15:02  LJHArchitecture  阅读(29)  评论(0)    收藏  举报