协议

S7(Step7)

qianmoQqianmoQ· 更新于 2026-10-01· 阅读 69 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

横幅

S7 驱动程序通过承载于 ISO-on-TCP(COTP)之上的 S7comm 协议与西门子 Simatic S7 控制器通信。它充分利用了 S7-300 和 S7-400 系列的高级特性——设备状态(RUN/STOP)事件、系统/用户诊断事件、报警、周期性(CYC)推送订阅以及 SZL/SSL 诊断——并为 S7-1200 和 S7-1500 系列提供基础的 PUT/GET 读写访问,这两个系列的固件并未开放相同的事件与诊断服务。S-200 与 S7-200 Smart 控制器同样可以访问,只需遵循下文所述的一小套连接与寻址约定。据报告,该驱动程序也可用于 VIPA 硬件——一种带有扩展内存、与 S7-300 兼容的西门子仿制产品。

大多数闭源 S7 协议栈,甚至包括最知名的开源实现 Snap7,都是围绕简单的请求/响应模式构建的。PLC4X 的 S7 驱动程序更进一步,让开放的、非西门子的应用程序也能访问异步的带时间戳数据,而否则这类数据只有借助西门子自身的生态系统才能获取——即 SOFTNET OPC-DA/OPC-UA、底层的 SAPI-S7 库,或 PCS7、Braumat、WinCC 等 DCS/SCADA 产品。

该驱动程序当前的稳定版本为 0.10.0(2022-10-04)。社区支持可通过 PLC4X 开发者邮件列表(dev@plc4x.apache.org)获取;提供 PLC4X 驱动程序商业支持的公司列于项目官网上。

支持的操作

名称值说明
readC、Go 和 Java。
writeC、Go 和 Java。
subscribeGo 和 Java。两个彼此独立的形式:按请求的间隔对普通标签进行周期性(CYC)推送,以及报警订阅(ALM 用于实时推送流,QUERY:ALARM_S / QUERY:ALARM_8 用于一次性获取当前已缓冲的内容)。两者都基于驱动在连接时探测的 S7Comm「UserData」服务;对于不响应该探测的设备——S7-1200/S7-1500 控制器并未实现 S7-300/S7-400 系列所具备的报警/事件子系统——订阅会以 UNSUPPORTED 被拒绝。C 驱动不提供订阅。
browseGo 和 Java,前提条件与 subscribe 相同的 UserData 服务。枚举连接设备上当前存在的静态内存区以及数据块(DB)——这是对可寻址内容的实时清单,而不是网络扫描。
discover仅 Java,并且仅当安装了可选的 pcap4j 运行时和系统 libpcap 时。发送 PROFINET DCP 广播并收集设备通告——这是网络发现 API,而非 browse;它用于发现设备,而不是枚举某个设备上的标签。

连接字符串

连接字符串的格式如下

s7://{ip-address}?{options}

SCHEMA 始终为 s7;cotp 是唯一的传输方式,因此被省略。ip address 用于指定 PLC 或其前端的 CP,options 是一个以 & 分隔的键/值参数列表,完整说明见下文。

s7://10.10.1.33?cotp.remote-rack=0&cotp.remote-slot=3&controller-type=S7_400
连接到西门子 LOGO 设备时,请在连接字符串中加入 ?controller-type=LOGO。西门子似乎只在这些设备上部分实现了该协议:如果不固定类型,一旦驱动尝试读取其通常用于自动检测所通信 S7 设备系列的 SZL 表,设备就会终止连接。

连接字符串选项

名称

类型

默认值

必填

描述

名称

Siemens S7 (Basic)

代码

s7

Maven 依赖

<dependency>
  <groupId>org.apache.plc4x</groupId>
  <artifactId>plc4j-driver-s7</artifactId>
  <version>1.0.0</version>
</dependency>

默认传输方式

cotp

支持的传输协议

  • cotp

配置选项:

pdu-size

整数 (INT)

1024

发送到远程 PLC 和从远程 PLC 接收的 S7 数据包的最大大小。

max-amq-caller

INT

8

PLC 可并行接受的最大未确认请求数。

max-amq-callee

INT(整数)

8

PLC4X 并行接受的未确认响应或请求的最大数量。

controller-type

STRING

ANY

跳过控制器类型检测,直接假设为给定的类型。

read-timeout-ms

INT

10000

单次 S7 请求/响应交换的最大等待时间(毫秒)。

ha-heartbeat-interval-ms

INT

4000

仅适用于 S7H 双路径:心跳间隔(毫秒)。每次心跳会对每个内部连接发送一次 ping,因此待机链路的中断将在 interval + ha-failover-timeout-ms 之内被检测到。数值越小检测越快,但产生的后台流量也越大。默认值为 4000(4 秒)。

