1. 协议概述

欧姆龙(Omron)是来自日本的知名电子和自控设备制造商,其中、小型PLC在国内市场有较高的占有率,有CJ、CM等系列。PLC可以支持Fins、Host link等协议进行通信。

支持以太网的欧姆龙PLC CPU、以太网通信模块根据型号的不同,一般都会支持FINS(Factory Interface Network Service)协议,一些模块也会支持EtherNet/IP协议。Omron fins协议缺省TCP/UDP端口号为9600。Fins协议封装在TCP/UDP之上,需要注意的是基于TCP的Fins数据包和基于UDP的包在头部上差异较大。协议的具体构造可以参考欧姆龙官方文档。

FINS协议实现了OMRON PLC与上位机以太网通信。Fins基于TCP/UDP的报文的概览如下:

123456789

Fins over TCP+-----------------------------------------------------------+| Fins/TCP Header | Fins over UDP(optional) |+-----------------------------------------------------------+ / \ / Fins over UDP \ +---------------------------------------+ | Fins/UDP Header | Command Data | +---------------------------------------+

由上图可知,Fins/TCP实际上是将Fins/UDP报文作为其负载,在其前面加了一个Fins/TCP报头。需要注意的是,Fins/TCP报文中负载即Fins/UDP部分不一定会出现,它可以只有一个简单的Fins/TCP报头。

因此我们先介绍Fins/UDP报文的组成,然后再介绍Fins/TCP结构。

2. 协议详解

2.1 Fins over UDP

基于UDP的Fins协议的结构相对简单,整体结构由报头和数据两部分组成,如下所示:

123456

Fins over UDP+--------------------------+| Fins/UDP Header |+--------------------------+| Command Data(opitonal) |+--------------------------+

其中报头部分为必要组成部分,为固定长度12个字节,数据部分非必现。

2.1.1 Fins/UDP Header

报头部分由11个定长字段组合而成,前面10个字段分别简称为:ICF、RSV、GCT、DNA、DA1、DA2、SNA、SA1、SA2、SID,如下所示:

1234567891011121314151617181920212223242526

0 1 2 6 7+---------+-----------+----------+---------------------+| Gateway | Data Type | Reserved | Response setting |+------------------------------------------------------+| Reserved |+------------------------------------------------------+| Gateway Counts |+------------------------------------------------------+| Destination Network Address |+------------------------------------------------------+| Destination Node Number |+------------------------------------------------------+| Destination Unit Addres |+------------------------------------------------------+| Source Network Address |+------------------------------------------------------+| Source Node Number |+------------------------------------------------------+| Source Unit Addres |+------------------------------------------------------+| Service Id |+------------------------------------------------------+| Command |+ +| Code(2B) |+------------------------------------------------------+

上述11个字段中,除最后一个Command Code字段为2个字节外,其余所有字段均只占1个字节。

2.1.2 ICF字段

第一个字段被称为ICF字段(即Information control filed,信息控制字段),1个字节,由4个子字段组成,分述如下:

1… …. = Gateway bit,是否使用网关,0x01表示使用;

.1.. …. = Data Type bit,数据类型比特位,0x01表示为响应,0x00表示命令;

..0. …. = Reserved bit,第一个保留比特位,默认置0;

…0 …. = Reserved bit,第二个保留比特位,默认置0;

…. 0… = Reserved bit,第三个保留比特位,默认置0;

…. .0.. = Reserved bit,第四个保留比特位,默认置0;

…. ..0. = Reserved bit,第五个保留比特位,默认置0;

…. …1 = Response setting bit,第一个保留比特位响应标志为,0x01表示非必需回应,0x00表示必须进行回应。

2.1.3 RSV字段

第二个字段被称为RSV(即Reserved,保留字段),1个字节,置0x00。

2.1.4 GCT字段

第三个字段被称为GCT(即Gateway count ,网关计数),1个字节,置为0x02。

2.1.5 DNA字段

第四个字段被称为DNA(即Destination network adrress,目标网络地址),1个字节,取值如下:

00:表示本地网络;

0x01~0x7F:表示远程网络。

2.1.6 DA1字段

第五个字段被称为DA1(即Destination node number,目标节点编号),1个字节,取值如下:

0x01~0x3E: SYSMAC LINK网络中的节点号;

0x01~0x7E: YSMAC NET网络中的节点号;

0xFF: 广播传输。

Omron的官方手册中,该字段只能取上述值,然而网上的实际抓包发现会有其它值出现,被wireshark标记为unknown。

