关于IEC61499 的数据交换信息抽象语法ASN.1

前言

 IEC61499 是一个分布式控制系统功能块标准。多个设备之间,和其它外部设备之间都有信息交换。这种信息交换通过通信功能块来实现。通信功能块包括:

  单向通信功能块:Publish/Subscribe

  双向通信功能块:Client/Server

     设备之间的消息是功能块的数据(IEC61499-FBDATA),它们由类型和值构成。通信功能块可能涉及多个数据的输入输出。每个输入输出数据可以是简单的单值数据类型,也可以是数组类型(Constructed)。所以它们要交换多个数据。多个数据的信息抽象标识采用了ASN.1 的编解码方式。

ASN.1

ASN.1抽象语法标记(Abstract Syntax Notation One)是国际标准ISO 8825-1。使用紧凑的方式抽象标识计算机内部的数据,比如 整型数,布尔数,浮点数等等。正是由于ASN.1 是一个通用的语言,所以采用了描述的语法。初学起来感觉十分的复杂。在IEC61499 标准中只是采用了ISO8825-1 中的基本编码规则。并且在IEC61499-1 标准的附录E 信息交换 中做了进一步的规范和描述。结合起来学习就比较清晰了。

ASN.1 基本编码规则

一个数据值的编码由四个部分构成

标识八比特组(identifier octets)

长度八比特组(length octets)

内容八比特组(contents octets)

内容结束八比特组(end of content octets)

内容结束八比特组是可以缺省的。所以大多数情况下是三段式标识

|  identifier octets | length octets | contents octets |

有时也称为TLV三元组<Type,Length, Value>

identifier 标识的定义

 

 

第8,第7位代表了tag 的类

 

在IEC61499-1 附录E 中,对FBDATA 的ASN.1 编码规则做了进一步的规范

-tag 的类为Application。所有8,7 为0,1

-基本数据类型的tag number

BOOL0                0

BOOL1               1

SINT                2

INT                    3

DINT                  4

LINT                         5

UINT                6

USINT             7

UDINT                8

ULINT                9

REAL                 10

LREAL                11

TIME                12

DATE                13

TIME_OF_DAY    14

DATE_AND_TIME        15

STRING               16

BYTE                   17

WORD                 18

DWORD              19

LWORD              20

WSTRING            21

 

数组

ArrayVariable     22

IEC61499 FBDATA 的ASN.1 编码

(IEC61499-1 附录E)中说可以是两种:

-基本(BASIC) 编码

 符合ISO/IEC 8825-1 的基本编码规则

-紧凑(COMPACT)编码

4DIAC 中使用的是ComPACT 编码。

  对于上面的数据类型省却了长度(length octets),不同数据类型的长度是默认的。

 简单类型数据编码

采用compact 编码,多个数据连续排列。

例如 4个 INT

tag=01000011=0x43 其中class=01,P/Construct=0,tag number=3=00011

最后的编码

0x43 0x00,0x00, 0x43 0x00,0x00, 0x43 0x00,0x00, 0x43 0x00,0x00

数组类型的编码

   -tag 第6位为 1 Constructed

   - length 编码成为 UINT ,16位无符号数

   - 数组的第一个元素带有tag (COMPACT Encoding),后面的元素缺省了tag

例如 LREAL[2] 的编码为

  tag = 0x76=011 10110 其中

 class=01,P/Constructed =1 ,tag number=22=10110

length=x0002

contents=8 octetX2

第一个元素(LREAL)的tag为

 tag=01001011=0x4b 其中 class =01 /Construct=0,tag number=11=0x0b=01011

0x4b 是LREAL 类型。后面是两个LREAL,每个64位,8 个字节)。

最后的编码为

0x76,0x00,0x02,0x4b,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00  

 

程序实例

使用这个简单软件,可以显示出Client 功能块发送的ASN.1 编码的FBDATA

package main

import (
        "fmt"
        "net"
        "os"
)
func main() {
        arguments := os.Args
        if len(arguments) == 1 {
                fmt.Println("Please provide a port number!")
                return
        }
        PORT := ":" + arguments[1]

        s, err := net.ResolveUDPAddr("udp4", PORT)
        if err != nil {
                fmt.Println(err)
                return
        }

        connection, err := net.ListenUDP("udp4", s)
        if err != nil {
                fmt.Println(err)
                return
        }
       
        defer connection.Close()
		buffer := make([]byte, 1024)

	serveraddr, _ := net.ResolveUDPAddr("udp", "192.168.31.108:8881")
	client, _ := net.DialUDP("udp4", nil, serveraddr)
        for {
			 //   n, addr, err := connection.ReadFromUDP(buffer)
                 n, _, _ := connection.ReadFromUDP(buffer)
                 txbuf := make([]byte, n)
                for i:=0;i<n;i++ {
                                        fmt.Printf("0x%02x ",buffer[i])
                                        txbuf[i]=buffer[i]
				}
		 fmt.Printf("length=%d\n",n)  
                _, err := client.Write(txbuf)
                if err != nil {
                        fmt.Println(err)
                        return
                } 
        }
}

     相信我将IEC61499 标准的FBDATA ASN.1 编解码解释清楚了。没有去大幅介绍ASN.1 的抽象概念。当然,为了写清楚这些,我还特意化了点小钱,下载了ISO8825-1 2008 版标准。

          写博客,深入简出非常重要。

猜你喜欢

转载自blog.csdn.net/yaojiawan/article/details/107382193