<< 点击显示目录 >> 主页 exOS使用助手 > exOS Automation Help > Development > Programming > Data communication > Datamodel description > Headerfile description |
让我们来看看 示例的各个部分 :
在#include<TypesTYP.typ>指令周围有一个#ifdefined(_SG4)。该包含指令来自.exospkg文件,通过<SG4Include="TypesTYP.h"/>指令,告诉头文件生成器使用数据类型定义的标准包含文件,而不是生成的Types数据定义。如果程序/库中使用的Types数据类型与IEC数据类型结合在一起,比如声明功能块输入/输出或Types或其任何成员的_LOCAL/_GLOBAL变量,这将非常有用。尽管生成的Types结构使用的数据类型与AS生成的头<TypesTYP.h>相同,但还是有区别的,因为exOS使用的是<stdint.h>数据类型,而AS使用的是char、short、long......等等。这就是在AS中包含IECTypes.typ生成的头文件<TypesTYP.h>而不是exOS头文件中的Types结构的原因。
如果.exospkg文件中没有定义<SG4Include="TypesTYP.h"/>(这可能是AR任务不需要将数据类型暴露给IEC环境的情况),并且对于Linux系统(没有定义_SG4),Types的数据类型定义如下:
typedef struct Types
{
bool Run; //PUB
bool Running; //SUB
uint32_t Counter; //SUB
} Types;
在系统启动时,exOS数据集消息路由器不知道Types数据类型,也不知道它使用了哪种填充。因此,数据模型会通过exos_datamodel_connect_types()函数以JSON描述的形式发送:
{
"name": "struct",
"attributes": {
"name": "<NAME>",
"dataType": "Types",
"info": "<infoId0>"
},
"children": [
{
"name": "variable",
"attributes": {
"name": "Run",
"dataType": "BOOL",
"comment": "PUB",
"info": "<infoId1>"
}
},
{
"name": "variable",
"attributes": {
"name": "Running",
"dataType": "BOOL",
"comment": " SUB",
"info": "<infoId2>"
}
},
{
"name": "variable",
"attributes": {
"name": "Counter",
"dataType": "UDINT",
"comment": " SUB",
"info": "<infoId3>"
}
}
]
}
这显然是一个结构定义,数据集报文路由器可以很简单地对其进行解析,以建立数据模型,而<infoId>标记则被替换为
{
"size": X,
"offset": Y
}
在发送到数据集消息路由器(DatasetMessageRouter)之前,exos_datamodel_connect()内部函数会提供一个完整的信息模型,包括所有成员和结构,以及在Types数据类型中使用的大小和偏移量。AR和Linux会使用这些信息自动调整两个系统之间的数据结构,而不会产生任何协议开销。
exos_datamodel_connect_types() 函数
应用程序应使用该函数将数据模型连接到数据集消息路由器。
它接收JSON数据模型定义,并使用MACROSEXOS_DATASET_BROWSE_NAME_INIT和EXOS_DATASET_BROWSE_NAME从类型成员Run、Running和Counter中计算当前大小和偏移量,然后将这些计算结果转发给_exos_internal_datamodel_connect(),后者会将完整的JSON字符串放在一起发送给数据集消息路由器。然后,数据集消息路由器将为所有成员准备缓冲区,这意味着运行、运行和计数器将成为应用程序可以发布和订阅的单独数据集。
exos_dataset_info_t datasets[] = {
{exos_dataset_browse_name_init,{}}、
{EXOS_DATASET_BROWSE_NAME(Run),{}}、
{EXOS_DATASET_BROWSE_NAME(运行),{}}、
{EXOS_DATASET_BROWSE_NAME(Counter),{}}.
};
这意味着,应用程序可以创建一个
exos_dataset_init(&run_dataset_handle,&types_datamodel_handle, "Run",&run_variable,sizeof(run_variable));
例如,初始化 Run 数据集。
有关数据集用法的更多信息,请参阅 exOS API 参考。 有关数组的更多详情,请参阅数据模型限制。
Lets go through the different sections of the Example:
Datatype definition (exos_types.h):
There is a #if defined(_SG4) surrounding an #include <TypesTYP.typ> directive. This include directive comes from the .exospkg file via the <SG4 Include="TypesTYP.h"/> instruction, telling the header generator to use a standard include file for the datatype definition rather than the generated Types data definition. This is useful if the Types datatype used in the program/library goes in conjunction with IEC datatypes, like declaring a function block input/output or a _LOCAL/_GLOBAL variable of Types or any of its members. Even though the generated Types structure uses the same datatypes as the AS generated header <TypesTYP.h>, there is a difference, as exOS used <stdint.h> datatypes, and AS uses char, short, long... and so forth. This is the reason for the possibility to include the IEC Types.typ generated headerfile <TypesTYP.h>from AS rather than the Types structure inside the exOS header.
If no <SG4 Include="TypesTYP.h"/> is defined in the .exospkg file (This could be the case if the AR task does not need to expose the datatype to an IEC environment), and for Linux systems (that do not define _SG4), the datatype definition of Types is the following:
typedef struct Types
{
bool Run; //PUB
bool Running; //SUB
uint32_t Counter; //SUB
} Types;
JSON datamodel definition (exos_types.c)
At the startup of the system, the exOS Dataset Message Router does not know about the Types datatype, nor which padding is used for it. Therefore, the datamodel is sent as a JSON description via the exos_datamodel_connect_types() function:
{
"name": "struct",
"attributes": {
"name": "<NAME>",
"dataType": "Types",
"info": "<infoId0>"
},
"children": [
{
"name": "variable",
"attributes": {
"name": "Run",
"dataType": "BOOL",
"comment": "PUB",
"info": "<infoId1>"
}
},
{
"name": "variable",
"attributes": {
"name": "Running",
"dataType": "BOOL",
"comment": " SUB",
"info": "<infoId2>"
}
},
{
"name": "variable",
"attributes": {
"name": "Counter",
"dataType": "UDINT",
"comment": " SUB",
"info": "<infoId3>"
}
}
]
}
This is visibly a definition of the structure which is rather simple to parse by the Dataset Message Router in order to build up the datamodel, whereas the <infoId> tags are replaced with
{
"size": X,
"offset": Y
}
inside the internal exos_datamodel_connect() function before being sent to the Dataset Message Router, providing a complete information model of all members and structures with sizes and offsets used in the Types datatype. This information is then used in AR and Linux to automatically align data structures between the two systems without any protocol overhead.
exos_datamodel_connect_types() function
This is the function that should be used by the application to connect a datamodel to the Dataset Message Router.
It takes the JSON datamodel definition and uses the MACROS EXOS_DATASET_BROWSE_NAME_INIT and EXOS_DATASET_BROWSE_NAME to calculate the current sizes and offsets from the Types members Run, Running and Counter, and forwards these calculations to the _exos_internal_datamodel_connect() which puts toghether the complete JSON string which is sent to the Dataset Message Router. The Dataset Message Router will then prepare buffers for all members, meaning that Run, Running and Counter become individual datasets that the application can publish and subscribe from.
exos_dataset_info_t datasets[] = {
{EXOS_DATASET_BROWSE_NAME_INIT,{}},
{EXOS_DATASET_BROWSE_NAME(Run),{}},
{EXOS_DATASET_BROWSE_NAME(Running),{}},
{EXOS_DATASET_BROWSE_NAME(Counter),{}}
};
This means, the application can make an:
exos_dataset_init(&run_dataset_handle, &types_datamodel_handle, "Run", &run_variable, sizeof(run_variable));
To initialize the Run dataset for example.
For more information regarding the usage of datasets, see exOS API reference. For more elaboration on arrays, see Datamodel limitations.