# 驱动

> 驱动是什么、驱动列在哪里以及怎样添加到工作站、一台设备定死的那个驱动、本产品认得的每一个驱动的总表、每个驱动页面讲什么，以及关于安装包没带的驱动的说明。

一个**驱动**就是工作站用来和一族仪器对话的那个协议：TCP 上的 Modbus 寄存器、一台 OPC UA 服务器、一台 Siemens PLC。Connector 页面上的每一台设备都恰好属于一个驱动，而驱动决定这台设备显示哪些连接字段、它的点位怎么寻址、这些点位可以带哪些数据类型、它们能不能被写、这个驱动能不能扫描设备，以及是工作站去轮询它们还是仪器主动推送过来。这一组里每个驱动一页；本页讲的是它们的共同之处。

## 驱动清单 {#the-registry}

驱动的集合是定死的：它随应用一起发布，不能从页面上扩充。通信栏树顶上的“**驱动**”文件夹打开本次安装带着的那些驱动的目录，每一个都有它的说明、设备数量、健康状态和**添加驱动**（添加之后则是**打开**和**移除驱动**）；这份目录和它的规则在[驱动列表与单个驱动的页面](connector-drivers)里讲。

安装包带着的每一个驱动都可以直接使用，没有启用或禁用的开关：工作站把它要用的驱动添加进来。在“驱动”文件夹下面，树列出已添加的驱动，不论下面有没有东西，所以这一栏装的是工作站准备好要读的东西。驱动用目录里它那一行或这一栏“新建…”菜单里的**添加驱动**添加，用目录里它那一行、它自己的命令栏或它的右键菜单上的**移除驱动**移除。移除不删除任何东西：只要驱动还带着设备、串行线路、Broker 或文件夹，移除就会被拒绝，而带着其中任何一样的驱动总是已添加的。新工作站没有已添加的驱动；从早先版本更新而来的工作站一开始就已添加了它已经在用的驱动。

## 一台设备的驱动是定死的 {#the-driver-of-a-device-is-fixed}

驱动是你创建设备时选的：在通信栏的“新建…”菜单里，设备从这个驱动自己的那一项新建，而一个驱动页面上的“添加设备”就建在那个驱动下面。从那以后，“设备”卡片把驱动显示为只读文字。要把一台设备挪到另一个协议上，就在另一个驱动下面新建一台设备，再把旧的删掉；地址会变，所以那些引用得通过每个点位的“被谁使用”卡片改指到新点位上。

## 每一个驱动 {#every-driver}

驱动按其连接的设备类别分组，分组及其顺序与**驱动**目录以及这一栏“新建…”菜单里的**添加驱动**相同。

### PLC {#plcs}

| 驱动 | 对话对象 |
| --- | --- |
| [Beckhoff ADS](driver-beckhoff-ads) | 通过 ADS/AMS 连接的 Beckhoff TwinCAT PLC。 |
| [Mitsubishi MC](driver-mitsubishi) | 通过 MELSEC MC 驱动连接的 Mitsubishi PLC。 |
| [Omron](driver-omron) | Omron PLC：CJ、CS 和 CP 控制器通过 FINS（UDP、TCP 或串行线路上的 Host Link）按存储区地址读取，NJ、NX 和 NY 控制器通过 EtherNet/IP 按变量名读取。 |
| [Rockwell EtherNet/IP](driver-rockwell) | 通过 EtherNet/IP（CIP）连接的 Allen-Bradley / Rockwell PLC。 |
| [Siemens S7](driver-siemens-s7) | 通过 S7comm 驱动连接的 Siemens S7 PLC。 |

### 工业协议 {#industrial-protocols}

