Database

把工厂系统保存在数据库表中的值(SQL Server、PostgreSQL、MySQL 和 MariaDB、SQLite,或通过 ODBC 访问的任何数据库)读成点位,并在点位要求的地方写回:“数据库”和“登录”卡片,按表、列和行读取单元格或执行自定义查询的点位,点位写入的两种方式,为每一列提供一个点位的扫描,四个完整示例,以及驱动不做的事。

以 Markdown 查看

Database 驱动读取工厂系统保存在数据库表中的值:MES 保存的生产订单,ERP 保存的配方或设定值,另一个测试系统记录的结果。每个点位读取一个表中的一个值,它的值和其他任何点位的值一样送达各处:Logic、仪表画面,以及 Process 测试台的运行记录。在点位要求时,驱动也会写回:写入点位所读取的单元格,或通过点位自己的命令写入。

SQL Server、PostgreSQL、MySQL 和 MariaDB 以及 SQLite 无需在计算机上安装任何东西即可连接。其他数据库(Oracle、Access、Firebird 等)通过它们自己的 ODBC 驱动连接,该驱动的 64 位版本必须安装在计算机上。

读取是主要用途,路径很短:设备说明其数据库在哪里以及工作站如何登录,扫描为其各表的每一列提供一个点位,每个点位新建时都是只读。属于写入的内容,只有在点位的访问方式允许工作站写入之后才会出现在该点位上。

此驱动的一台设备就是一个数据库:同一服务器上的两个数据库就是两台设备。设备位于驱动之下,可以归入文件夹,驱动 → 文件夹 → 设备 → 点位,和任何没有串行线路或 Broker 的驱动一样。

驱动页面

标题下面的一行写着“每台设备读取一个数据库。添加设备,填写其数据库的位置和工作站的登录方式,然后扫描它,把其中的列添加为点位。”有配置 Connector 的权限时,页面上有此驱动自己的扫描范围卡片,其中是扫描要读取其数据库的设备(参见设备发现)。下面是和任何驱动一样的设备表(参见设备表),用标题右侧的添加设备增加设备;表为空时显示“还没有设备。”驱动的工具栏上有发现设备,在扫描范围卡片填写完整之前是灰色的。此驱动列在文件和数据库之下,位于 File 驱动旁边。

设备

此驱动的设备没有“连接”卡片:取而代之的是数据库卡片,除了没有登录的 SQLite 之外,其后还有登录卡片。“设备”卡片的轮询间隔(ms)默认为 1000,表示点位读取数据库的频率,和任何驱动一样,每个点位都可以覆盖它。

新设备是一台没有服务器的 SQL Server:它显示“尚未填写服务器”,其页面显示“在这台设备说明其数据库的位置之前,工作站不会连接它,因此暂时不读取任何数据,也没有错误可显示。在下面的‘数据库’卡片里填写(服务器和数据库名称、文件或数据源),工作站就会连接。”在说明位置之前不读取任何内容。标题中显示的基础 URI 是运行时地址,从不包含用户或密码:SQL Server 实例为 database://sqlserver?server=mes-sql&instance=SQLEXPRESS&database=MES,SQLite 文件为 database://sqlite?file=C%3A%5CData%5Crecipes.db,ODBC 数据源为 database://odbc?source=ERP。

“数据库”卡片

字段 显示条件 含义 默认值
数据库类型 始终 SQL Server、PostgreSQL、MySQL / MariaDB、SQLite 或 其他(ODBC),后者显示“使用此计算机上为该数据库安装的 64 位 ODBC 驱动(Oracle、Access、Firebird 等)。” SQL Server
服务器 SQL Server、PostgreSQL、MySQL / MariaDB 在 SQL Server 上:“主机名或 IP 地址。SERVER\INSTANCE 和 SERVER,PORT 会拆分到各自的框中。”在另外两种上:“主机名或 IP 地址。冒号后写的端口会移到‘端口’框。” 空
端口 同上 留空即数据库自己的端口,空框中会显示该端口:1433、5432 或 3306。SQL Server 实例没有端口时,框中不显示任何内容,由服务器的 SQL Server Browser 告知端口。 空
实例名称 SQL Server “默认实例留空。没有端口的命名实例通过 SQL Server Browser 查找。”最多 16 个字母、数字、_ 和 $,以字母或 _ 开头。 空
数据库名称 SQL Server、PostgreSQL、MySQL / MariaDB 服务器上存放这些表的数据库,最多 128 个字符。 空
数据库文件 SQLite “SQLite 文件的完整路径,使用运行工作站的账户的 Windows 权限访问。除非有点位写入,否则以只读方式打开。”框中以 C:\Data\recipes.db 作为提示。从不创建该文件。 空
数据源或连接字符串 其他(ODBC) “Windows‘ODBC 数据源(64 位)’中的数据源名称,或类似 Driver=;Dbq=C:\Data\plant.accdb 的连接字符串。密码填在密码框里,绝不写进连接字符串。” 空