2.1.7 DA2字段

第六个字段被称为DA2(即Destination unit address,目标单元地址),1个字节,取值如下:

0x00:PC(CPU);

0xFE: SYSMAC NET Link Unit or SYSMAC LINK Unit connected to network;

0x10~0x1F:CPU总线单元 ,其值等于10 + 单元号(前端面板中配置的单元号)。

Omron的官方手册中,该字段只能取上述值,然而网上的实际抓包发现会有其它值出现,被wireshark标记为unknown。

2.1.8 SNA字段

第七个字段被称为SNA(即Source network address,源网络地址),1个字节,取值及含义同DNA字段。

2.1.9 SA1字段

第八个字段被称为SA1(即Source node number,源节点编号),1个字节,取值及含义同DA1字段。

2.1.10 SA2字段

第九个字段被称为SA2(即Source unit addess,源单元地址),1个字节,取值及含义同DA2字段。

2.1.11 SID字段

第十个字段被称为SID(即Service ID,服务ID**),1个字节,取值0x00~0xFF,产生会话的进程的唯一标识。

2.1.12 Command Code字段

这个字段占2个字节,其取值由第一个字节表示的大分类和第二个字节表示的子分类复合而成,取值及其含义如下表:

Command Code英文释义中文释义

1st Byte

2nd Byte

0x01

0x01

MEMORY AREA READ

内存区域读取

0x02

MEMORY AREA WRITE

内存区域写入

0x03

MEMORY AREA FILL

内存区域填充

0x04

MULTIPLE MEMORY AREAREAD

多内存区域读取

0x05

MEMORY AREA TRANSFER

内存区域传输

0x02

0x01

PARAMETER AREA READ

参数区域读取

0x02

PARAMETER AREA WRITE

参数区域写入

0x03

PARAMETER AREA CLEAR

参数区域清除

0x20

DATA LINK TABLE READ

数据链表读取

0x21

DATA LINK TABLE WRITE

内存区域传输

0x03

0x04

PROGRAM AREA PROTECT

程序区保护

0x05

PROGRAM AREA PROTECT CLEAR

程序区保护清除

0x06

PROGRAM AREA READ

程序区读取

0x07

PROGRAM AREA WRITE

程序区写入

0x08

PROGRAM AREA CLEAR

程序区清除

0x04

0x01

RUN

执行

0x02

STOP

停止

0x03

RESET

重置

0x05

0x01

CONTROLLER DATA READ

控制器数据读取

0x02

CONNECTION DATA READ

连接数据读取

0x06

0x01

CONTROLLER STATUSREAD

控制器状态读取

0x02

NETWORK STATUS READ

网络状态读取

0x03

DATA LINK STATUS READ

数据连接状态读取

0x20

CYCLE TIME READ

循环次数读取

0x07

0x01

CLOCK READ

时钟读取

0x02

CLOCK WRITE

时钟写入

0x08

0x01

LOOP-BACK TEST/INTERNODE ECHO TEST

环路测试/内部节点响应测试

0x02

BROADCAST TESTRESULTS READ

广播测试/结果读取

0x03

BROADCAST TEST DATASEND

广播测试数据发送

0x09

0x20

MESSAGE READ

消息读取

MESSAGE CLEAR

消息清除

FAL/FALS READ

FAL/FALS读取

0x0C

0x01

ACCESS RIGHT ACQUIRE

访问权限获取

0x02

ACCESS RIGHT FORCEDACQUIRE

访问权限强制获取

0x03

ACCESS RIGHT RELEASE

访问权限释放

0x21

0x01

ERROR CLEAR

错误清除

0x02

ERROR LOG READ

错误日志读取

0x03

ERROR LOG CLEAR

错误日志清除

0x22

0x01

FILE NAME READ

文件名读取

0x02

SINGLE FILE READ

单文件读取

0x03

SINGLE FILE WRITE

单文件写入

0x04

MEMORY CARD FORMAT

记忆卡格式化

0x05

FILE DELETE

文件删除

0x06

VOLUME LABELCREATE/DELETE

卷标创建/删除

0x07

FILE COPY

文件复制

0x08

FILE NAME CHANGE

文件名更改

0x09

FILE DATA CHECK

文件数据校核

0x0A

MEMORY AREA FILETRANSFER

内存区域文件传输

0x0B

PARAMETER AREA FILETRANSFER/td>

参数区域文件传输

0x0C