| 驱动 | 对话对象 |
| --- | --- |
| [BACnet](driver-bacnet) | BACnet/IP 楼宇自动化设备。 |
| [Generic serial and TCP](driver-generic-serial-tcp) | 通过串行线路、TCP 或 UDP 接入说自有文本或字节协议的现场设备，例如称重仪表和条码阅读器。 |
| [Modbus RTU](driver-modbus-rtu) | 串行线路（RS-485/232）上的 Modbus 寄存器，传输模式为 RTU 或 ASCII。 |
| [Modbus TCP](driver-modbus-tcp) | TCP/IP 上的 Modbus 寄存器，用 MBAP 帧，或为串口转以太网转换器用 RTU 帧。默认端口 502。 |
| [MQTT](driver-mqtt) | 通过外部 MQTT Broker 以普通 MQTT 或 Sparkplug B 发布数据的设备。 |
| [OCPP](driver-ocpp) | 通过 OCPP 连接的电动汽车充电桩（由充电桩主动连上本工作站）。 |
| [OPC DA](driver-opc-da) | 通过 COM/DCOM 的经典 OPC Data Access 服务器，经由专用的 32 位辅助进程访问。 |
| [OPC UA](driver-opc-ua) | 走 opc.tcp 的 OPC Unified Architecture 客户端。 |
| [SNMP](driver-snmp) | 响应 SNMP v1、v2c 或 v3 的网络设备，例如 UPS、PDU、交换机和机房传感器；与负责服务器的 Redfish 一起覆盖整个机房。 |

### 仪器与数据采集 {#instruments-and-acquisition}

| 驱动 | 对话对象 |
| --- | --- |
| [Fluke NetDAQ](driver-fluke-netdaq) | Fluke NetDAQ（2640A、2645A）和 2680 Series（2680A、2686A）数据采集仪，根据点位配置，并在 32 位辅助进程中通过 Fluke 自己的库读取。 |
| [NI-DAQmx](driver-ni-daqmx) | 通过本计算机上安装的 NI-DAQmx 读取的 National Instruments 数据采集硬件（cDAQ 机箱及其模块、USB 和 PCI Express 设备），每次读取一个样本。 |
| [SCPI instruments](driver-scpi) | 使用 SCPI 的台式仪器，例如万用表、电源和电子负载，通过 TCP、串行线路，或经由 VISA 的 USB 和 GPIB 连接。 |

### 无线 {#wireless}

| 驱动 | 对话对象 |
| --- | --- |
| [LoRaWAN](driver-lorawan) | 通过内置的 Basics Station 网络服务器接入的 LoRaWAN 传感器和无线集中器。 |
| [Matter](driver-matter) | Matter 智能家居设备（通过蓝牙调试入网）。 |

### Web 与 API {#web-and-apis}

| 驱动 | 对话对象 |
| --- | --- |
| [AVEVA PI](driver-aveva-pi) | 通过 PI Web API 接入的 AVEVA PI System 点，默认走 HTTPS。 |
| [HTTP](driver-http) | 作为点位轮询的通用 HTTP 和 HTTPS endpoint，可选带一份凭据。 |
| [Redfish](driver-redfish) | 服务器/数据中心硬件的 Redfish REST API。 |

### 文件和数据库 {#files-and-databases}

| 驱动 | 对话对象 |
| --- | --- |
| [Database](driver-database) | 工厂系统数据库中的表（SQL Server、PostgreSQL、MySQL 和 MariaDB、SQLite，或通过其 ODBC 驱动访问的任何数据库），每个点位按表、列和行读取一个单元格，或执行自定义查询；在点位要求的地方写入该单元格或点位自己的命令。 |
| [File](driver-file) | 其他程序写入本地或网络文件夹的文件（CSV 与分列文本、自由文本、JSON、XML），一次读取一个文件或从收件文件夹读取；在设备允许时，为该程序写入行或整个文件。 |

### 测试 {#test}

| 驱动 | 对话对象 |
| --- | --- |
| [Simulated](driver-simulated) | 应用内合成的信号，用来在没有硬件时做测试。 |

[Modbus 服务器](connector-modbus-server)不在这张表里：它不是驱动，而是工作站自己通过 Modbus TCP 把自己的点位和 Logic 变量提供给 PLC、HMI 和楼宇系统，在“服务器”文件夹下它自己的那一行里配置。

## 各驱动的共同之处与不同之处 {#what-the-drivers-have-in-common-and-where-they-differ}

Connector 为每个驱动画的是同一套编辑器，然后让驱动决定其中哪些部分露出来。打开某个驱动的页面之前，这张表先告诉你可以指望什么：