ha-failover-timeout-ms

INT

2000

S7H 双路径专用:包装层在切换到备用路径之前,等待当前活跃内层操作完成的最长时间(单位:毫秒)。心跳机制中每次 tick 的 ping 超时也使用该值。数值越小,切换越快,但可能因瞬时慢响应而误触发切换。默认值为 2000(2 秒)。

传输配置选项:

cotp

cotp.local-rack

整型(INT)

1

客户端(PLC4X 设备)的机架号(Rack)值。

cotp.local-slot

INT

1

客户端(PLC4X 设备)的插槽值。

cotp.local-device-group

STRING

OTHERS

本地设备组。

cotp.remote-rack

INT

0

远程主 CPU(PLC)的机架号(Rack 值)。

cotp.remote-slot

整数 (INT)

0

远程主 CPU(PLC)的插槽值。

cotp.remote-device-group

STRING

PG_OR_PC

远程设备组。

cotp.local-tsap

INT

0

本地 TSAP(传输服务访问点)标识符。

cotp.remote-tsap

INT

0

远程 TSAP(传输服务访问点)标识符。

cotp.tpdu-size

INT

8192

用于数据传输的 COTP PDU 大小。有效值:128、256、512、1024、2048、4096、8192。

cotp.handshake-timeout-ms

整型(INT)

5000

COTP 握手的连接超时时间,单位为毫秒。

cotp.protocol-class

INT

0

COTP 协议类。最常使用的是 0 类(简单类,无流控)。

cotp.connect-timeout-ms

INT

5000

连接超时时间(毫秒)。

cotp.read-timeout-ms

INT

0

Socket 读取超时时间(毫秒)。0 表示不超时。

cotp.write-timeout-ms

INT

0

以毫秒为单位的套接字写入超时时间。0 表示不超时。

cotp.no-delay

BOOLEAN

true

启用 TCP_NODELAY(禁用 Nagle 算法)。

cotp.keep-alive

BOOLEAN

false

启用 SO_KEEPALIVE。

cotp.send-buffer-size

INT

81920

发送缓冲区大小(字节)。0 表示使用系统默认值。

cotp.receive-buffer-size

INT

81920

以字节为单位的接收缓冲区大小。0 表示使用系统默认值。

cotp.local-address

STRING

要绑定的本地地址(可选)。若未设置,则使用默认值。

cotp.local-port

INT

0

要绑定的本地端口(可选)。0 表示使用临时端口。

标签地址

寻址功能已在 C、Go 和 Java 中实现。各实现的具体支持情况请参见协议支持矩阵]。

通用格式

PLC4X 的 S7 驱动采用 TIA Portal 自身的地址表示法,因此通常可以直接从 TIA Portal 中复制地址。

一般来说,所有 S7 地址都具有以下格式:

%{Memory-Area}{start-address}[{selection}]:{Data-Type}

如果省略选择部分,则读取单个元素。方括号中的选择采用共享数组表示法——单个索引、闭区间范围,以及可选的数组声明下界。完整的形式列表以及本驱动所能表达的范围,请参阅数组寻址。

一般来说,地址分为两种类型:

Bit-Addresses  {Memory-Area-Code}{Start-Byte-Address}.{Bit-Offset}:BOOL[{Count}]
Byte-Addresses {Memory-Area-Code}{Start-Byte-Address}:{Data-Type-Code}[{count}]

位地址仅在使用数据类型 BOOL 时才使用。其数组表示法可以省略,此时默认使用 Count 为 1。Start-Byte-Address 和 Bit-Offset 都表示无符号整数值。

在访问 data block 存储区中的数据时,语法会稍微复杂一些:

DB{Data-Block-Number}.DB{Short-Data-Type-Code}{Start-Byte-Address}.{Bit-Offset}:BOOL[{Count}]
DB{Data-Block-Number}.DB{Short-Data-Type-Code}{Start-Byte-Address}:{Data-Type-Code}[{Count}]

在读取 STRING 数据类型时,目前会自动从 PLC 中读取 254 个字符。为了减少传输的数据量,STRING 类型声明语法经过扩展,允许声明一个更短的长度:

DB{Data-Block-Number}.DB{Short-Data-Type-Code}{Start-Byte-Address}:STRING({string-length})[{Count}]

上面的数据块形式带有一些多余的样板内容(中间的 .DB 以及 Short-Data-Type-Code),因此也接受一种更简短的语法,其处理方式与长形式完全相同:

DB{Data-Block-Number}:{Start-Byte-Address}.{Bit-Offset}:BOOL[{Count}]
DB{Data-Block-Number}:{Start-Byte-Address}:{Data-Type-Code}[{Count}]
DB{Data-Block-Number}:{Start-Byte-Address}:STRING({string-length})[{Count}]

存储区

