Support für Hersteller
Userkonfiguration
Beispielcode
Analysewerkzeuge
Support für BiDiB
Was sind Features?
Zum Verwalten heterogener Strukturen und Eigenschaften verwendet BiDiB ein feature-System. Features sind Eigenschaften des jeweiligen Knotens, welche abgefragt und verändert werden können. Hierzu sind für eine bestimmte Klasse eines Knotens auch die möglichen Features einheitlich festgelegt.
Feature-Abfrage
Einzelne, bestimmte Features werden wie folgt abgefragt:
Host | Knoten | |
---|---|---|
MSG_FEATURE_GET (3) | → | |
← | MSG_FEATURE (3, value) |
Sollte der Knoten das Feature nicht kennen, dann ergibt sich folgender Dialog:
Host | Knoten | |
---|---|---|
MSG_FEATURE_GET (3) | → | |
← | MSG_FEATURE_NA (3) |
Alle Features abfragen
Wenn man alle Features eines Knotens abfragen will, geht man wie folgt vor:
Host | Knoten | |
---|---|---|
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) |
Der Host beginnt mit einer Abfrage der Anzahl. Dadurch wird im Knoten der Abfragezähler zurückgesetzt. Mit einer Reihe von MSG_FEATURE_GETNEXT werden dann die Features abgeholt (hier im Beispiel 3,5, und 7), bis der Knoten mit einer MSG_FEATURE_NA (255) anzeigt, dass alles übertragen wurde.
Wichtig: Die Nachrichten müssen nicht so verzahnt hin- und hergeschickt werden, es ist zulässig (und aus Performancegründen wünschenswert), dass mehrere Nachrichten gebündelt werden, also z. B. ein MSG_FEATURE_GETALL und gleich noch mehrere MSG_FEATURE_GETNEXT mit dazu. Dann wird man in Gegenrichtung auch die entsprechende Zahl an Antworten bekommen. Hierbei ist zu beachten, dass ein Nachrichtenblock den jeweiligen Antwortkanal nicht überfordert, weil sonst der Knoten gezwungen ist, Nachrichten unbeantwortet zu lassen. (siehe MSG_STALL).
Wenn man nach den verfügbaren Features weitere MSG_FEATURE_GETNEXT an den Knoten sendet, so werden diese alle mit MSG_FEATURE_NA(255) beantwortet.
Feature im Knoten
Dieses Beispiel zeigt, wie man solche Features leicht implementieren kann. Für das Feature-Systems wird hier zuerst eine Struktur deklariert, mit der man dann die Features angeben kann:
typedef struct
{
unsigned char num; // feature index (aus bidib_messages.h)
unsigned char value; // der aktuelle Wert
unsigned char min; // unsere Grenzen
unsigned char max;
void (*notify_function)(void); // Diese Funktion wird gerufen, wenn das Feature beschrieben wird
} t_feature;
Alle features des Knotens werden dann in einer Tabelle angelegt:
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},
};
Als weitere Zutat werden noch Funktionen zum Absenden der Antworten benötigt:
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);
}
Jetzt kann man eine Funktion bauen, welche angefragte Features in der Tabelle sucht: wenn das Feature vorhanden ist, dann wird es zurückmeldet. Beim Setzen eines Features wird auf die Grenzen (min, max) verglichen und fallweise die bei Veränderungen die notify_function aufgerufen, damit die Veränderung auch wirkt.
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); // feature zuruecksenden
return;
}
}
bidib_send_feature_na(fnum); // kein Feature gefunden
}
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); // alle gesendet
}
}
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); // feature zuruecksenden
return;
}
}
bidib_send_feature_na(fnum); // kein Feature gefunden
}
Weitere Features lassen sich damit einfach durch Erweitern der Tabelle hinzufügen.