| 驱动 | 设备页面上的连接字段 | 点位寻址 | 轮询间隔 | 点位写入 | 设备发现 |
| --- | --- | --- | --- | --- | --- |
| Simulated | 无 | 点位名称，外加信号形状 | 有 | 有 | 有（它的目录） |
| Modbus TCP | 主机、端口、从站 ID、帧格式（MBAP 或 RTU）、最小事务间隔 | 定型：寄存器类别和寄存器号 | 有 | 有 | 有（按主机或 CIDR 扫描） |
| Modbus RTU | 串行线路（固定；传输模式 RTU 或 ASCII 由线路决定）、从站 ID | 定型：寄存器类别和寄存器号 | 有 | 有 | 有（在一条线路上探测从站 ID） |
| OPC UA | 主机、端口、资源路径、用户名、密码 | 自由文本：节点 id | 有 | 有 | 有（服务器地址） |
| OPC DA | 主机、服务器 / 键 | 自由文本：项 ID | 有 | 有 | 有（一台计算机上的服务器） |
| Siemens S7 | 主机、机架 / 槽位 | 定型：区域、DB、字节、位 | 有 | 有 | 无 |
| Rockwell EtherNet/IP | 主机、槽位 | 自由文本：控制器标签，外加一个偏移 | 有 | 有 | 有（广播） |
| Beckhoff ADS | 主机、端口、本机 IP（AMS） | 自由文本：符号 | 有 | 有 | 无 |
| Mitsubishi MC | 主机、端口 | 自由文本：设备地址 | 固定 1 秒 | 有 | 无 |
| BACnet | 主机、端口、设备 Id | 定型：对象类型和实例号 | 固定 1 秒 | 有 | 有（Who-Is） |
| OCPP | 标识符 | 定型：充电接口编号；点位名以 Meter、Status 或 Transaction 结尾 | 由充电桩推送 | 无（只读） | 有（已连上的充电桩） |
| Redfish | 主机、端口、用户名、密码 | 自由文本：资源路径，外加一个 JSON 指针 | 有 | 有 | 有（服务地址） |
| Matter | 节点 ID（只读） | 定型：输出、簇和属性；点位来自设备 | 有 | 有（驱动知道怎么改的那些值） | 有（已调试入网的节点，连同每个节点公开的值） |
| LoRaWAN | 标识符（DevEUI）、服务器 / 密钥（应用密钥） | 定型：通道或偏移、LPP 类型 | 由传感器推送 | 无（只读） | 无 |
| AVEVA PI | 主机、端口、资源路径、传输方式、用户名、密码、承载令牌 | 自由文本：PI 路径 | 有 | 有 | 有（服务地址之后的 AF 元素） |
| HTTP | 主机、端口、资源路径 | 自由文本：路径 | 有 | 有 | 无 |
| MQTT | Broker（固定；主机、端口、传输方式和登录信息都在 Broker 上）、协议，Sparkplug B 还有组、边缘节点和设备 ID | 自由文本：主题，加上 JSON 负载中的数值路径，或 Sparkplug B 指标 | 由 Broker 送达 | 有（发布到命令主题，或用 Sparkplug B 命令） | 有（在 Broker 上监听） |
| Generic serial and TCP | 传输方式（TCP 客户端或 UDP 监听）、主机、端口，线路上的设备则是串行线路（固定）；然后是消息和校验和卡片 | 定型：取值方式、请求、消息过滤条件以及数值在消息中的位置 | 有；监听的点位保留现场设备发来的内容 | 有（写入消息；UDP 上没有） | 无 |
| Omron | 主机、协议（FINS 或 NJ/NX 点位（按名称））；FINS 下还有端口和 FINS 卡片（传输、网络、节点、单元、响应超时）；串行线路上为串行线路（固定）、单元 ID（Host Link 单元号）和响应超时 | 自由文本：存储区地址（FINS）或变量名（NJ/NX） | 有 | 有 | 有（对一台 PLC 的 FINS 探测，以及查找 NJ/NX 控制器的广播） |
| SCPI instruments | 传输方式（TCP（LXI 套接字）或 VISA）、主机和端口或 VISA 资源，线路上的设备则是串行线路（固定）；然后是“仪器”卡片（结束符、响应超时、写入确认、初始化命令） | 自由文本：查询，加上逗号分隔应答中的哪个值，以及写入命令 | 有 | 有（写入命令，通过仪器的错误队列确认） | 有（VISA 列出的仪器，以及对一台主机的 TCP 探测） |
| NI-DAQmx | 无：取而代之的是“NI-DAQmx 设备”卡片（设备名称，以及 NI-DAQmx 读出的产品） | 定型：物理通道和测量，以及测量的量程、接线、热电偶或计数器设置 | 是 | 是（数字输出线和电压输出） | 是（NI MAX 认识的每一台设备及其通道） |
| Fluke NetDAQ | 主机；然后是“仪器”卡片（基本通道、扫描速度） | 定型：点（模拟通道及其功能、数字线、继电器或累加器） | 是；仪器按设备点位中最短的间隔扫描 | 是（数字线和继电器，以及累加器清零） | 否 |
| SNMP | 主机、端口；再加“SNMP 代理”卡片（版本、community 或 SNMPv3 用户与安全设置、响应超时、重试次数） | 自由文本：OID，用数字或标准名称 | 有 | 有（代理接受的 SET；MIB 声明为只读的标准对象保持只读） | 有（遍历一个代理的标准子树） |
| File | 无：取而代之的是“文件夹和文件”卡片（文件夹路径、文件名或收件文件夹的模式、读取来源、文件格式），其后是“文件文本”和“写入”卡片 | 定型：点位读取的内容（一个值、整个文件或一项文件信息），对于值，还有列和行（CSV）、行及其中的字符（自由文本）或路径（JSON、XML） | 有 | 有（在允许写入的设备上：追加一行、替换整个文件或指定另一个文件） | 有（一个文件，设备的文件或输入的文件） |
| Database | 无：取而代之的是“数据库”卡片（数据库类型，然后是服务器、端口、实例名称和数据库名称、数据库文件，或数据源或连接字符串），之后是“登录”卡片（用户名和密码，SQL Server 还有 Windows 登录和加密） | 类型化：点位的读取方式（按表、值列和要读取的行选定的单元格，或自定义查询的查询文本） | 是 | 是（所读取的单元格，或自己的写入命令） | 是（设备数据库中的表） |