S7 驱动当前支持访问以下存储区。

Code 列表示在上述通用地址语法中所使用的代码:

并非所有 S7 设备类型都支持全部相同的存储区,因此最后一列提供了有关给定存储区在哪些类型上受支持的更多信息。

代码名称说明支持的 PLC 类型
CCOUNTERSTODO: Document thisTODO: Document this
TTIMERSTODO: Document thisTODO: Document this
DDIRECT_PERIPHERAL_ACCESSTODO: Document thisTODO: Document this
IINPUTS输入(数字量和模拟量…… 通常模拟量输入只是具有一个起始地址偏移,以便与数字量输入区分开)全部
QOUTPUTS输出(数字量和模拟量…… 通常模拟量输出只是具有一个起始地址偏移,以便与数字量输出区分开)全部
MFLAGS_MARKERSTODO: Document thisTODO: Document this
DBDATA_BLOCKS包含用户自定义数据结构的存储区,通常通过整数形式的数据块编号进行访问。请注意,数据块的地址格式稍微复杂一些。全部
DBIINSTANCE_DATA_BLOCKSTODO: Document thisTODO: Document this
LDLOCAL_DATATODO: Document thisTODO: Document this

数据类型

代码短代码名称描述位大小支持的 PLC 类型
位串(在 PLC4X 中都将被解释为布尔值序列)
BOOLX位单个布尔值1全部
BYTEB字节8 个布尔值的数组1全部
WORDW字16 个布尔值的数组2全部
DWORDD双字32 个布尔值的数组4全部
LWORDX长字64 个布尔值的数组8S7_1500
整数值
SINTB短整数8 位整数(有符号)1S7_1200、S7_1500
USINTB无符号短整数8 位整数(无符号)1S7_1200、S7_1500
INTW整数16 位整数(有符号)2全部
UINTW无符号整数16 位整数(无符号)2S7_1200、S7_1500
DINTD双精度整数32 位整数(有符号)4全部
UDINTD无符号双精度整数32 位整数(无符号)4S7_1200、S7_1500
LINTX长整数64 位整数(有符号)8S7_1500
ULINTX无符号长整数64 位整数(无符号)8S7_1500
浮点数值
REALD实数32 位 IEEE 754 全精度浮点值(有符号)4全部
LREALX长实数64 位 IEEE 754 双精度浮点值(有符号)8S7_1200、S7_1500
字符值
CHARB字符8 位字符1全部
WCHARX双字节字符16 位字符值2S7_1200、S7_1500
STRINGX字符串2 + n 字节的字符串1全部
WSTRINGX双字节字符串由 16 位字符组成的字符串,2 + n 字节1S7_1200、S7_1500
时间值
S5TIMEXS5 时间S5 时间(类似时长)2S7_300、S7_400、S7_1500
TIMEX时间时间(类似时长)(分钟、秒、毫秒)4全部
LTIMEX长时间长时间(类似时长)(分钟、秒、毫秒、微秒、纳秒)8S7_1500
DATEX日期日期2全部
TIME_OF_DAYX一天中的时间时间(类似下午 4:40)4全部
DATE_AND_TIMEX日期和时间日期和时间(类似 03.05.2020 下午 4:40)8S7_300、S7_400、S7_1500

示例

地址含义
%DB1.DBX0.0:BOOL数据块 1、字节 0、位 0 处的单个位
%DB10.DBW20:INT数据块 10、字节 20 处的 16 位有符号整数
%I0.0:BOOL输入字节 0、位 0 处的单个位
%MD100:DINT标志/存储器字节 100 处的 32 位有符号整数
%DB1.DBB0[0..9]:BYTE从数据块 1、字节 0 开始的 10 个字节,以列表形式返回
%DB5:10:INT数据块 5、字节 10 处的 16 位有符号整数,使用更简短的数据块语法
%DB1.DBB0[0..15]:RAW_BYTE_ARRAY从数据块 1、字节 0 开始的 16 个原始字节,解码为 BYTE,也接受 RAW_BYTE_ARRAY 作为 BYTE 的别名
%DB1.DB0:STRING(80)数据块 1、字节 0 处长度最多为 80 个字符的 STRING——比默认的 254 个字符更短
%DB1.DB0:STRING数据块 1、字节 0 处的 STRING,按其默认最大长度读取
ALM订阅实时报警推送源(详见协议细节)
QUERY:ALARM_S一次性读取 PLC 当前缓冲的报警,ALARM_S 布局

表 1. 示例

注意事项与提示

尤其是在模拟量通道的输入、输出地址方面,起始地址是可配置的,因此并不总是从相同的地址开始。要了解这些端口对应的地址,请在 TIA Portal 中查看您 PLC 的 device setting。

devsettings

请特别注意这部分:

iosettings

