# 操作

> 在用的那些单元：每个单元一个节点，带着操作它所用的操作面板和仪表画面、一次运行记录是什么、从启动到已完成的生命周期，以及运行时停止期间什么会被拒绝。

**操作**是 Process 页面工作区列里一个模型四个分组中的最后一个（Process > 模型 > 某个模型 > 操作），排在[定义](process-definition)、[可视化](process-visualization)和[设定](process-setup)之后。另外三个分组声明这个过程；这一个装的是在用的那些单元，每个单元一个节点，而每个单元下面是操作它所用的那些界面。这里什么也不配置：一个单元是在模型自己的页面上声明和结束的（见[单元](process-units)），它的操作面板和仪表画面在可视化下面排布，而它运行什么则在设定下面拼装。

这一支画给每一个可以查看模型的角色（查看模型、运行流程、管理 Process）。只拥有编辑配方与判定的角色，看到的每个模型都缩成它的设定分组，因此操作对它不画出来。看是跟着树白送的；预选、启动和操控一次运行记录需要**运行流程**，角色没有它时，操作面板会在自己脸上说出来。

## 操作页面 {#the-operate-page}

选中这个分组会打开一整面卡片墙，每个单元一张，标题写着“这个模型运行在哪些工位上。打开一个即可预选流程、启动它，并观看一次带记录、有判定的运行。”。点一张卡片就打开那个单元。每张卡片都带着这个单元的实时状态，按下面这个优先次序解析出来：

