Support für BiDiB

Für die ersten Gehversuche mit einer neuen Hardware / Software sind hier ein paar Hinweise zum Start einer Session und ein paar beispielhafte Protokolldaten angegeben.

Protokollstart

Üblicherweise ist nach dem Einschalten zunächst mal unklar, im welchem Zustand sich der jeweilige Protokollpartner befindet. Man muss also warten, bis ein Nachrichten-Framezeichen eintrifft, erst dann kann man beginnen, sinnvoll Daten auszuwerten. Seitens des Hostes muss man auch damit rechnen, dass das BiDiB-System bereits freigeschaltet ist und aktiv Daten sendet bzw. gesandt hat. Diese Daten können noch in Buffern sowohl auf dem PC als auch auf BiDiB-System.

Beim Start eines Hostprogrammes sendet man also ein Framezeichen, eine Abfragenachricht, ein Framezeichen und nochmal eine Abfragenachricht samt Framezeichen: Die erste Abfrage provoziert eine Antwort, man bekommt also sicher an deren Ende ein Framezeichen. Die zweite Abfrage ist dann der eigentliche Protokollstart.

Nach dem erfolgten Kontakt mit dem Interface (also eine gültige Antwort auf MSG_GET_SYS_MAGIC) sollte ein MSG_SYS_RESET durchgeführt werden, damit alle evtl. noch vom vorherigen Betrieb übrigen Kommunikationsreste wie z. B. Secure-ACK, Nodetab-Benachrichtigungen usw. beendet werden.

Diesen Doppelstart muss man auf den drei möglichen Baudraten 1 MBaud, 115200 Baud und 19200 Baud (in dieser Reihenfolge) probieren. Hierbei ist zu beachten, wenn man ein BiDiB-System mit 1MBaud kontaktiert, welches bereits aktiv auf 115200 Baud agiert, dann sieht man ein Null-BIT als Null-Byte! Wenn also die Antwort auf eine Anfrage aus lauter Nullbytes besteht, ist vermutlich eine langsamere Baudrate bereits aktiv.

Nach der Kontaktaufnahme und Initialisierung kann man dann die NODETAB des Interfaces einlesen. In der Nodetab stehen alle Nodes, welche auf dieser Ebene vorhanden sind. Wenn bei diesen Nodes ein Interface dabei ist (erkenntlich am gesetztem Class-ID-Bit für Interface), dann sind dort weitere Subnodes vorhanden.

Beispieldaten BiDiB (seriell)

Host sendet:

0xFE 0x03 0x00 0x00 0x01 0xD6 0xFE, dabei bedeutet:
    0xFE Magic
    0x03 MSG_LENGTH
    0x00 lokale Adresse
    0x00 MSG_NUM
    0x01 MSG_TYPE (= MSG_SYS_GET_MAGIC)
    0xD6 CRC
    0xFE Magic

Die Nachricht beginnt mit BIDIB_PKT_MAGIC (siehe hierzu die Anmerkung unten), es folgt eine Size von 3. Die Size umfasst hier die Daten bis zum CRC, CRC selbst wird jedoch nicht mitgezählt.

Die Lokale Adresse ist 0, damit ist diese Nachricht an das Interface gerichtet.

Die Nachrichtennummer ist 0, also soll der Zielknoten keine Überprüfung durchführen und auch seine Überprüfung zurücksetzen.

Schließlich ist der Messagetyp = 0x01 = MSG_SYS_GET_MAGIC, also die Abfrage der Systemkennung. Diese Abfrage dient zur Überprüfung, ob man mit einem BiDiB-System verbunden ist. Parameter sind hier keine vorhanden.

Die Antwort des Knotens sieht dann so aus:

0xFE 0x05 0x00 0x00 0x81 0xFD 0xDE 0xAF 0x89 0xFE, dabei bedeutet:
    0x05 MSG_LENGTH
    0x00 lokale Adresse
    0x00 MSG_NUM
    0x81 MSG_TYPE (= MSG_SYS_MAGIC)
    0xFD escape
    0xDE macht dann: FE
    0xAF zusammen mit oben: FEAF
    0x89 CRC

Auch hier beginnt die Nachricht mit BIDIB_PKT_MAGIC (siehe hierzu die Anmerkung unten), es folgt eine Size von 5. Die Size umfasst hier die Daten bis zum CRC, CRC selbst sowie das in diesem Beispiel eingelagerte Escape wird jedoch nicht mitgezählt.

