# 地址空间

> 每个点位所在的那七个保留根、一个地址怎么书写和规整、点位到哪里为止、成员从哪里开始、筛选框收窄的是什么，以及在编辑器里输入一个地址的三种办法。

一个表达式、一个脚本、一个仪表画面绑定或者一个代理工具能点名的每一个点位，都住在七个保留根之一下面。你自己起的名字始终住在某个根下面，所以它们绝不会和那些根本身撞上。Logic 页面那一栏画的就是这同样几个根，分在两个小标题下；树里显示的东西，正是你要打的东西：一行的地址就是表达式所用的那段文字。

## 七个根 {#the-seven-roots}

| 根 | 装着什么 | 栏里的小标题 | 在哪里编辑 |
| --- | --- | --- | --- |
| `System` | 应用发布的关于它自己的四项诊断值 | 来自其他页面 | 哪里都不能 |
| `Server` | 内置 OPC UA 服务器的四项诊断值 | 来自其他页面 | 在 [Connector](connector-opcua-server) 里 |
| `Connector` | 实时的驱动、文件夹、设备和点位树 | 来自其他页面 | 在 [Connector](connector) 页面上 |
| `Variables` | 你在这里定义的那些变量，在它们的文件夹里 | 在这里定义 | 就在这里 |
| `Alarms` | 你在这里定义的那些报警的实时状态，在它们的文件夹里 | 在这里定义 | 就在这里（状态本身只读） |
| `Process` | 每个模型的单元：通道、运行状态、产量、命令、预选 | 来自其他页面 | 在 [Process](process) 页面上 |
| `Assets` | 素材库里的图像、图标和颜色，可以按名字寻址 | 在这里定义，作为 Assets 根 | 在[资源](logic-assets)的那些面板上 |

Actions 和 Triggers 是这一栏里的两节，但不是地址空间的根：它们是按身份被引用的，不是按地址，也不带实时数值。`Assets` 根是给表达式和“浏览…”选择器用的；在栏里，它的位置由素材库的 Assets 根占着，所以树里绝不会出现两个同名的根。`System` 和 `Server` 的那些固定点位，以及 `Connector` 和 `Process` 两根树枝的形状，都列在[来自其他页面](logic-from-other-pages)里。

## 一个地址怎么书写 {#how-an-address-is-spelled}

地址是从一个保留根起、用点分隔的若干段：`Connector.Simulated.Air.CompressedAir.HeaderPressure`、`Variables.Forno.Setpoint`、`Alarms.HighLevel`、`System.Now`、`Assets.Colors.Red`。显示名称仍然是自由文本；地址用的是每个名字规整之后的那一段：每一个不是字母也不是数字的字符都变成 `_`，而以数字开头的名字前面补一个 `_`（`Forno de teste` 对应 `Forno_de_teste`，`3rd zone` 对应 `_3rd_zone`，空名字对应 `_`）。段永远是标识符，所以点号形式永远管用；一段也可以写成带字符串字面量的方括号形式，`Variables["Setpoint"]`，求值器把它读成同一个地址。

点位到哪里为止、成员从哪里开始，取决于那个根。`Connector` 的地址在驱动和设备之间带着设备的文件夹层级（串行线路和 MQTT Broker 都不加一层），而 `Variables` 和 `Alarms` 在名字之前最多带三层文件夹，所以在这几个根下面，点位是能解析出来的那个最长前缀，跟在它后面的是成员（`.Value`、`.State()`）。`Assets` 永远是根下面两段；`Process` 对一个普通点位是四段，对一个产量汇总点位是六段，对一个产量输出点位或流程点位是七段。比它的根所允许的还短的链会作为不完整的地址被拒绝。

表达式和脚本里的地址必须是静态的：每一段要么是标识符，要么是字符串字面量，绝不能是算出来的值。`Variables[someName]` 在校验时被拒绝，写作“地址必须是静态的”。

## 地址冲突 {#address-collisions}

一节里的一层就是一个由归在那里的文件夹和定义共用的单段命名空间。不同文件夹里两个都叫 `Setpoint` 的变量没问题；同一层上一个变量和一个文件夹都规整成 `Forno` 就不行，`Pump 1` 和 `Pump_1` 并排也不行。编辑器会在你打字时就拒绝这样的名字，并点名什么已经在应答这个地址：“‘Pump 1’已经对应‘Variables.Pump_1’。归在同一个文件夹里的名称，净化之后必须得到互不相同的地址段。”资源在每个类别内部遵循同一条规则：你自己的两张图像、两个图标或两种颜色不能共用一段，而一个用户图标或用户颜色的段和某个系统条目撞上时，它在那个地址上顶掉系统条目。

## 输入一个地址 {#entering-an-address}

在一个[表达式](logic-expressions)、一个条件或者一个脚本里输入地址有三种办法：

- **自己打。** 编辑器会自动补全地址记号：光秃秃的一个记号补根名（`Con` 提供 `Connector`），然后补已经打出来的那条路径下面的子项，按前缀匹配且不区分大小写，等这个记号点到一个点位之后，再补这个点位可读的成员。每一个候选项替换掉整个记号。
- **浏览…** 打开一个选择器，覆盖每一个根成员那一层的树，`Assets` 根也在内。选中一行按**插入**，或者双击它，就把它的地址放到光标处。页脚显示选中那一行会插入的文字，或者在什么都没选中时显示“双击（或按插入）添加到编辑器。”
- **从一个点位那里复制。** 在栏里选中任何一个点位都会打开[点位面板](logic-from-other-pages#the-point-panel)，它的“地址”字段是可以选中并复制的只读文字，旁边就是实时数值、它的质量和它的时间戳。变量或报警的编辑器则在“名称”字段下面回显它自己的地址。

在一个点位下面，选择器列出它可读的那些成员（`Value`、`ValueToReal()`、`State()` 等等）。成员不是一个自己的地址：它是你接在点位地址后面的东西。[表达式](logic-expressions#the-read-surface-of-a-point)列出的是同一个面，并写明每个成员返回什么。

## 筛选框 {#the-filter-box}

栏上方的**筛选…**框把树收窄到名称里含有所打文字的那些行，不区分大小写。点位只有自己匹配才留下来；文件夹在自己匹配或者任何后代匹配时留下来，并展开到它的那些匹配项。Actions 和 Triggers 两节只列出名称匹配的行（它们自己的名称能让这一节继续列着，但里面是空的）；Assets 根收窄到名称匹配的那些类别（打 `Col` 只剩下 Colors），而只有它自己的名称匹配时就整个留下；名称自己匹配的地址空间根仍然列着，展开时才载入它的树枝。成员从不进入筛选后的视图，而筛选只属于你自己那个窗口：同一工作站上的另一个浏览器保留它自己的筛选。

## 地址空间不做什么 {#what-the-address-space-does-not-do}

对一台已禁用的设备、一台点位没有在 Connector 里落地的设备，或者一个没有绑定的 Process 通道（这样的通道会列出来，但不提供成员），它什么都不发布。名字不会被翻译：地址就是规整过的显示名称，所以给一个变量、一个报警、一个文件夹、一台设备、一个点位或者一张图像重命名，都是一次地址改动，应用会通过那次安全重命名把每一处引用都改写掉（见[变量](logic-variables#name-and-address)、[设备文件夹](connector-folders)）。