在上图中可以看到,该设备有 8 个数字量输入(DI 8)、2 个模拟量输入(AI 2_1)以及 6 个数字量输出(DQ 6)。

数字量输入和输出的起始地址直接从 0 开始。而模拟量输入从地址 64 开始。

每个数字量输入和输出都可以通过单个位地址(起始地址加位偏移)进行寻址,也可以在不提供位偏移的情况下,从给定起始地址开始读取完整的一个字节,从而成块读取。

协议细节

西门子 S7-200 / S7-200 Smart

S7-200 以及较新的 S7-200 Smart 属于低端控制器,其行为与 S7-300/400/1200/1500 系列略有不同。它们仍然可以通过 S7 驱动程序经由以太网(ISO-on-TCP)访问,但需要一些特定的连接设置,并且对其变量存储器的寻址采用了不同的约定。

本节汇总了社区验证可行的方法(参见 PLC4X 问题 devlive-community/knowforge#1925 和 devlive-community/knowforge#2641)。

连接

连接 S7-200(Smart)时,有两点需要注意:

  1. 通过传入 controller-type=S7_200 来禁用自动控制器类型检测。S7-200 不会响应驱动程序通常用于自动检测 CPU 系列的 SZL/SSL 标识请求,因此——与上文提到的 LOGO 设备一样——必须显式提供类型。
  2. 显式提供 TSAP(传输服务访问点)值。S7-200(Smart)要求本地和远程 TSAP 均为 0x0200,即十进制的 512。使用 cotp.local-tsap=512 和 cotp.remote-tsap=512 进行设置;非零 TSAP 将覆盖基于机架/插槽的寻址方式。

因此,一个最简可用的连接串如下所示:

s7://192.168.12.100?cotp.local-tsap=512&cotp.remote-tsap=512&controller-type=S7_200

cotp.remote-rack=0 和 cotp.remote-slot=0 是默认值,因此是可选的,但为了清晰起见可以加上:

s7://192.168.12.100?cotp.remote-rack=0&cotp.remote-slot=0&cotp.local-tsap=512&cotp.remote-tsap=512&controller-type=S7_200

使用此配置,已确认对 S7-200 Smart 的读取和写入均正常工作。

寻址 V(变量)存储区

S7-200 将其用户变量保存在 V(变量)存储区中,在西门子工具(STEP 7-Micro/WIN)中的寻址方式例如为 VW310、VD732 或 V350.0。S7 驱动程序没有专门的 V 存储区代码。

不过在 S7-200 上,V 区域只是 Data Block 1(DB1)的别名。因此,任何 V 地址都可以改用 DB1 来读写,所用的正是上文所述的普通数据块语法:

S7-200 记法PLC4X 地址含义
VB100%DB1.DBB100:BYTEV100 处的单个字节
VW310%DB1.DBW310:INTV310 处的 16 位字
VD732%DB1.DBD732:UDINTV732 处的 32 位双字
V350.0%DB1.DBX350.0:BOOL单个位 V350.0

较短的数据块记法同样有效,例如用 %DB1:732:UDINT 表示 VD732。

M(标志位/存储器位)存储区仍按常规方式寻址,例如 %M10.0:BOOL 或 %MW20:INT。

注意未来版本可能会增加对专门的 V 存储区代码的原生支持。在此之前,请使用上面所示的 DB1 别名。

参与通信过程的角色

PLC 编程总体而言可谓潘多拉之盒!

这里我们假设你在开发周期中使用标准的技术功能/库,因此,指出参与驱动程序与 PLC 之间这一对话的角色,以及它们如何影响通信周期,就显得尤为重要。

参与通信的不同角色如图 1 所示。

  1. PLC (AS),控制器。AS 是 PCS7 中使用的参考。
  2. App,你的应用程序。
  3. PLC4X,S7 驱动程序的实现。
  4. OS,PLC 操作系统。
  5. PCS7,代表 PLC 中使用的技术功能。PCS7 指的是西门子 DCS 库。
  6. S7App,在 PLC 上运行的应用程序。
  7. CP,通信 CP 取决于你的架构和需求:S7-300 使用 CP 343-1,S7-400 使用 CP 443-1。

S7 读/写

S7 事件订阅

注意onSubscribe 恰好接受两种标签:作为 EVENT 订阅的 S7AlarmTag(ALM、QUERY:ALARM_S 或 QUERY:ALARM_8),或作为 CYCLIC 订阅的普通 S7Tag;其他任何内容都会被拒绝并返回 INVALID_ADDRESS。本节曾经记录过的 MODE、SYS 和 USR 订阅建立在 addEventField() / S7ModeEvent / S7SysEvent / S7UserEvent API 之上,而该 API 已不再存在于源码树中;这些小节已在本页面的源文件中被注释掉,而非删除。目前实际可用的是 ALM 和周期性(CYC)订阅。

S7 驱动程序允许订阅 PLC 中产生的异步事件。

此类事件由 S7-300、S7-400、G120C-PN、S120-PN 控制器以及 VIPA 设备生成。遗憾的是,对于 S7-1200 和 S7-1500 系列,此功能已被取代。

Note有关 S7-300、400 与 S7-1200 及 S7-1500 之间兼容性的完整列表,您可以查看西门子提供的文档 [1]。

这些服务具有以下优势:

  1. 报告控制架构中支持该功能的 CPU 及其他组件(CP、IM、DI 等)的状态。
  2. 在发生变更时传送数值。
  3. 将数值与所发送的事件相关联。
  4. 更好地处理关联数值的时间戳。

根据生成方式的不同,消息被分为两组:

  1. SCAN:所有由系统生成或在 Step7(TIA Portal)中预先设定的事件。所配置信号的状态变更由操作系统按特定周期(500 ms、100 ms 或 16 ms)执行。
  2. ALARM:由用户程序使用报警块(ALARM_S、ALARM_SQ、NOTIFY、ALARM、ALARM_8)生成的事件。除用户程序外,这些事件还可以由 PCS7 或 Braumat 等工艺功能生成。

与事件关联的数据以 HashMap 表示,以便于将其传输到基于 JMS、MQTT 或其他消息传递技术等标准的其他应用中。

SCAN 类型事件的时间戳在计算机中生成。而在 ALARM 类型的消息中,时间戳由 PLC 生成。因此,计算机与 PLC 之间的日期和时间同步极其重要。

与事件关联的数值可以有不同的表示形式,因此其解释方式必须在 PLC 中的应用程序编程与您的应用程序编程时协商确定。

对于每种事件类型,特定的 <String, T> 类型字段将被安排在 Map 中。这些字段将针对每种事件类型分别进行说明。

为了最大化利用与事件关联的数据字段,建议在 PLC 中使用区内指针系统和 ANY 类型指针,同时遵循关于时间戳管理的建议 [2]。

在用户应用层面 App,您可以使用 PLC4X API 订阅 SCAN 或 ALARM 类型的事件,根据需求选择以下任意字段:

  1. MODE:控制器运行状态的变更,即 STOP 与 RUN 之间的切换(反之亦然)。
  2. SYS:系统事件,与控制器的内部事件或先前为其指示而参数化的事件相关联。
  3. USR:由用户编程且记录在内部诊断缓冲区中的事件。
  4. ALM:由用户程序生成的报警事件,ALARM_S、ALARM_8、NOTIFY。

在接下来的章节中,我们将更详细地描述每个字段的功能。

SCAN 事件

Note本节过去描述的 MODE、SYS 和 USR 订阅在当前驱动中不可用:它们所基于的 S7ModeEvent、S7SysEvent、S7UserEvent 和 addEventField() API 已不再存在于源码树中。这些小节在本页源文件中以注释块的形式保留,而非直接删除,以便在 API 恢复后能够还原协议层面的描述,或针对当前 API 重新编写。驱动今天实现的是下文所述的 ALM 订阅,以及后文介绍的循环(CYC)订阅。

ALARM 事件

订阅 ALM 类型事件
Note这是本节最初描述的四类事件中,当前驱动真正实现的一类:它在 S7AlarmTag 上作为真实的 PlcSubscriptionRequest 存在(此处所示的实时推送通道使用 ALM;对当前缓冲内容的一次性获取则使用 QUERY:ALARM_S / QUERY:ALARM_8,参见 S7CotpConnection.onSubscribe)。下图说明了协议层面的消息流程。请注意,较早的 S7AlarmEvent 类并不属于当前 API——订阅交付的是标准的 PlcSubscriptionEvent。

订阅的注册流程与迄今为止所采用的典型流程相同(01)(02)(03)(04)(05)。从那一刻起,你就可以开始异步接收报警事件了。

根据应用程序的不同,你可以请求 PLC(AS) 报警缓冲区中当前处于活动状态的报警,这样便可以准备一个接收缓冲区,或者根据控制器中的活动事件建立起正确的状态机状态。

你必须考虑到,发出请求(06)时,根据应用程序的复杂程度以及 PLC (AS) 的容量,可能存储着从几条到数百条不等的报警。

在这种场景下,PLC4X 驱动会与 OS 保持对话,按顺序接收(07)(08)(09)(10)(11)(12)(13)(14)存储在控制器上的报警,随后将其传递给用户应用程序 App(15)。

订阅过程结束后,系统开始接收所产生的事件,例如高精度时间信号(16)(17)(18)(19)或由用户应用程序生成的事件(20)(21)(22)。

这一简单的事件序列被基于 PCS7 的过程应用程序用于处理报警、事件,以及对分布式控制系统(DCS)中几乎所有事件的日志记录。

驱动的另一项重要特性是能够识别由 PLC(AS) 生成的报警。在(23)(24)(25)中,S7App 应用程序生成了一个报警/事件,需要用户确认后才能继续执行特定例程。用户应用程序 App 使用相应的报警标识符生成确认(27)(28),由 OS 负责作出回执(29)(30),并异步生成事件以更新 App 中的状态机(31)(32)。

在应用程序 S7App 的循环执行过程中,它会等待报警(26)的确认,以便继续执行某些特定的例程。

TODO: 字段说明

字段类型说明
TYPE
TIMESTAMP
TIMESTAMP_GOING
TIMESTAMP_COMING
ASSOCIATED_VALUES
MAP
EVENT_ID
EVENT_STATE
STATE
ACKSTATE_GOING
ACKSTATE_COMING
EVENT_GOING
EVENT_COMING
EVENT_LAST_CHANGE
SIG
SIG_[1…​8]
SIG_STATE
SIG_[1…​8]_STATE
SIG_DATA
SIG_[1…​8]_DATA
SIG_[1…​8]_DATA_GOING
SIG_[1…​8]_DATA_CO
SIG_[1..8]_DATA_STATUS
SIG_[1…​8]_DATA_SIZE
SIG_[1…​8]_DATA_LENGTH

TODO: 示例代码

周期订阅(CYC)

周期订阅允许以被动模式采集数据,即数据由 PLC 以周期性、同步的方式发送。与上述 MODE/SYS/USR 事件类别不同,当前驱动程序已实现该方式:使用订阅类型 CYCLIC 和请求的 Duration 订阅一个普通的 S7Tag,驱动程序会为你挑选匹配的硬件时基和系数。

数据传输有三种时基:

  1. B01SEC:时基 0.1 秒(100 毫秒)。
  2. B1SEC:时基 1.0 秒。
  3. B10SEC:时基 10 秒。

驱动程序倾向于选择系数仍能容纳于一个字节的最粗时基,因为从 V3.2 起的 S7-300 固件会直接拒绝 B01SEC(100 毫秒)的订阅请求(errCode=0xD804),只接受 B1SEC 和 B10SEC;亚秒级请求仍会回退到 B01SEC,因为它是唯一能够表达这类请求的时基,但会被该固件拒绝。

SZL 系统状态列表

系统状态列表可访问 PLC 的运行数据,例如内存空间、运行状态、控制开关的状态,以及扩展卡或分布式外围设备、PROFIBUS 或 PROFINET 的诊断数据。

这些是用于判定 PLC 所提供数据质量的基础数据。

通过与 PLC 建立连接,你可以确定其运行状态,从而判断所采集数据的质量,以及所部署的应用程序能够做什么、不能做什么——最终,这正是 Siemens CP 执行的过程。

Note为什么是 SZL 而不是 SSL?嗯,这是一种创作上的自由。德语手册翻译成西班牙语时使用 SZL,而德语翻译成英语时使用 SSL。源代码和文档都采用这一缩写,以保持文本的一致性。

由于数据结构种类繁多(基本上每种诊断类型对应一种),因此决定将它们作为字节数组返回,由开发人员根据自身需求自行实现解析器。

作为首次使用系统状态列表的入门方案,可以使用 org.apache.plc4x.java.s7.readwrite.utils.StaticHelper.SZL 中提供的字节数组到 JSON 记法的解析器。

Note请参阅 XXX 文档以获取每个 SZL 的详细说明,因为如前所述,一切都取决于你所安装的硬件。
Note驱动本身会在内部读取 SZL——用于在连接时自动检测控制器类型,以及为 browse 提供支持——其途径是 S7SzlService/S7CotpConnection,而不是通过用户可寻址的 PlcTag。下面演练中使用的 SZL_ID=…​;INDEX=…​ 标签地址不符合当前 S7PlcTagHandler 所接受的任何模式(它不以其他所有 S7 地址都要求的 % 开头),因此使用该字符串调用 addTagAddress 会针对当前驱动抛出 PlcInvalidTagException。SZL_ID/INDEX 编码本身以及响应的 JSON 形态仍然准确,予以保留以供参考;仅此处展示的"将其作为普通 PlcTag 读取"这一具体机制已经过时。

SZL 请求的表示法

对 PLC 的 SZL 的访问以读取请求的方式进行,其中 PLCTag 由 "SZL_ID" 和 "INDEX" 两个字段构成。

  1. SZL_ID:分配给 SZL 列表的编号。根据请求是完整请求、部分请求还是仅请求表头,SZL_ID 会有所不同。为便于使用,其表示始终采用十六进制,格式为 0xxyID。
  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1|
  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
  \__________/\__________/\____________________/
   Module      Number of   Number of the partial
   class       the partial list
               list
               extract
  1. 部分列表编号:你要读取的部分 SZL 列表的编号。
  2. 部分列表摘录编号:定义你想提取该部分列表中的哪一部分,其取值因列表而异。
  3. 模块类型:对部分列表的请求取决于所使用的硬件。通常,IM(通讯模块)、FM(功能模块)和 CP(外围设备控制器)都拥有各自的诊断系统,可通过 SZL_ID/INDEX 这个 PlcTag 进行查询。
  Module Class:
  +--------------+-----------------+
  | Module class | Coding (Binary) |
  +--------------|-----------------+
  |     CPU      |      0000       |
  +--------------|-----------------+
  |     IM       |      0100       |
  +--------------|-----------------+
  |     FM       |      1000       |
  +--------------|-----------------+
  |     CP       |      1100       |
  +--------------|-----------------+
  1. INDEX:所需子列表的编号。为便于使用,该表示形式始终采用十六进制,格式为 0xhhhh。

mi_001

public static void main(String[] args) throws Exception {
    System.setProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "trace");

    System.out.println("******************************************************************************************");
    System.out.println("Before using, take a look at:");
    System.out.println("System Software for S7-300/400.\r\nSystem and Standard Functions - Volume 1/2");
    System.out.println("Document: A5E02789976-01");
    System.out.println("Chapter 34 System Status Lists (SSL).");
    System.out.println("URL: https://cache.industry.siemens.com/dl/files/604/44240604/att_67003/v1/s7sfc_en-EN.pdf");
    System.out.println("******************************************************************************************");

    try (PlcConnection connection  new DefaultPlcDriverManager().getConnection("s7://10.10.1.33?cotp.remote-rack=0&cotp.remote-slot=3&controller-type=S7_400")) { //(01)

        final PlcReadRequest.Builder readrequest  connection.readRequestBuilder(); //(02)

        readrequest.addTagAddress("MySZL", "SZL_ID=16#0012;INDEX=16#0000"); //(03)

        final PlcReadRequest rr  readrequest.build(); //(04)
        final PlcReadResponse szlresponse  rr.execute().get(); //(05)

        if (szlresponse.getResponseCode("MySZL") = PlcResponseCode.OK){ //(06)

            Collection<Byte>  data  szlresponse.getAllBytes("MySZL"); //(07)
            byte[] dbytes  ArrayUtils.toPrimitive(data.toArray(new Byte[data.size()])); //(08)

            SZL szl  SZL.valueOf(0x0012); //(09)
            ByteBuf wb  wrappedBuffer(dbytes); //(10)
            StringBuilder sb =  szl.execute(wb); //(11)
            System.out.println(sb.toString());  //(12)

        } else if (szlresponse.getResponseCode("MySZL") = PlcResponseCode.NOT_FOUND){ //(13)
                System.out.println("SZL is not supported.");
        }

            Thread.sleep(2000);
            System.out.println("Bye...");

      }
    }