每个驱动还会把点位提供的**数据类型**列表收窄到它真正能编排的那些；确切的列表在驱动自己的页面上。表里写“固定 1 秒”的地方，驱动不理会配置的间隔，所以设备页面和点位页面对它隐藏“轮询间隔”字段。写“只读”的地方，“读写”字段只提供“只读”，写入字段从不出现。

## 每个驱动页面讲什么 {#what-every-driver-page-documents}

每个驱动页面都按同样的顺序走同样几节：“设备”卡片显示的那些连接字段，以及它们怎么拼出基础 URI；一个点位怎么寻址（那些定型字段或者那个自由文本记号，以及面板预览出来的那个只读总线地址）；提供哪些数据类型；驱动有设备发现时的设备发现；驱动接受写入时的写入；以及这个驱动的特别之处（凭据、证书、时序、工作站自己跑的一个网络服务器、配对）。

## 安装包没带的驱动 {#a-driver-the-package-does-not-carry}

Connector 从不列出、也从不提供正在运行的安装包没带的驱动。一份带着这类设备到来的配置（一份还原回来的备份、一份从别的机器带过来的配置）会把它们留下：只要那些设备还在，这个驱动就一直列在目录里和“驱动”文件夹下，它的说明写“本安装包不包含该驱动。”，而这个驱动的页面和它下面每一台设备都带着一条说着同样话的提示条。那些设备保持离线并保留各自的设置；它们可以被删掉，但不能被复制，这个驱动下面也不能新建设备或启动设备发现扫描。

一个安装包带着哪些驱动，是从 Connector 的驱动清单里读来的，而那份清单要等 Connector 启动之后才存在。在那之前每个驱动都算在场，所以目录在启动几秒之后才稳定下来，然后在这一次会话里就不再变，哪怕 Connector 又被停掉再启动一次也一样。

驱动的代码在应用运行期间只加载一次。把通信停掉再启动，是拿那同一次加载去重建正在跑的设备和驱动列表，这也正是让工作站的内存在一整天的反复启停里保持平坦的原因。由此带来的后果是：替换磁盘上驱动自己的文件，要等应用本身重启之后才生效。