所选类型不读取的字段不会显示,并保留其值以备将来读取。选择另一种类型时,仍停留在旧数据库自身端口的端口会被清空,这样新数据库就在它自己的端口上连接。“服务器”框会把数据库工具写在一起的内容拆开:

在“服务器”中输入 结果
mes-sql\SQLEXPRESS(SQL Server) 服务器 mes-sql,实例名称 SQLEXPRESS
mes-sql,1433(SQL Server) 服务器 mes-sql,端口 1433
10.0.0.5:5433 服务器 10.0.0.5,端口 5433

在卡片说明数据库的位置之前,设备按原样保存并等待,灰色圆点,不读取任何内容,也不显示错误:

数据库类型 等待 设备显示
SQL Server、PostgreSQL、MySQL / MariaDB 服务器,然后是数据库名称 “尚未填写服务器”,然后是“尚未填写数据库名称”
SQLite 文件 “尚未填写数据库文件”
其他(ODBC) 数据源或连接字符串 “尚未填写数据源”

卡片无法接受的设置会显示在卡片下方,修正之前设备不会保存:

您输入 卡片显示
含协议前缀、路径或空格的服务器,例如 http://mes-sql “服务器只填主机名或 IP 地址:不含协议前缀、路径或空格。与之一起写的 SQL Server 实例和端口会移到各自的框中。”
含空格或 _、$ 以外符号的实例名称 “实例名称最多 16 个字符,可用字母、数字、下划线和美元符号。”
超过 128 个字符的数据库名称 “数据库名称最多 128 个字符,不含控制字符。”
不是完整路径的文件,例如 recipes.db “数据库文件是完整路径:驱动器、文件夹和文件(C:\Data\recipes.db),或网络共享(\server\data\recipes.db)。”
文件夹,或含 *、?、<、> 或引号的路径 “请填写数据库文件本身的路径,而不是文件夹,不含 * ? | < > 或引号。”
含方括号、大括号、圆括号、逗号、分号或 ? * ! @ \ 之一的数据源名称 卡片要求填写该数据源在 ODBC 数据源中的名称,或连接字符串。
不是 key=value 对的连接字符串,例如留着未闭合的大括号 “连接字符串是以分号分隔的 key=value 对;含分号的值要放在大括号中。”
含 PWD= 或 Password= 的连接字符串 “请把密码从连接字符串中拿出,填到密码框里:连接字符串会显示并写入诊断日志,而密码框会加以保护。”

保存遵循同样的规则,拒绝时动态栏会说明:“设备‘MES’有驱动无法使用的数据库设置。请打开它并修正面板标出的字段。”

“登录”卡片

除 SQLite 之外的每种数据库都有登录卡片,其中是工作站登录所用的用户。

字段 显示条件 含义 默认值
使用工作站的 Windows 账户登录 SQL Server 打开:“使用运行工作站的 Windows 账户登录 SQL Server;不保存用户或密码。”关闭:“使用数据库用户及其密码登录 SQL Server。” 关闭
用户名 用用户登录的服务器,以及可选的 ODBC 数据库用户。 空
密码 同上 用户的密码,和驱动的其他凭据一样受保护地保存:不再显示,不写入地址或诊断日志,也不返回给智能体。 空
加密 SQL Server 加密,校验证书:“连接经过加密,服务器证书会与此计算机信任的证书进行校验。”加密,接受任何证书:“连接经过加密,并接受任何证书,这是使用自有证书的工厂服务器所需要的。不校验服务器的身份。”不加密:“值和命令以明文传输。仅用于不提供加密的旧服务器。” 加密,校验证书