SZL 列表的请求遵循与变量读取相同的模式,即每次请求对应一个响应;与过程变量请求可以在一次请求中分组多个变量不同,SZL 请求必须严格遵循一次请求对应一次应答的规则。

与其他请求一样,先建立连接 URL(01),然后创建请求构造器实例(02)。将相关的 PLCTag 添加到诊断列表中(每个请求一个),在本例中为 SZL_ID=0x0012 和 INDEX=0x0000(03),借此可以获取 PLC 的标识与固件信息。

在(04)和(05)中,我们准备并执行对 PLC 的请求。如果获得了有效响应(06),就可以对获取的数据流进行处理,正如前所述,该数据流是一个字节数组,分别在(07)和(08)中获取。

正如我们在支持库中提到的,我们有一个 "SZL" 对象(一个枚举),它允许我们根据数值索引 SLZ_ID(09)选择合适的解析器。在(10)中,我们将数据包装为一个 ByteBuf 类型的对象(来自 Netty 库),以便通过 "execute" 方法(11)传递给 "szl" 实例。

在处理数据缓冲区时,我们需要在(12)中获得一个包含 JSON 表示的 StringBuilder。

{"RECORDS":[{"AUSBG2":0,"AUSBG1":61,"BGTYP":130,"INDEX":1,"MIFB":"6ES7 417-4XT05-0AB0 "},{"AUSBG2":0,"AUSBG1":2,"BGTYP":130,"INDEX":6,"MIFB":"6ES7 417-4XT05-0AB0 "},{"AUSBG2":768,"AUSBG1":22021,"BGTYP":0,"INDEX":7,"MIFB":"                    "},{"AUSBG2":3,"AUSBG1":22021,"BGTYP":0,"INDEX":129,"MIFB":"Boot Loader         "}],"LENGTHDR":28,"SZL-ID":17,"INDEX":0,"N_DR":4}

