exos_dataset_init()

<< 点击显示目录 >>

主页  exOS使用助手 > exOS Automation Help > Development > Programming > exOS Communication API reference (exos_api.h) >

exos_dataset_init()

初始化数据集句柄并将其附加到数据模型

调用语法

该函数初始化了 exos_dataset_handle_t 结构,即清零所有成员并设置人工制品、数据和大小成员。该函数还会将 exos_dataset_handle_t 附加  到特定的数据模型,以便 API 可以通过 exos_datamodel_process() 触发事件回调 。

EXOS_ERROR_CODE exos_dataset_init(exos_dataset_handle_t *dataset, exos_datamodel_handle_t *datamodel, const char *browse_name, const void *data, size_t size);

参数

dataset:  需要初始化exos_dataset_handle_t (以指针形式给出)

数据模型重要的是 调用 exos_datamodel_init()之前 该句柄已通过 exos_datamodel_init() 初始化

browse_name:这是数据模型所代表的数据类型结构成员的名称。在这里,生成的标头可以提供帮助,因为可用的浏览名称是在 exos_datamodel_connect_() 函数 中  通过 EXOS_DATASET_BROWSE_NAME 宏 初始化 。在下面的示例中,浏览名称和 .typ 文件 之间的关系  应该是可视化的。

  //WaterTank.typ: declaration of the WaterTank structure becoming the datamodel
  TYPE
      WaterTank :  STRUCT
          FillValve : WaterTankFillValve_enum;
          EnableHeater : ARRAY[0..2]OF BOOL;
          HeaterConfig : ARRAY[0..2]OF WaterTankHeaterConfig;
      END_STRUCT;
      WaterTankHeaterConfig :  STRUCT
          MaxTemperature : REAL;
          MaxPower : REAL;
      END_STRUCT;
      WaterTankFillValve_enum :
          (
          VALVE_CLOSED := 0,
          VALVE_OPEN := 1
          );
  END_TYPE
 //exos_watertank.h:生成的连接函数,包含数据集的可用浏览名称
 EXOS_ERROR_CODE exos_datamodel_connect_watertank(exos_datamodel_handle_t *datamodel, exos_datamodel_event_cb datamodel_event_callback)
  {
      WaterTank data;
      exos_dataset_info_t datasets[] = {
          {EXOS_DATASET_BROWSE_NAME_INIT,{}},
          {EXOS_DATASET_BROWSE_NAME(FillValve),{}},
          {EXOS_DATASET_BROWSE_NAME(EnableHeater),{}},
          {EXOS_DATASET_BROWSE_NAME(EnableHeater[0]),{3}},
          {EXOS_DATASET_BROWSE_NAME(HeaterConfig),{}},
          {EXOS_DATASET_BROWSE_NAME(HeaterConfig[0]),{3}},
          {EXOS_DATASET_BROWSE_NAME(HeaterConfig[0].MaxTemperature),{3}},
          {EXOS_DATASET_BROWSE_NAME(HeaterConfig[0].MaxPower),{3}},
 //watertank.c: 初始化数据集的应用程序
  int main()
  {
      WaterTank data;
      exos_datamodel_handle_t watertank;
      exos_dataset_handle_t config;
      exos_dataset_handle_t enable;
      exos_dataset_handle_t fill;
      ...
      EXOS_ASSERT_OK(exos_datamodel_init(&watertank, "WaterTank", "WaterTankDemo"));
      EXOS_ASSERT_OK(exos_dataset_init(&config, &watertank, "HeaterConfig", &data.HeaterConfig, sizeof(data.HeaterConfig)));
      EXOS_ASSERT_OK(exos_dataset_init(&enable, &watertank, "EnableHeater[1]", &data.EnableHeater[1], sizeof(data.EnableHeater[1])));
      EXOS_ASSERT_OK(exos_dataset_init(&fill, &watertank, "FillValve", &data.FillValve, sizeof(data.FillValve)));

这个示例还表明,可以将数据集初始化为一个完整的结构数组(如 HeaterConfig),也可以初始化为单个数组成员(如 EnableHeader[1])。请注意,在 数据模型限制中  ,只能对同一 BROWSE_NAME 的一个数组成员进行初始化,例如,不可能对同一工件上的 EnableHeater[2] 数据集进行初始化。但可以将 HeaterConfig[0] 或 HeaterConfig[2].MaxTemperature 作为附加数据集进行初始化。这是因为在内部,每个 BROWSE_NAME 都会进入 数据集消息路由器 中具有单独发送缓冲区的传输对象列表 。

数据:指向 API 中用于发布和订阅的数据区的指针。在数据模型的整个生命周期中,该数据区域必须可用且有效。值得注意的是,传递给此函数的数据区将  由 API exos_datamodel_process() 上下文 直接使用 。这意味着,如果需要一个不直接受影响的区域,则应使用多个区域。例如

 ConfigStruct_t gConfig; // 应用程序的结构,不受 API 影响
  void configChanged(exos_dataset_handle_t *value)
  {
      if(value->connection_state != EXOS_STATE_CONNECTED && value->connection_state != EXOS_STATE_OPERATIONAL) return;
      //evaluate if its ok to update the members, check the limits etc..
      ConfigStruct_t *config = (ConfigStruct_t *)value->data;
      if(config->maxSpeed <= 100)
      {
          gConfig.maxSpeed = config->maxSpeed;
      }
      else
      {
          gConfig.maxSpeed = config->maxSpeed = 100;
          //respond to the server with the limited config->maxSpeed value
          exos_dataset_publish(value);
      }
  }
  int main(int argc, char *argv[])
  {
      ...
      ConfigStruct_t apiConfig; //structure directly used in the API
      exos_dataset_handle_t configValue;
      exos_value_init(&myartefact, &configValue, "Config", &apiConfig, sizeof(apiConfig));
      exos_value_register_subscription(&configValue, NULL, configChanged);
      exos_value_register_publisher(&configValue, NULL, NULL);
  }

大小:API 用于发布和订阅的数据区域的大小。

数据集消息路由器(DatasetMessage Router)会在  执行 exos_dataset_connect() 后 检查数据集的大小 ,这意味着即使 exos_dataset_init() 返回 EXOS_ERROR_OK,数据集仍会收到 EXOS_STATE_ABORTED 事件,并伴有 EXOS_ERROR_BAD_DATASET_SIZE 错误。

例如,应在使用 exos_dataset_handle_t之前调用该函数 :

exos_dataset_handle_t counter;
exos_dataset_init(&counter, &myartefact, "Counter", &interface.Counter, sizeof(interface.Counter));
counter.user_tag = VARS_COUNTER;


Initialize a dataset handle and attach it to a datamodel

Call syntax

This function initializes the exos_dataset_handle_t structure, meaning it zeroes all members and sets artefact, data and size members. The function will also attach the exos_dataset_handle_t to the certain datamodel that the API can trigger event callbacks via exos_datamodel_process().

EXOS_ERROR_CODE exos_dataset_init(exos_dataset_handle_t *dataset, exos_datamodel_handle_t *datamodel, const char *browse_name, const void *data, size_t size);

Parameters

dataset: the exos_dataset_handle_t that should be initialized (given as a pointer)

datamodel: The exos_datamodel_handle_t that the dataset should be attached to (given as a pointer) It is important that this handle is already intialized with exos_datamodel_init() before calling exos_dataset_init().

browse_name: This is the name of the structure member of the datatype that the datamodel represents. Here, the generated header can be of help, as the available browse names are initialized in the exos_datamodel_connect_() function via the EXOS_DATASET_BROWSE_NAME macro. In the following example, the relation between the browse name and the .typ file should be visualized.

  //WaterTank.typ: declaration of the WaterTank structure becoming the datamodel
  TYPE
      WaterTank :  STRUCT
          FillValve : WaterTankFillValve_enum;
          EnableHeater : ARRAY[0..2]OF BOOL;
          HeaterConfig : ARRAY[0..2]OF WaterTankHeaterConfig;
      END_STRUCT;
      WaterTankHeaterConfig :  STRUCT
          MaxTemperature : REAL;
          MaxPower : REAL;
      END_STRUCT;
      WaterTankFillValve_enum :
          (
          VALVE_CLOSED := 0,
          VALVE_OPEN := 1
          );
  END_TYPE
  //exos_watertank.h: generated connection function, with available browse names for datasets
  EXOS_ERROR_CODE exos_datamodel_connect_watertank(exos_datamodel_handle_t *datamodel, exos_datamodel_event_cb datamodel_event_callback)
  {
      WaterTank data;
      exos_dataset_info_t datasets[] = {
          {EXOS_DATASET_BROWSE_NAME_INIT,{}},
          {EXOS_DATASET_BROWSE_NAME(FillValve),{}},
          {EXOS_DATASET_BROWSE_NAME(EnableHeater),{}},
          {EXOS_DATASET_BROWSE_NAME(EnableHeater[0]),{3}},
          {EXOS_DATASET_BROWSE_NAME(HeaterConfig),{}},
          {EXOS_DATASET_BROWSE_NAME(HeaterConfig[0]),{3}},
          {EXOS_DATASET_BROWSE_NAME(HeaterConfig[0].MaxTemperature),{3}},
          {EXOS_DATASET_BROWSE_NAME(HeaterConfig[0].MaxPower),{3}},
  //watertank.c: application that initializes datasets
  int main()
  {
      WaterTank data;
      exos_datamodel_handle_t watertank;
      exos_dataset_handle_t config;
      exos_dataset_handle_t enable;
      exos_dataset_handle_t fill;
      ...
      EXOS_ASSERT_OK(exos_datamodel_init(&watertank, "WaterTank", "WaterTankDemo"));
      EXOS_ASSERT_OK(exos_dataset_init(&config, &watertank, "HeaterConfig", &data.HeaterConfig, sizeof(data.HeaterConfig)));
      EXOS_ASSERT_OK(exos_dataset_init(&enable, &watertank, "EnableHeater[1]", &data.EnableHeater[1], sizeof(data.EnableHeater[1])));
      EXOS_ASSERT_OK(exos_dataset_init(&fill, &watertank, "FillValve", &data.FillValve, sizeof(data.FillValve)));

This example also shows that it is possible to initialize a dataset towards a complete structure array (like HeaterConfig), or to individual array members (like EnableHeader[1]). Note in the Datamodel limitations that its only possible to initialize one array member of the same BROWSE_NAME, for example it is not possible to initialize a dataset with EnableHeater[2] on the same artefact. However it is possible to initialize HeaterConfig[0] or HeaterConfig[2].MaxTemperature as additional datasets. This is because internally, every BROWSE_NAME goes into a list of transmission objects with separate send buffers in the Dataset Message Router.

data: Pointer to the data area used in the API for publishing and subscribing. This data area must be available and valid throughout the life-cycle of the datamodel. It is important to note that the data area that is passed on to this function will be used directly by the API in the context of the exos_datamodel_process(). This means that if it is required to have an area that is not directly affected, multiple areas should be used. For example:

  ConfigStruct_t gConfig; //structure for the application, unaffected by the API
  void configChanged(exos_dataset_handle_t *value)
  {
      if(value->connection_state != EXOS_STATE_CONNECTED && value->connection_state != EXOS_STATE_OPERATIONAL) return;
      //evaluate if its ok to update the members, check the limits etc..
      ConfigStruct_t *config = (ConfigStruct_t *)value->data;
      if(config->maxSpeed <= 100)
      {
          gConfig.maxSpeed = config->maxSpeed;
      }
      else
      {
          gConfig.maxSpeed = config->maxSpeed = 100;
          //respond to the server with the limited config->maxSpeed value
          exos_dataset_publish(value);
      }
  }
  int main(int argc, char *argv[])
  {
      ...
      ConfigStruct_t apiConfig; //structure directly used in the API
      exos_dataset_handle_t configValue;
      exos_value_init(&myartefact, &configValue, "Config", &apiConfig, sizeof(apiConfig));
      exos_value_register_subscription(&configValue, NULL, configChanged);
      exos_value_register_publisher(&configValue, NULL, NULL);
  }

size: Size of the data area used by the API for publishing and subscribing.

The size of the data area is checked on the Dataset Message Router after the exos_dataset_connect(), meaning even if the exos_dataset_init() returns EXOS_ERROR_OK, the dataset can still get an EXOS_STATE_ABORTED event with an EXOS_ERROR_BAD_DATASET_SIZE error.

This function should be called before using the exos_dataset_handle_t, for example:

exos_dataset_handle_t counter;
exos_dataset_init(&counter, &myartefact, "Counter", &interface.Counter, sizeof(interface.Counter));
counter.user_tag = VARS_COUNTER;