Die Lokale Adresse ist 0, damit kommt diese Nachricht vom Interface.

Die Nachrichtennummer ist 0, diese wird dann bei weiteren Nachrichten inkrementiert.

0x01 = MSG_SYS_MAGIC kündigt die Systemkennung an. Diese besteht aus zwei Bytes: 0xFE, 0xAF; Da 0xFE gleich BIDIB_PKT_MAGIC ist, muss das 'escaped' werden: Es wird 0xFD gesendet und dann 0xDE; das hat sich aus 0xFE mittels xor mit 0x20 ergeben.

Beispieldaten BiDiBus (RS485)

Eine Logonnachricht eines Knoten sieht z. B. so aus:

0x0B 0x0A 0x00 0x00 0x8E 0x40 0x00 0x0D 0x67 0x00 0x01 0x00 0x4C, dabei bedeutet:
    0x0B Größe des Pakets, enthält hier nur eine Message
    0x0A MSG_LENGTH Größe der Message
    0x00 lokale Adresse
    0x00 MSG_NUM
    0x8E MSG_TYPE (= MSG_LOCAL_LOGON)
    0x40 Class_ID
    0x00 extended Class_ID
    0x0D Vendor_ID (13 = DIY)
    0x67 0x00 0x01 0x00 Product_ID (Herstellerspezifisch)
    0x4C CRC

Die Nachricht beginnt mit der Paketgröße, hier sind 11 Bytes enthalten (von 0x0A bis 0x00), dann kommen die Messages, wobei hier nur eine Message enthalten ist. Diese beginnt wieder mit der Size (10 Bytes), gefolgt von lokaler Adresse, Sequenznummer und Nachrichtentyp. Es schließen sich 7 Byte an Daten an (Unique-ID des Knotens). Die CRC wird dann über das Paket berechnet.

Beispieldaten BiDiB (Systemstart)

Hier noch ein etwas ausführlicheres Beispiel einer Kommunikation zwischen einem Hostprogramm und einen BiDiB-System. Nach Kontaktaufnahme frägt hier der Host die Softwareversionen ab, lässt sich dann alle vorhandenen Features übermitteln und frägt zum Schluss noch die Belegtmeldung ab.


IRP_MJ_WRITE FE 03 00 00 01 D6 FE
IRP_MJ_WRITE FE 03 00 00 01 D6 FE                 // = MSG_GET_MAGIC
IRP_MJ_READ  FE 05 00 01 86 02 00 46 FE           // = CRC Error (von alten Initversuchen)
IRP_MJ_READ  05 00 00 81 FD DE AF 89 FE           // = MSG_SYS_MAGIC
IRP_MJ_READ  FE 05 00 00 81 FD DE AF 89 FE        // = MSG_SYS_MAGIC
IRP_MJ_WRITE FE 03 00 00 09 14 FE                 // = MSG_SYS_RESET
IRP_MJ_WRITE FE 03 00 00 01 D6 FE                 // = MSG_SYS_GET_MAGIC
IRP_MJ_WRITE FE 03 00 01 07 CF FE                 // = MSG_SYS_PING
IRP_MJ_WRITE FE 03 00 05 02 CB FE                 // = MSG_SYS_GET_P_VERSION
IRP_MJ_WRITE FE 03 00 02 05 26 FE                 // = MSG_SYS_GET_UNIQUE_ID
IRP_MJ_WRITE FE 03 00 03 03 3F FE                 // = MSG_SYS_ENABLE
IRP_MJ_READ  05 00 00 81 FD DE AF 89 FE           // = MSG_SYS_MAGIC
IRP_MJ_READ  03 00 01 82 7C FE                    // = MSG_SYS_PONG
IRP_MJ_WRITE FE 03 00 04 06 6E FE                 // = MSG_SYS_GET_SW_VERSION
IRP_MJ_WRITE FE 03 00 06 10 BF FE                 // = MSG_FEATURE_GETALL
IRP_MJ_READ  05 00 04 83 04 00 58 FE              // = MSG_SYS_P_VERSION --> 00.04
IRP_MJ_READ  0A 00 02 84 C0 00 0D 66 00 00 0A C0 FE
                                                  // = MSG_SYS_UNIQUE_ID --> C000 = Interface + Belegtmelder
IRP_MJ_READ  06 00 03 85 02 08 01 FF FE           // = MSG_SYS_SW_VERSION --> 01.08.02
IRP_MJ_READ  04 00 05 92 09 E4 FE                 // = MSG_FEATURE_COUNT