PostgreSQL 和 MySQL 没有“加密”字段:只要服务器提供,它们的连接就会加密。使用自有证书的 SQL Server(工厂服务器常常如此)会以数据库自己的话拒绝连接,说证书链由不受信任的机构颁发:这种服务器需要选择加密,接受任何证书。

在字段下方,卡片说明应当申请什么样的用户:“请向数据库管理员申请一个只具备工作站所需权限的用户:读取权限,以及仅对其点位修改的表的写入权限。”工作站以该用户能做的一切去读写另一个系统的数据,因此这个用户才是工作站能修改内容的真正边界。每次写入都会记入诊断日志,和任何驱动一样。

用用户登录的服务器尚未填写用户时,会改为显示“请填写工作站登录所用的用户。在此之前,工作站不会连接这台设备。”这不是拒绝:设备会保存,在填写用户之前,它的错误会说明尚未填写数据库用户。

在线、等待和离线

情况 设备及其点位的行为
“数据库”卡片没有说明数据库的位置 设备等待,灰色圆点,不读取任何内容,也没有错误(见上文)。
用用户登录的服务器,且未填写用户 工作站不连接该设备;其错误说明尚未填写数据库用户。
服务器没有响应、拒绝登录,或 SQLite 文件不存在 设备离线,并附上数据库自己给出的原因,工作站在可以时立即连接。连接最多等待 10 s。
连接断开(服务器重启、网络中断) 设备离线,然后重新连接。
数据库拒绝的语句,或 10 s 后仍在运行的语句 该点位读取失败,并附上数据库自己的话;设备继续读取其他点位。
点位读取还没有任何行的表的最新一行 该点位等待,没有错误,在写入第一行之前,设备的健康状态不把它算在内:设备是否在线由其他点位说明。点位读取过之后被清空的表不属于这种等待:点位保留上一次读数,和任何驱动一样,当它比轮询间隔加 10 s 还旧时就算作失败。

每台设备都有自己的连接,在连接时打开,从不共享,也不放入连接池,因此服务器断开的连接不会再被使用。

准备服务器

在常见的安装中,这三种网络数据库出厂时对其他计算机是关闭的。下面每一项设置都由服务器的管理员在服务器上完成;工作站不会改动其中任何一项。

数据库 把工作站挡在外面的原因 修改位置
SQL Server TCP/IP 关闭(SQL Server Express 和 Developer 出厂即如此) SQL Server Configuration Manager > SQL Server Network Configuration > Protocols for 实例:启用 TCP/IP,然后在 SQL Server Services 中重启 SQL Server(该实例)
SQL Server 命名实例在自己选择的端口上侦听 TCP/IP > IP Addresses > IPAll:清空 TCP Dynamic Ports,在 TCP Port 中填入端口,然后重启;或让设备的“端口”框留空并填写实例名称
SQL Server 没有端口的命名实例要靠 SQL Server Browser 定位,而它已停止或被阻挡(错误 26) SQL Server Services:启动 SQL Server Browser,Start Mode 设为 Automatic;在服务器防火墙中允许 UDP 1434
PostgreSQL listen_addresses 是默认值 localhost postgresql.conf:listen_addresses = '*',然后重启 PostgreSQL
PostgreSQL pg_hba.conf 中没有一行放行本工作站的地址(SQLSTATE 28000) pg_hba.conf:为该数据库、该用户和本工作站的地址加一行 host,方法为 scram-sha-256(以 MD5 保存的密码用 md5),然后执行 SELECT pg_reload_conf();
MySQL、MariaDB bind-address 是 127.0.0.1(许多软件包都这样设置),或 skip-networking 已开启 配置文件的 [mysqld] 段:bind-address = 0.0.0.0,删除 skip-networking,然后重启
MySQL、MariaDB 没有对应本工作站地址的账户(错误 1130) 用 CREATE USER 为本工作站地址上的该用户建账户,并用 GRANT 授予点位所需的权限