PROGRAM AREA FILETRANSFER

程序区域文件传输

0x0F

FILE MEMORY INDEX READ

文件内存索引读取

0x10

FILE MEMORY READ

文件内存块读取

0x11

FILE MEMORY WRITE

文件内存块写入

0x23

0x01

FORCED SET/RESET

强制设置/重置

0x02

FORCED SET/RESETCANCEL

取消强制设置/重置

0x0A

MULTIPLE FORCED STATUSREAD

多强制状态读取

0x26

0x01

NAME SET

名称设置

0x02

NAME DELETE

名称删除

0x03

NAME READ

名称读取

合计:14个大类,57个子类,共57个Command Code。

2.2 Fins Over TCP

基于TCP的FINS报文结构也不复杂,无非就是一个FINS/TCP头部(必选),加上FINS/UDP报文(可选),如下所示:

12345678

Fins over TCP+----------------------------------------+| Fins/TCP Header |+----------------------------------------+| Fins/UDP Header(not neccessary) |+----------------------------------------+| Command Data(not neccessary) |+----------------------------------------+

2.2.1 Fins/TCP Header

Fins/TCP的报头与Fins/UDP不同的是,它由4个固定字段和2个可选字段组成,如下所示:

123456789101112131415

Fins/TCP Header0 31+---------+-----------+----------+---------------------+| Magic Bytes |+------------------------------------------------------+| Length |+------------------------------------------------------+| Command |+------------------------------------------------------+| Error Code |+------------------------------------------------------+| Client Node Address(optional) |+------------------------------------------------------+| Server Node Address(optional) |+------------------------------------------------------+

因此Fins/TCP的头部长度范围为[16,24]

字节,每个字段的长度均为固定的4个字节。

2.2.2 Magic字段

第一个字段为Magic Bytes字段,从字面意思看是魔数字段,其ASCII码(0x46494E53)刚好是FINS这个单词,因此可以推测这个字段的值是恒定的。

2.2.3 Length字段

第二个字段为Length字段,这个字段的值表示其后所有字段(包括可能出现的Fins/UDP包)的总长度,用公式表达为:Length=len(TCPPAYLOAD)−len(MagicBytes)−len(Length)=len(TCPPAYLOAD)−4−4=len(TCPPAYLOAD)−8(2 - 1)

也就是说,该字段的值等于TCP负载的总长度减去8个字节。

2.2.4 Command字段

第三个字段为Command字段,这个字段表示消息中随附的命令的类型。这个字段的取值直接决定了后续可选的字段Client Node Address、Server Node Address是否出现,具体情况如下所示:

0x00000000:节点地址数据已发送(C->S),此时仅有Client Node Address字段;

0x00000001:节点地址数据已发送(S->C),此时Client/Server Node Address字段均出现;

其它:不会出现上述两个字段。

2.2.5 Error Code字段

第四个字段为Error Code字段,这个字段表示错误代码。根据wireshark源代码所提供的信息,错误代码目前共定义了10种类型,如下所示:

错误码对应含义

0x00000000

Normal

0x00000001

The header is not ‘FINS’ (ASCII code)

0x00000002

The data length is too long

0x00000003

The command is not supported

0x00000020

All connections are in use

0x00000021

The specified node is already connected

0x00000022

Attempt to access a protected node from an unspecified IP address

0x00000023

The client FINS node address is out of range

0x00000024

The same FINS node address is being used by the client and server

0x00000025

All the node addresses available for allocation have been used

2.2.6 Client/Server Node Address字段

这两个字段是Fins/TCP的客户端/服务器建立连接的时候的类似DHCP协议客户端获取IP地址的时候才会出现的,如下所示:

由上可以看出,Fins/TCP协议的客户端/服务器在传输有效的命令数据之前,由客户端先向服务器发送一个包含Client Node Address字段的报文申请节点地址,如下图所示:

类似DHCP协议,由于客户端申请的时候还没有节点地址,因此该字段被置为0x00000000。 服务器收到客户端请求后,给客户端分配相应的节点地址并通告给客户端,同时在报文中包含服务器自己的节点地址信息,如下所示:

客户端收到服务器的响应报文后,即使用分配的节点地址与服务器进行通信,由此客户端/服务器之间就建立起了有效的长连接。

2.3 Command Data

这个字段是Fins/UDP、Fins/TCP协议的实际负载部分,鉴于其涵盖内容较多(官方手册就有两百多页),目前未对其进行深入解析,后续根据需要再深入解析。