// Jetzt werden die features des Node 0 gelesen

IRP_MJ_WRITE FE 03 00 07 11 25 FE                 // = MSG_FEATURE_GETNEXT
IRP_MJ_READ  05 00 06 90 00 18 95 FE              // = feature: Anzahl Belegtmelder = 0x18
IRP_MJ_WRITE FE 03 00 08 11 3D FE                 // = MSG_FEATURE_GETNEXT
IRP_MJ_READ  05 00 07 90 01 01 DF FE              // = feature: Belegtmeldung aktiviert

// usw.

// Belegtmeldung abfragen

IRP_MJ_WRITE FE 05 00 10 20 00 18 18 FE           // = MSG_BM_GET_RANGE von 0x00 bis 0x18
IRP_MJ_READ  08 00 0F A2 00 18 00 00 00 09 FE     // = MSG_BM_MULTIPLE
                                                  // 0x00 = Start, 0x18 = Size
                                                  // drei Bytes 0x00: alles leer.

Adressierung mehrerer Knoten

Dieses Bespiel zeigt die Adressierung verschiedener Knoten. Hier angenommen sei ein Interface (diese hat die Adresse 00) und ein daran angeschlossener BiDiBus-Knoten. Dessen Bus-Adresse wird beim Logon vergeben und sei hier mit 01 angenommen, der Knoten wird also mit 01 00 adressiert.

Hierzu holt man zuerst vom Interface die aktuelle Zuordnung von Nodes zu lokalen Adressen. Diese geschieht mit MSG_NODETAB_GETALL.

Dann hast man eine Liste, welche Knoten (erkennbar an Ihrer UNIQUE_ID) angeschlossen ist und weiß deren aktuelle lokale Adresse. (in diesem Fall 00 und 01 00)

Nachfolgend zwei Beispiele für Nachrichten an diese Knoten:

Interface, Node Adresse 0:

fe 04 00 06 12 fd de d8 fe   // serielle Nachricht

Aufgeschlüsselt ergibt sich folgende Bedeutung der Bytes:

fe: Magic
04: Size
00: Adresse
06: Sequence (d.h. hier die 6. Nachricht an das Interface)
12: MSG_FEATURE_GET
fd de: Abfrage Feature 254 (inkl. escaping)
d8: CRC

Knoten, Node Adresse 1:

fe 05 01 00 04 12 32 c7 fe   // serielle Nachricht
Aufgeschlüsselt ergibt sich folgende Bedeutung der Bytes:
fe: Magic
05: Size (hier um eins mehr, die Adresse ist länger)
01 00: Adresse
04: Sequence (d.h. hier die 4. Nachricht an diesen Knoten)
12: MSG_FEATURE_GET
32: Abfrage Feature 50
c7: CRC

Adressierung mehrerer Ebenen, Verwendung eines Hubs

BiDiB ist hierarchisch aufgebaut, Busebenen können verschachtelt werden. Aus Hostsicht ist das wie eine Baumstruktur. Meldet also ein Knoten ein Interface an (entsprechendes Class-Bit in der der Unique-ID ist gesetzt), so kann man durch Lesen der Nodetabelle dieses Knotens die Zuordnung der entsprechenden Unterknoten zur aktuell vergebenen lokalen Adresse erhalten:

00 → Interface
04 00 → Hub (die 4 ist hier einfach ein Beispiel)
04 02 00 → Knoten hinter dem Hub (wobei 02 die aktuelle, lokale Adresse des Knotens ist,
        welche man aus der Nodetabelle des Hubs erfährt)

Das kann auch rekursiv auftreten:

00 → Interface
04 00 → Hub
04 02 00 → Hub hinter dem Hub
04 02 05 00 → Zielknoten hinter dem zweitem Hub
  • 04 ist die lokale Adresse des ersten Hubs, diese gewinnt man aus der Nodetabelle des Interfaces
  • 02 ist die lokale Adresse des zweiten Hubs, diese gewinnt man aus der Nodetabelle des ersten Hubs. Zusammen mit der Adresse des ersten Hub ergibt sich der Adressstapel zu 04 02 00.
  • 05 ist die lokale Adresse des Zielknotens, diese gewinnt man aus der Nodetabelle des zweiten Hubs.

Der Adressstapel ist auf 32 Bit = 4 Ebenen beschränkt, dann wirft das Interface eine entsprechende Fehlermeldung.