西门子PLC协议-S7COMM 2020-11-20 程序之旅,记录 暂无评论 1305 次阅读 ## 西门子PLC协议-S7COMM [TOC] ### 简述 前段事件对接西门子设备,是一台盾构机控制PLC(programmable logic controllers)设备,目的是为了获取盾构机中运行的数据状态,有必要是可以通过数据状态来发送预警推送。这里简单的介绍S7COMM协议和他的通讯方法,可以结合附页中的wireshark抓的包来学习。 ### 认识S7 S7是一个基于TCP/IP的应用层协议,不能的单纯的使用Socket来进行通讯。以下是网络模型: | **OSI layer** | **Protocol** | | | ------------- | ------------------ | --------------------- | | 7 | Application Layer | S7 communication | | 6 | Presentation Layer | S7 communication | | 5 | Session Layer | S7 communication | | 4 | Transport Layer | ISO-on-TCP (RFC 1006) | | 3 | Network Layer | IP | | 2 | Data Link Layer | Ethernet | | 1 | Physical Layer | Ethernet | #### 连接过程 1、连接PLC 端口 102 2、连接ISO层 3、建立S7通信 #### PDU 主要的协议数据内容在PDU(Protocol Data Unit)中,S7 PDU由三个部分组成: * Header:长度信息,pdu相关和消息类型常量 * Parameters:根据消息头,内容和结构都有所不同 * Data:数据内容 ### 消息头 消息头一般时10-12字节,可能还会携带两个额外的错误码字节 ![S7HeaderStructure](http://gmiru.com/images/s7proto/s7header.png) * protocol ID(1byte): 协议参量,通常时 0x32 * MSG Type(1byte): 消息类型 * 0x01:工作请求(Job Request),主要是由服务器请求,写/读内存,开启/停止设备,配置会话 * 0x02:确认(Ack),主要是由设备请求,不携带数据 * 0x03:响应数据(Ack-Data),响应0x01的请求 * 0x07:自定义数据(Userdata),扩展协议类型 * Reserved(2bytes):保留字,0x0000 * PDU Ref(2bytes):响应序号,可以递增,设备复制回复,用于响应请求内容,小端 * Parameter Length(2bytes):大端(低位优先),参数长度 * Data Length(2bytes):大端,数据区域长度 * (Error Class)(1byte):错误类,只会出现在响应参数后边 * (Error code)(1byte):错误码,只会出现在响应参数后边 ### 消息参数(Parameter ) Parameter 数据参数内容大致相同,不同的是请求项中的内容 * Function Code(1byte):0x04读,0x05写 * Item Count(1byte):请求结构的数量 * Request Item:请求数据项 ### 数据内容 数据内容格式根据寻址方式来改变,不同的寻址方式有不同的结构内容,结构如下: * Function Code(1byte):0x04读,0x05写 * Item Count(1byte):请求结构的数量 * Request Item:请求数据项 寻址方式有以下三种方式: * any-type:这是默认的寻址模式,用于查询任意变量。为每个寻址变量指定了所有三个参数(area、address、type)。 * db-type:特殊的DB区域值 * symbolic-addressing:特殊标志地址 这里简单只介绍`any-type`方式 #### any-type 以下是请求和数据项(**Data Item** ) ![s7-any-type-items](https://mufeng-blog.oss-cn-beijing.aliyuncs.com/worker/20201109091837.png) Request Item * Specification Type(1byte):0x12 * Length(1byte):剩下项的长度 * Syntax ID(1byte):决定寻址方式,0x10表示any-type * Variable Type(1byte):数据类型(REAL, BIT, BYTE, WORD, DWORD, COUNTER,Timer) * Count(2bytes):可以使用单个项结构选择类似变量的整个数组。这些变量必须具有相同的类型,并且在内存中必须是连续的,而count字段决定了这个数组的大小。对于单个变量的读或写,它被设置为1。 * DB Number(2bytes): * Area(1byte):内存区域常量,可以在**附页**里查询到 * Address(3bytes):地址,例如 DBX40.3 计算 40 \* 8 + 3 = 323 十六进制:0x000143 * 响应的Data Item数据项: * Error Code(1byte):错误码 * Variable Type and Count(1byte 2byte):变量类型和计算,与Request Item一样 * Data:`len(variable) * count` > 小编但是使用过Netty直接发起S7协议请求,但是失败了,如果有能实现的可以下边评论,一起讨论。 ### 协议对接 我这里对接是直接使用一个大佬的开源项目, **s7connector** https://github.com/s7connector/s7connector 简单的使用方法在gay里面也有说明 ```java s7Connector.read(DaveArea.DB, areaNumber, bytes, offset); ``` 参数说明: - 参数一:读取方式,一般默认是DB区域块 - 参数二:区域块编号 - 参数三:区域数据类型大小,int 2字节,real 4字节 - 参数四:区域偏移量 举例子: ``` # DB40_DBD72.0 s7Connector.read(DaveArea.DB, 40, 4, 72); ``` ### 附件 [建立连接例子](https://github.com/gymgit/s7-pcaps/blob/master/snap7_s300_setupCommunication.pcapng) [读取例子](https://github.com/gymgit/s7-pcaps/blob/master/snap7_s300_readVar.pcapng) 打赏: 微信, 支付宝 标签: none 本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。