欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

IEC61499 编程(1)-UDP Publish/Subscribe 与Golang 通信

程序员文章站 2022-03-12 16:04:54
...

        通过IEC61499 功能块和外部软件通信,同样能够扩展应用程序的性能。比如使用其它语言实现与云端数据库的通信。不需要实现特殊的功能块,而是通过其它程序来实现访问数据库的功能,功能块通过Publish/subscribe 机制与其它程序通信。如果IEC61499 运行时forte和其它应用程序在同一个计算机中运行,相信传输效率还是比较高的,毕竟只是内存之间的数据传输。这一方式使IEC 61499 标准与物联网,边缘计算,云计算,人工智能等新技术相融合。是非常令人激动的事情。为此,我先做了一些实验。

IEC61499 编程(1)-UDP Publish/Subscribe 与Golang 通信

测试方法

  1. 使用Eclipse 4DIAC 开发环境编写IEC 功能块。
  2. 使用golang 编写了一个UDPTest 程序。该程序接收publish 功能块发送的数据,显示在控制终端上,并且转发到Subscribe 的端口。注意,Publsh/subscribe 不能使用同一个端口。

 

IEC61499 功能块网

IEC61499 编程(1)-UDP Publish/Subscribe 与Golang 通信

Golang程序

package main

import (
        "fmt"
        "math/rand"
        "net"
        "os"
     //   "strconv"
     //   "strings"
        "time"
)

func random(min, max int) int {
        return rand.Intn(max-min) + min
}

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)
		
        rand.Seed(time.Now().Unix())
	serveraddr, _ := net.ResolveUDPAddr("udp", "192.168.43.52: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
                } 
        }
}

结果

首先运行udptest程序。

>./udptest 8888

在udptest 显示的结果:

IEC61499 编程(1)-UDP Publish/Subscribe 与Golang 通信

从中可以看出,4DIAC 的Publish /subscribe 的UDP 格式为:

数据类型ID/数据/数据类型ID/数据。。。

在这个应用中,0x43 表示 INT ,而0x4a 表示是ULINT 

在Forte 的源代码src/core/datatypes/forte.any.h 中,有DataTypeID 定义,好像INT 为0x03,ULINT 为0x0a 是相互对应的。至于前面的4 是什么意思还不清楚。

 enum EDataTypeID{
      e_ANY, e_BOOL, e_SINT, e_INT, e_DINT, e_LINT, e_USINT, e_UINT, e_UDINT, e_ULINT, e_BYTE, e_WORD, e_DWORD, e_LWORD, e_DATE, e_TIME_OF_DAY, e_DATE_AND_TIME, e_TIME, //until here simple Datatypes
      e_REAL,
      e_LREAL,
      e_STRING,
      e_WSTRING,
      e_DerivedData,
      e_DirectlyDerivedData,
      e_EnumeratedData,
      e_SubrangeData,
      e_ARRAY, //according to the compliance profile
      e_STRUCT,
      e_External = 256, // Base for CIEC_ANY based types outside of the forte base
      e_Max = 65535 // Guarantees at least 16 bits - otherwise gcc will optimizes on some platforms
    };

4DIAC 监控的结果

IEC61499 编程(1)-UDP Publish/Subscribe 与Golang 通信

下面这个是发送和接收数组

IEC61499 编程(1)-UDP Publish/Subscribe 与Golang 通信

运行的结果:

IEC61499 编程(1)-UDP Publish/Subscribe 与Golang 通信

看来 76 是代表数组 ,0x00,0x02 是长度,0x4b 是LREAL 类型。后面是两个LREAL (每个64位,8 个字节)。

IEC61499 编程(1)-UDP Publish/Subscribe 与Golang 通信

可惜,目前只支持3 个值的数组 (嗨!),背景资料可以参考我的博文:

当物联网遇见 IEC61499

相关标签: iot IEC61499