Support for BiDiB

Feature-queries

To manage heterogeneous structures and properties, BiDiB is using a feature-system. Features are properties of the node, which can be queried and modified. For this purpose, a particular class of a node and the possible features are standardized.

A single feature can be queried as follows:

Host Node
MSG_FEATURE_GET (3) 
  MSG_FEATURE (3, value)

If the queried feature is unknown to the node, the dialog will be:

Host Node
MSG_FEATURE_GET (3) 
  MSG_FEATURE_NA (3)

Query all features

All features of a particular node can be queried as follows:

Host Node
MSG_FEATURE_GETALL  
  MSG_FEATURE_COUNT
MSG_FEATURE_GETNEXT 
  MSG_FEATURE (3, value)
MSG_FEATURE_GETNEXT 
  MSG_FEATURE (5, value)
MSG_FEATURE_GETNEXT 
  MSG_FEATURE (7, value)
MSG_FEATURE_GETNEXT 
  MSG_FEATURE_NA (255)

The host starts with a query count. As a result of the query, the counter at the node will be reset. With a number of MSG_FEATURE_GETNEXT commands the features will be fetched (here at the example 3.5 and 7), until the node respond with a MSG_FEATURE_NA (255) which indicates that everything was transferred.

Important: Messages must not be transmitted like in the example above, it is allowed (and desirable for performance reasons), that multiple messages are bundled, as example a single MSG_FEATURE_GETALL followed by several MSG_FEATURE_GETNEXT. Then we will get the appropriate number of responses in the opposite direction. It must be noted that a message block should not overload the respective feedback channel, otherwise the node is forced to leave messages unanswered. (see MSG_STALL).

Features at the node

This example shows how to implement these features. For the feature-system a structure will be declared first, which allows you to specify the features:


typedef struct
{
  unsigned char num;              // feature index (from bidib_messages.h)
  unsigned char value;            // current value
  unsigned char min;              // limits
  unsigned char max;
  void (*notify_function)(void);  // This function is called when the feature is described
} t_feature;

All features of the node will be applied in a table:


t_feature my_feature[] =
{   // num                        value min max notify_function
  { FEATURE_BM_SIZE,              8,    0,  8,  NULL},
  { FEATURE_BM_ON,                0,    0,  1,  NULL},
  { FEATURE_BM_SECACK_AVAILABLE,  0,    0,  0,  NULL},
  { FEATURE_BM_SECACK_ON,         0,    0,  0,  NULL},
};

A few other functions are required for sending the answers:


static void bidib_send_feature(unsigned char fnum, unsigned char f_value)
{
  t_node_message2 message;
  message.header.node_addr = 0;
  bidib_tx0_msg_num++;
  if (bidib_tx0_msg_num == 0) bidib_tx0_msg_num++;
  message.header.index = bidib_tx0_msg_num;
  message.header.msg_type = MSG_FEATURE;
  message.data[0] = fnum;
  message.data[1] = f_value;
  message.header.size = 3+2;
  send_bidib_message((unsigned char *)&message);
}

static void bidib_send_feature_na(unsigned char fnum)
{
  bidib_send_onepara_msg(MSG_FEATURE_NA, fnum);
}

static void bidib_send_feature_count(unsigned char fcount)
{
  bidib_send_onepara_msg(MSG_FEATURE_COUNT, fcount);
}

Now we are able to build a function that search for requested features in the table: If the feature is available, then it will be reported back. If a feature is set, it will be compared with the current limits (min, max) and if necessary the notify_function will be called to make sure the change is also effective.


static void get_feature(unsigned char fnum)
{
  unsigned char i;
  for (i=0; i<sizeof(my_feature)/sizeof(my_feature[0]); i++)
    {
      if (fnum == feature0[i].num)
        {
          bidib_send_feature(fnum, my_feature[i].value);    // send back feature
          return;
        }
    }
  bidib_send_feature_na(fnum);                            // no feature found
}

static void bidib_send_next_feature(void)
{
  if (bidib_feature2send < sizeof(feature)/sizeof(feature[0]))
    {
      bidib_send_feature(feature[bidib_feature2send].num, feature[bidib_feature2send].value);
      bidib_feature2send++;
    }
  else
    {
      bidib_send_feature_na(255);                           // all transmitted
    }
}

static void set_feature(unsigned char fnum, unsigned char f_value)
{
  unsigned char i;
  void (*fp)(void);                               // declare pointer to function

  for (i=0; i<sizeof(my_feature)/sizeof(my_feature[0]); i++)
    {
      if (fnum == feature0[i].num)
        {
          if (f_value < my_feature[i].min) f_value = my_feature[i].min;
          if (f_value > my_feature[i].max) f_value = my_feature[i].max;
          if (my_feature[i].value != f_value)
            {
              my_feature[i].value = f_value;
              fp = my_feature[i].notify_function;
              if (fp) (*fp)();                    // call this function, if not NULL
            }
          bidib_send_feature(fnum, my_feature[i].value);    // send back feature
          return;
        }
    }
  bidib_send_feature_na(fnum);                            // no feature found
}

Additional features can be added by simply expanding the table.