无论哪种情况,都还需要在服务器所在计算机的防火墙中允许数据库端口。服务器以其中一种方式答复时,设备页面会代替数据库的英文错误,说明是哪项设置,并给出这些步骤和此设备的值(端口、实例、服务器看到的本工作站地址、pg_hba.conf 的那一行和 MySQL 账户,各带一个复制按钮)。设备一旦连接,或服务器以别的方式答复,此提示就会自行消失。日志和代理读到的是同样的步骤。

点位寻址

点位如何读取

此驱动的点位没有自己的地址框:它的信号源卡片询问它如何读取。

读取内容 点位显示的内容 其字段
表和列 一个单元格:表中某一行的值列。 表、值列、要读取的行以及行的字段
自定义查询 自己的 SELECT 返回的第一行第一列。 查询文本

新点位按键读取表和列,类型为 Double。提供的类型有 Boolean、Int32、Int64、Float、Double、String 和 DateTime。读取单元格时,整数点位会拒绝带小数部分的值而不是将其舍入(写入则相反,见写入),文本只有在它是数字时才按数字读取。每个点位新建时都是只读;写入增加的内容见写入。

表和列

字段 显示条件 含义 默认值
表 表和列 “一个名称,或架构加名称(dbo.Orders)。含空格或大写字母的名称要放在引号或方括号中,例如 [Order Lines]。” 空
值列 表和列 其单元格就是点位值的那一列。 空
要读取的行 表和列 按键:“键列中为该键值的那一行。同一表、同一行的点位在一次查询中一起读取。”最新一行:“日期列值最大的那一行:日期时间,或只增不减的数字。同一表、同一行的点位在一次查询中一起读取。” 按键
键列 按键 选定行的列,例如 OrderNo。 空
键值 按键 要读取的那一行中键列的值,例如 4711,以文本输入:数据库按该列的值来读取它。 空
日期列 最新一行 其最大值所在的行即最新一行的列,例如 updated_at。 空

名称按数据库读取的方式读取:

写法 读取方式
Orders 普通名称,按数据库读取任何普通名称的方式读取:PostgreSQL 为小写,Oracle 为大写。
"Order Lines"、[Order Lines] 名称本身,不论数据库自己接受哪种引号。
dbo.Orders 架构和表:引号外的点把两者分开。

驱动会把名称的每一部分放进其数据库接受的引号中,因此名称从不会作为文本拼接进语句。字段无法工作的点位不会保存,其页面会说明缺少什么:

您留空或输入 点位页面显示
没有表 “请填写值所在的表。”
由三部分组成的表,或未闭合的引号 “表是一个名称,或架构加名称(dbo.Orders);含空格的名称要放在引号或方括号中。每部分最多 128 个字符。”
没有值列 “请填写值所在的列。”
由两部分组成的值列 “值列是单个名称;含空格的名称要放在引号或方括号中。”
按键,没有键列 “请填写用来选定行的键列。”
按键,没有键值 “请填写键值:要读取的那一行中键列的值。”
最新一行,没有日期列 “请填写日期列,其最大值所在的行即最新的一行。”

只读的源地址(总线)一行显示驱动收到的内容:按键选行为 row?table=dbo.ProductionOrders&column=Quantity&key=OrderNo&equals=4711,最新一行为 newest?table=recipe_setpoints&column=oven_temperature&by=updated_at。

自定义查询

字段 含义 默认值
查询文本 “一个只读的 SELECT;值为第一行第一列。@now 是工作站的日期和时间。”以 WITH 开头且只读的查询也可以接受。 空

查询按数据库读取的方式读取:引号中的文本、引号中的名称或注释中的内容不算语句中的词。不只读取的查询会在输入处被拒绝:

您输入 点位页面显示
什么都没有 “请填写查询:一个 SELECT,其第一行第一列就是值。”
不是 SELECT 的语句,例如 UPDATE 或 DELETE “查询以 SELECT 或 WITH 开头。要写入,请让点位的访问方式允许写入,并使用写入命令。”
修改数据库的 SELECT:SELECT ... INTO、FOR UPDATE,或含 INSERT、UPDATE、EXEC 的 SELECT “该查询会修改数据库(INSERT、UPDATE、SELECT INTO、FOR UPDATE、EXEC 等)。查询只能读取。”
两条语句 “查询包含多条语句。请只保留一个 SELECT。”
未闭合的引号、括号或注释 “查询中的引号、括号或注释没有闭合。”
@now 以外的值,例如 @order “查询只接受 @now,即工作站的日期和时间。其他值请直接写进文本。”