| 状态 | 含义 |
| --- | --- |
| 停止信号已触发、等待复位、停止信号不可用 | 这个单元的[联锁](process-automation)不是正常。只有在模型观测一个外部停止信号时才显示；它压过下面的一切。 |
| 正在等待设定值抵达设备 | 一次运行占着这个单元，它的配方已经把某一段的设定值交了出去，正等着现场设备收下。这一段自己的时间还没开始计，所以它压过它下面的那些状态；底下的数据记录照旧一直在记。只有设为等待的段才会显示它。见[配方](process-recipes#what-a-run-does-with-it)。 |
| 记录中、已暂停、保存中、准备中、收尾中 | 一次运行记录占着这个单元：正在采样、被扣在某个设定值上、正在写它的快照、在运行记录存在之前先被预留，或者在最终状态之后正在关掉它的文件。 |
| 空闲 · 某个流程 | 没有东西占着这个单元，而那个流程已经为下一次启动预选好了。 |
| 空闲 · 未预选流程 | 没有东西占着这个单元，也什么都没预选。 |

一个没有单元的模型读作“还没有单元。请在模型自己的页面上，在‘单元’表里添加一个。”。这个分组的树行数出它有多少个单元。

详情栏带着那两条批量触发命令，只画给拥有运行流程的角色。这条栏上没有别的东西，因为这里既不创建也不删除什么。

| 命令 | 做什么 | 什么时候变灰（情形） | 什么时候不画出来（角色） |
| --- | --- | --- | --- |
| 全部启动 | 启动每一个已预选流程且当前可以运行的单元；其余的默默跳过。每一次启动的运行记录都把在这个屏幕上登录的操作员记为责任人。 | 当前没有单元接受启动，或者已经有一批正在派发。 | 没有运行流程时。 |
| 全部停止 | 停止每一个正在运行的单元；已经停止的仍然停止。 | 当前没有单元接受停止，或者已经有一批正在派发。 | 没有运行流程时。 |

一批只是一次触发，不是一次协同操作：每个单元各跑各的，某个单元上的一次拒绝会记进日志，绝不会把另一个回滚，而操作记录条报出的是数量（“已启动 3 个单元。”“没有单元可以停止。”）。

## 这个单元 {#the-unit}

一个单元自己的页面写出它的名字，说明有没有运行记录占着它，并通向它的每一个界面。有运行占着单元时，标题栏带着一枚写着运行状态的胶囊（记录中、已暂停、保存中、准备中、收尾中；一个设为等待的配方段还欠着设定值时则是“正在等待设定值抵达设备”；单元空着时什么也不带）。运行在等待时，那一行标题让位给“仍在等待：Furnace, Pump 1”，也就是还没有被各自的现场设备收下设定值的那些通道，所以页面自己就说明了这一段的时钟为什么还没开始走。另有一张**界面**卡片，把模型定义的那些操作面板和仪表画面按这个单元画出来，列成方块。这一页既没有命令栏动作，也没有右键菜单：它是一个入口，不是一个编辑的地方。

单元下面，树里每张操作面板一个节点，随后是每张仪表画面一个节点。两者都在 View 页面所用的那条舞台栏下面打开，名字写作“模型 · 单元 · 界面”，运行状态胶囊在名字旁边，两条窗口命令在末尾一侧：**展开**把整个窗口交给这个界面，**全屏**（F11）拿下整块屏幕，而 Esc 从两者中的任何一个退出来。

- 一个**操作面板**节点，为这个单元画出这张面板所排的那些卡片：运行记录卡片、元数据卡片、运行状态、备注、事件条目、通道图表、产量台账、单条命令，以及这张面板当作卡片嵌进来的任何一张仪表画面。那个界面逐张卡片讲在[运行记录与备注](process-runs)里。
- 一个**仪表画面**节点，跑的是模型那唯一一份定义，其中每一条抽象通道都由这个单元绑定的信号源来回答。它只显示这张仪表画面，绝不编辑它：编辑是模型自己在可视化下面那一行上的动作（见[一个模型的仪表画面][model-dashboards]）。上面什么都没放的仪表画面会这样说一句，而不是画出一个空舞台。它的命令类组件在这里只需要运行流程，因为这是官方的 Process 界面，不是工作站自己的一张仪表画面。

[model-dashboards]: process-dashboards

标着**在 View 上显示**的操作面板或仪表画面，也会出现在 View 页面上，这个模型的每个单元一个条目，名字相同；无论从哪里打开，它画出来的东西都一样。

## 一次运行记录是什么 {#what-a-run-is}

一次运行记录是一个流程在一个单元上的一次执行。它名叫“流程 · 单元”，记录进应用数据根目录下 `acquisitions` 文件夹里它自己那个 SQLite 文件，并由历史索引里的一行指向它，正是这一行让一次没结束的运行记录在重启之后还找得到、还能继续。流程的模式就是这次运行记录的外壳：**即时**套用一次、记录一行、判一次，然后自己结束；**时序**跑完流程的那个时间窗口，可以按循环重复若干轮，在最后一个窗口关掉时结束；**受控**在启动时套用，然后一直记录到有人把它停下来。

一个单元同时只有一次运行记录。启动会在解析任何东西之前先预留这个单元，因此正在准备的单元是忙的，却并不假装在记录；这次预留一直持续到运行中、已暂停、保存中，以及文件最后关掉为止。只要有任何一个单元被占着，这台工作站的每一个配置界面都是只读的（“有单元在运行时配置是锁住的。”）；操作本身照常活着，因为操作不是配置。

## 生命周期 {#the-lifecycle}

| 状态 | 含义 | 由什么进入 | 由什么离开 |
| --- | --- | --- | --- |
| 准备中 | 单元已被预留，运行记录正在被校验和成形。它不是一个保存下来的状态：`Procedure.Status` 这个点位在 `Busy` 已经为真的时候读到它。 | 启动 | 运行记录成形（运行中），或者一次拒绝（重新空闲）。 |
| 运行中 | 采样在走，时序运行记录的窗口时钟也在走。 | 启动、继续 | 暂停、停止、中止、窗口走完、一次失败、联锁。 |
| 已暂停 | 窗口时钟冻结在最后一个设定值上；数据记录继续记录。只有时序运行记录才有。 | 暂停 | 继续、停止、中止、联锁。 |
| 保存中 | 采样已经停止；收尾块已经执行，冻结的快照正在写下去。 | 停止、中止、窗口走完、联锁、一次即时运行记录完成 | 快照写完。 |
| 已完成 | 干净地结束了；结论就是判定给出的那个。 | 停止之后的保存中、窗口走完，或者一次即时运行记录 | 终态。 |
| 已中止 | 提前结束了；无论判定判出什么，结论都是不合格。 | 中止之后的保存中、配方失败处置设为中止、联锁，或者运行时停止 | 终态。 |
| 已失败 | 被一个无法恢复的错误结束；结论是没有结论。 | 运行期间或结束过程中的一次失败；崩溃留下的一个保存中指针，会在下一次启动时回来成为已失败 | 终态。 |

应用关闭时正处于运行中或已暂停的运行记录并没有结束：它在下一次启动时继续下去，时序曲线停在它保存下来的那个曲线段和那个循环上。

每一次运行记录都记下是谁启动了它（按下启动的那个屏幕上登录的操作员、没有人时就是工作站、单元的自动化，或者一个代理），以及是谁结束了它（对一次停止或中止而言，同样是这几类）。自己走完的窗口、一次联锁动作和一次失败，结束时不点任何人的名。暂停和继续不留下任何执行者。

## 什么会被拒绝，为什么 {#what-is-refused-and-why}

- **运行时已停止**：工作站运行时停止期间，启动、暂停、继续、停止、中止、那些单条命令、预选和备注全都以这个理由被拒绝，运行记录卡片把它写在自己的按钮下面。运行时停止时仍然开着的运行记录，以已中止结束。
- **联锁**：某个单元的联锁处于已触发、等待复位或者不可用时，这个单元上不再受理新的启动、继续、快照、判定或者套用配方（“单元‘X’被它的联锁挡住：理由”）。停止和中止仍然可用。
- **什么都没预选**：启动需要一个预选好的流程（“没有预选任何流程。请先选一个。”）。
- **信号源被另一次运行记录占着**：两个写同一个信号源的单元不能一起跑；第二次启动会被拒绝，并点名是哪条通道、被哪个单元占着。

这个分组的那些页面：

| 页面 | 讲什么 |
| --- | --- |
| [运行记录与备注](process-runs) | 一个单元的操作面板：预选、启动以及它校验什么、那些生命周期命令、那些实时卡片、备注、单条命令、运行记录文件，还有通向同一个生命周期的自动化路径和代理路径。 |
| [单元地址空间](process-addresses) | 一个单元在 `Process.<模型>.<单元>` 下面发布的每一个点位、它的类型和含义，以及哪些点位是可写的命令。 |