如上所述,对 SZL 枚举的解析并不完整,因此缺失的信息必须从返回的字段中获取。有关更多详细信息,您可以参阅 []。

在无法处理请求的情况下,将在 (13) 处进行检测,以便采取必要的措施。

下图以 JSON 格式表示相关信息。

从获取到的 StringBuilder 中,您可以使用自己选择的 JSON 处理器来访问各个字段。

模块类别SZL-ID已实现
SZL 列表16#xy00已在 S7-400 上测试,JSON
模块标识16#xy11已在 S7-400 上测试,JSON
CPU 特性16#xy12已在 S7-400 上测试,JSON
用户存储区16#xy13已在 S7-400 上测试,JSON
系统区域16#xy14已在 S7-400 上测试,JSON
块类型16#xy15已在 S7-400 上测试,JSON
中断状态16#xy22已在 S7-400 上测试,JSON
过程映像分区与 OB 之间的分配16#xy25已在 S7-400 上测试,JSON
通信状态数据16#xy32已在 S7-400 上测试,JSON
H CPU 组信息16#xy71
模块 LED 的状态16#xy74已在 S7-400 上测试,JSON
H 系统中切换的 DP 从站16#xy75
模块状态信息16#xy91已在 S7-400 上测试,JSON
机架 / 站状态信息16#xy92已在 S7-400 上测试,JSON
机架 / 站状态信息16#xy94已在 S7-400 上测试,JSON
扩展 DP 主站系统 / PROFINET IO 系统信息16#xy95已在 S7-400 上测试,JSON
模块状态信息,PROFINET IO 与 PROFIBUS DP16#xy96已在 S7-400 上测试,JSON
换刀装置信息(PROFINET IO)16#xy9C已在 S7-400 上测试,JSON
CPU 的诊断缓冲区16#xyA0已在 S7-400 上测试,JSON
模块诊断信息(数据记录 0)16#xyB1已在 S7-400 上测试,JSON
模块诊断信息(数据记录 1),地理寻址16#xyB2已在 S7-400 上测试,JSON
模块诊断信息(数据记录 1),本地寻址16#xyB3已在 S7-400 上测试,JSON
DP 从站的诊断数据16#xyB4已在 S7-400 上测试,JSON