查询点位的总线地址是 query?sql= 后接经过百分号编码的查询。

读取

读取的点位 读取方式
按键 在键列等于键值的那一行中读取其列;键值作为参数传给数据库。
最新一行 在日期列取该列最大值的那一行中读取其列(WHERE ... = (SELECT MAX(...) FROM ...)),这种写法所有数据库和 ODBC 都以同样方式读取;两行并列时读取第一行。
同一表、同一行的多个点位 每轮用一次查询读取它们所有的列,以免为每个点位都询问工厂的数据库。如果数据库拒绝这次查询(表中没有的列),就单独读取该点位自己的列,此后该行逐列读取:错误的列只影响它自己的点位。
自定义查询 按原样执行查询,@now 作为参数传入。
数据库返回 点位
点位可读取类型的值 读取它。
空单元格(NULL) 读取失败。
没有行含该键值,或不止一行 读取失败:一个点位只读取一行。
还没有任何行的表的最新一行 等待,没有错误。
不返回任何行的查询 读取失败。
点位类型无法读取的值(Int32 点位中的文本、整数点位中的小数部分) 读取失败,并附上原因。

读取失败时点位保留上一次读数,和任何驱动一样,当它比轮询间隔加 10 s 还旧时就算作失败。每次读取都会询问数据库:其他程序做的修改在下一次读取时才能看到,而不是修改的那一刻。

写入

只有在点位的访问为读写或只写之后,点位才会写入。此时它的信号源卡片会增加写入的方式:

字段 显示条件 含义 默认值
写入方式 点位写入时 修改所读取的单元格:“修改此点位所读取的单元格,只改一行。仍在等待的较新值会取代较旧的值。”执行其写入命令:“执行下面的写入命令。每次写入都算数:仍在等待的写入不会因为较新的写入而被丢弃。”读取自定义查询的点位没有可修改的单元格,只提供执行其写入命令。 修改所读取的单元格
写入命令 执行其写入命令 “带 WHERE 的 UPDATE、INSERT 或存储过程调用。@value 是写入的值,@now 是工作站的日期和时间;值总是作为参数传入,从不拼接进文本。”空框中以 INSERT INTO results (result, recorded_at) VALUES (@value, @now) 作为提示。 空

执行写入命令的只写点位不读取任何内容,因此它的信号源卡片只有写入。

写入 执行方式
修改所读取的单元格 一条 UPDATE,在点位那一行把值列设为 @value,放在事务中执行,除非恰好改动一行,否则撤销:没有行含有的键值,或两行都含有的键值,都不写入任何内容并说明原因。和任何设定值一样,仍在等待的较新值会取代较旧的值。
执行其写入命令 每次写入执行一次命令,值作为 @value,工作站的日期和时间作为 @now。每次写入都算数:两次 INSERT 就是两行,仍在等待的写入不会因为较新的写入而被丢弃。存储过程用 EXEC、CALL 或 ODBC 的 {call ...} 调用。
整数点位上带小数部分的值 被舍入,而不是被拒绝:向没有量程换算和校准的整数点位(Int32 或 Int64)写入带小数部分的值,会在到达数据库之前四舍五入到最近的整数,一半时远离零(2.5 写入 3,-2.5 写入 -3)。拒绝小数部分是读取单元格的方式,不是写入值的方式。
答复 完成,或以数据库自己的话拒绝:用户缺少的权限、该行违反的约束、该列不接受的值。

驱动无法执行的命令会在点位页面被拒绝:

您输入 点位页面显示
什么都没有 “请填写写入命令:包含 @value 的 UPDATE、INSERT 或存储过程调用。”
以其他词开头的命令,例如 DELETE “写入命令以 UPDATE、INSERT、EXEC 或 CALL 开头。”
两条语句 “写入命令包含多条语句。请只保留一条,或调用存储过程。”
未闭合的引号、括号或注释 “写入命令中的引号、括号或注释没有闭合。”
没有 @value “请把 @value 放在写入值的位置:值总是作为参数传入,从不拼接进文本。”
@value 和 @now 以外的值,例如 @line “写入命令只接受 @value(写入的值)和 @now(工作站的日期和时间)。”
不带 WHERE 的 UPDATE “不带 WHERE 的 UPDATE 会修改表中的每一行。请加上选定该行的 WHERE。”

以 @@ 开头的名称(SQL Server 的函数)和 EXEC 的参数名(@speed = @value)不是值,按原样保留。保存遵循同样的规则,拒绝点位时动态栏会说明:“点位‘Order quantity’没有说明其值在数据库中的位置,或含有驱动拒绝的查询或写入命令。请打开它并修正点位面板标出的字段。”

总线地址会加上写入:单元格为 row?table=recipes&column=setpoint&key=code&equals=R-100&write=cell,执行命令的只写点位为 none?write=command&command= 后接命令。

设备发现

“扫描范围”卡片

有配置 Connector 的权限时,驱动页面上有扫描范围卡片,其下一行写着“以设备的方式登录,为其各表的每一列提供一个点位,取最新一行或键最小的那一行。”

字段 含义 默认值
要扫描的设备 按名称选择此驱动的一台设备。数据库只能通过保存其登录信息的设备来扫描;设备中仍在等待保存的修改会先保存。 按名称排序的第一台设备
表 “留空表示所有表,也可以写名称或用 * 代表任意字符的模式,例如 Recipe*。” 空

没有设备的驱动只显示“数据库通过保存其登录信息的设备来扫描。请添加此驱动的设备,并说明其数据库的位置。”范围中仍缺少的内容会以红色显示在卡片下方,在范围完整之前发现设备一直是灰色的:

范围 卡片显示
没有说明数据库位置的设备,或有驱动无法使用的设置的设备 “设备‘Recipes’尚未说明其数据库的位置,或有驱动无法使用的设置。请先完成它的‘数据库’卡片。”
含架构、引号、方括号或分号的模式,例如 dbo.Recipe* “‘dbo.Recipe*’不是表名或模式。请写一个名称,或用 * 代表任意字符的模式,不带架构或引号。”
已不存在的设备 “所选的扫描设备已不存在。请另选一台要扫描的设备。”

要扫描的设备有无法保存的修改时,扫描不会开始:“设备发现没有开始,因为要扫描的设备的修改无法保存。”

扫描提供的内容

扫描以设备的方式登录,读取数据库自己保存的表和视图(不含系统表)及其列的清单,并说明正在读取哪个表,例如“正在读取 recipes 的列…”。它提供一个候选项,即设备本身,标记为已经配置过:其卡片列出设备尚无点位读取的列,并已勾选,添加所选点位位于打开之前,把勾选的列以只读方式添加到设备。

表 其候选点位
有日期时间列 每列一个,按第一个这样的列读取最新一行。
没有 除键之外每列一个,读取主键(没有主键的表则为第一列)值最小的那一行:要读取另一行,请修改点位的键值。
没有,也没有任何行 不提供。
任何点位类型都无法读取的列(二进制数据、几何数据) 不提供,并在结束扫描的那一行中计数。

点位以其表和列命名(recipes.oven_temperature),类型取自列的类型,每一个都是只读。一次扫描最多读取 100 个表和 500 个值;在此截断的扫描会显示“Recipes 的扫描提前停止。一次扫描最多读取 100 个表和 500 个值:请指定表名或模式以查看其余部分。”扫描的其他行为见设备发现。

设备自己的页面不经过驱动页面也能做同样的事:点位卡片标题栏里的发现点位像设备那样登录,按设备保存的样子扫描它的数据库,只列出它还没有点位的列(见发现一台设备的点位)。

示例:来自 SQL Server 的生产订单

MES 把生产订单保存在 SQL Server 中 MES 数据库的 dbo.ProductionOrders 表里,每个订单号一行:

  1. 在驱动页面点添加设备,命名为 MES。在数据库卡片上保留 SQL Server,服务器填写 mes-sql(命名实例则为 mes-sql\SQLEXPRESS),端口留空,数据库名称填写 MES。
  2. 在登录卡片上,用户名填写 station_reader 及其密码,或打开使用工作站的 Windows 账户登录。对于使用自有证书的工厂服务器,选择加密,接受任何证书。
  3. 添加点位 Order quantity,Int32:表 dbo.ProductionOrders,值列 Quantity,要读取的行 按键,键列 OrderNo,键值 4711。其总线地址为 row?table=dbo.ProductionOrders&column=Quantity&key=OrderNo&equals=4711。
  4. 添加点位 Product,String,同一表同一行,值列 ProductCode:两个点位在一次查询中读取。