更多信息

  1. https://snap7.sourceforge.net/
  2. https://support.industry.siemens.com/cs/document/13649203/simatic-net-pc-software-s7-programming-interface?dti=0&dl=en&lc=es-ES
  3. https://support.industry.siemens.com/cs/document/109797648/simatic-comparison-list-for-s7-300-s7-400-s7-1200-s7-1500?dti=0&lc=en-WW
  4. https://support.industry.siemens.com/cs/mdm/109746537?c=98956468747&lc=es-DO
  5. https://support.industry.siemens.com/cs/document/15166942/writing-user-specific-information-to-the-diagnostic-buffer-of-a-cpu-(sfc-52)?dti=0&lc=en-ES
  6. https://support.industry.siemens.com/cs/document/24013249/how-do-you-display-alarm_s-or-alarm_d-messages-with-process-values-(so-called-associated-values)-on-a-wincc-flexible-operator-panel-?dti=0&lc=en-WW
  7. https://support.industry.siemens.com/cs/document/109481157/comunicaci%C3%B3n-entre-paneles-de-operador-simatic-hmi-y-convertidores-de-frecuencia-sinamics-g120-para-el-manejo-y-la-visualizaci%C3%B3n-de-avisos-de-fallo-y-de-advertencia-(enlace-directo-sin-controlador)?dti=0&lc=es-WW
  8. https://support.industry.siemens.com/cs/document/97550333/sinamics-g-s-hmi-direct-access?dti=0&lc=en-WW
  9. https://support.industry.siemens.com/cs/document/21402122/technology-cpus-technology-template-error-messages-?dti=0&lc=en-WW
  10. https://support.industry.siemens.com/cs/document/77467239/transforming-warning-and-error-messages-of-a-sinamics-drive-with-the-aid-of-the-xml-parser-and-integrating-them-into-a-step-7-hmi-project?dti=0&lc=en-WW
  11. https://support.industry.siemens.com/cs/document/24037531/%C2%BFqu%C3%A9-pasos-de-configuraci%C3%B3n-hay-que-realizar-en-el-simotion-scout-y-el-wincc-flexible-para-que-se-muestren-los-avisos-alarm_s-y-las-alarmas-tecnol%C3%B3gicas-dentro-del-wincc-flexible-runtime-?dti=0&lc=es-ES

评论

登录后参与评论

正在加载评论…