使用工具时:

device_upsert name=MES driver=Database databaseKind=SqlServer host="mes-sql\SQLEXPRESS" databaseName=MES username=station_reader password=<password> databaseEncryption=TrustServerCertificate
tag_upsert device=MES name="Order quantity" opcUaType=Int32 databaseTable=dbo.ProductionOrders address=Quantity databaseRow=Key databaseKeyColumn=OrderNo databaseKeyValue=4711
tag_upsert device=MES name=Product opcUaType=String databaseTable=dbo.ProductionOrders address=ProductCode databaseRow=Key databaseKeyColumn=OrderNo databaseKeyValue=4711

示例:来自 PostgreSQL 的配方设定值

配方系统每次设定值改变时都会在 recipe_setpoints 中添加一行,并在 updated_at 列中记录日期:

  1. 点添加设备,命名为 Recipes,数据库类型 PostgreSQL,服务器 recipes-db,端口留空(PostgreSQL 的 5432),数据库名称 recipes,然后在登录卡片上填写用户名和密码。
  2. 添加点位 Oven setpoint,Double:表 recipe_setpoints,值列 oven_temperature,要读取的行 最新一行,日期列 updated_at。

每个新行会在点位的下一次读取时读到。PostgreSQL 按小写读取普通名称,因此用大写字母创建的列(例如 OvenTemp)要放在引号中写成 "OvenTemp"。使用工具时:

device_upsert name=Recipes driver=Database databaseKind=PostgreSql host=recipes-db databaseName=recipes username=station password=<password>
tag_upsert device=Recipes name="Oven setpoint" opcUaType=Double databaseTable=recipe_setpoints address=oven_temperature databaseRow=Newest databaseDateColumn=updated_at

示例:用 INSERT 写入的结果行

质量系统希望每个测量过的零件在其 test_results 表中有一行:

  1. 在该数据库的设备上,添加点位 Result,Double,访问设为只写。
  2. 写入方式选执行其写入命令,并在写入命令中写入添加该行的 INSERT INTO test_results (result, recorded_at) VALUES (@value, @now)。

Logic 写入 Result 的每个值都成为单独的一行,旁边是工作站的日期和时间;快速连续的写入都会按顺序保留,不会因为较新的写入而丢弃。读取单元格的读写点位则会在每次写入时修改它的那一行。使用工具时:

tag_upsert device=Quality name=Result opcUaType=Double accessType=WriteOnly databaseWriteMode=Command databaseCommand="INSERT INTO test_results (result, recorded_at) VALUES (@value, @now)"

示例:通过 ODBC 访问 Access 和 Oracle

数据库 此计算机上需要 设备上的设置
Microsoft Access Microsoft 的 Access Database Engine,64 位 数据库类型 其他(ODBC),数据源或连接字符串 Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=C:\Data\plant.accdb,无用户
Oracle Oracle 的 64 位 ODBC 驱动,以及用它在 ODBC 数据源(64 位)中创建的数据源 ERP 数据库类型 其他(ODBC),数据源或连接字符串 ERP,在登录卡片上填写用户名和密码

当设备指定的数据源或驱动只对 32 位程序存在(32 位 Office 的 Access、在“ODBC 数据源(32 位)”中创建的数据源),或这台计算机上根本没有时,只要设备处于启用状态且未能连接,设备面板就会连同设备给出的名称说明是哪一种情况,并给出完整的说明。设备的错误用英文说明同样的内容,driver_capabilities 也在 Database 驱动的 prerequisite(perDevice 为 true)中说明同样的内容:

部分 内容
缺少什么 该数据源或驱动的 64 位 ODBC 驱动:Ganter Lab 是 64 位程序,只能看到 64 位 ODBC 驱动以及用它们创建的数据源,并且不能包含其他厂商的驱动
从哪里获取 数据库厂商;对于 Access,是 Microsoft 的页面“Download and install Microsoft 365 Access Runtime”,其运行时带有 Access Database Engine
选择哪个 64 位版本(对于 Access,即您所用语言的 64 位下载按钮),不要选 32 位版本
如何安装 以管理员身份运行;然后,如果设备指定的是数据源名称,请在“ODBC 数据源(64 位)”中用相同的名称和相同的数据库创建它
常见问题 在装有 Office 的计算机上安装 Access 时:Microsoft 的页面说,安装的 Access Runtime 与已安装的 Office 相匹配,并且与通过 Windows Installer 安装的 Office 不兼容;Microsoft 关于在 Office 64 位和 32 位版本之间选择的页面说,要先卸载一个版本,再安装另一个版本
之后 在下一次连接尝试时,设备以现有配置连接,无需重启 Ganter Lab

提示的最后列出这台计算机上的 64 位 ODBC 驱动,名称即 Driver={...} 中所写的名称。64 位一侧已有、却仍然失败的数据源或驱动,显示驱动程序管理器自己的错误。

通过 ODBC 时,普通名称按数据库读取的方式读取(Oracle 上为大写),引号中的名称按原样读取;日期和时间精确到整秒发送,这是每个 ODBC 驱动都接受的最细精度。使用工具时:

device_upsert name="Plant book" driver=Database databaseKind=Odbc databaseOdbc="Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=C:\Data\plant.accdb"
device_upsert name=ERP driver=Database databaseKind=Odbc databaseOdbc=ERP username=STATION password=<password>

智能体工具

driver_capabilities 在 database 下描述此驱动:简单路径,每种数据库及其字段和自己的端口,加密选项,点位的两种读取方式和两种写入方式,值只能以 @value 或 @now 进入语句的规则,类型,超时,关于数据库用户的建议,设备发现,以及四个完整示例。device_upsert driver=Database 接受 databaseKind(默认的 SqlServer、PostgreSql、MySql、Sqlite 或 Odbc),服务器接受 host(SQL Server 的 server\INSTANCE 或 server,port 会被拆开)、port、databaseName,SQL Server 还接受 databaseInstance、databaseWindowsSignIn 和 databaseEncryption(Verified、TrustServerCertificate 或 Off);SQLite 接受 databaseFile,ODBC 接受 databaseOdbc;以及 username 和从不返回的 password。它返回的设备带有 database,其中有地址以及设备是否仍在等待其用户。tag_upsert 以 address 接受值列,并接受 databaseSource(Fields 或 Query)、databaseTable、databaseRow(Key 或 Newest)、databaseKeyColumn、databaseKeyValue、databaseDateColumn、databaseQuery,在 accessType 写入时还接受 databaseWriteMode(Cell 或 Command)和 databaseCommand;除非 opcUaType 另有指定,新点位为只读的 Double。device_discover driver=Database 接受此驱动已配置设备的名称 databaseDevice,以及可选的 databaseTables(表名或带 * 的模式);设备缺少的点位用 tag_upsert 添加。connector_browse 返回每台设备的 databaseKind。其他工具见智能体工具。

值得了解的限制

  • 驱动读写其点位的值,每个点位一个值。它不会把工作站的运行记录写入数据库:每次运行一行、包含序列号、判定和测量值,这不是此驱动写入的内容。
  • 产品不附带任何 ODBC 驱动。Oracle、Access、Firebird 以及直接连接的四种以外的任何数据库,都需要在计算机上安装其自己的 64 位 ODBC 驱动;32 位的驱动无法识别。
  • 设备不保存任何 Windows 密码:登录 SQL Server 的 Windows 登录,以及网络共享上的 SQLite 文件,都使用运行工作站的账户,因此数据库或共享必须允许该账户访问。
  • 查询只能读取。修改数据库的是写入,而写入只发生在访问方式允许写入的点位上。
  • 值从不进入语句的文本:写入的值总是参数 @value,工作站的日期和时间是 @now,键值也是参数。命名任何其他值的语句都会被拒绝。
  • 单元格写入恰好修改一行;UPDATE 命令需要它的 WHERE。
  • 每次读取都会询问数据库:其他程序做的修改在下一次读取时看到,同一行有许多点位的数据库每轮只为它们全部询问一次。
  • 不读取二进制列。