netBiDiB

BiDiB - Bidirektionaler Bus - Logo

Inhaltsverzeichnis

1. Allgemeines

Das Protokoll BiDiB dient zur Kontrolle einer Modellbahnanlage. Es ermöglicht die Ansteuerung von Loks, Zubehör und sichere Übertragung von Rückmelderinformationen aus der Modellbahnanlage an den steuernden Rechner.

BiDiB kann über verschiedene Übertragungsmedien transportiert werden, dabei wird das Framing und die Sicherung der Nachrichten gewährleistet.

Eine Erläuterung der hier verwendeten Begriffe und der Protokollgrundzüge findet sich im allgemeinen Teil der Protokollbeschreibung, gleiches gilt auch für die Hinweise zur Benutzung und zur Lizenz.

Im folgenden ist der Transport über eine Netzwerkverbindung beschrieben, verwendet wird der TCP/IP-Stack.

Hinweis: Datenübertragung über ein öffentliches Netzwerk beinhaltet die Gefahr der Manipulation der übertragenen Daten. Die unverschlüsselte Datenübertragung zur Modellbahn darf daher nur in einer lokalen, geschützten Umgebung erfolgen. Eine Fernsteuerung der Modellbahn mittels netBiDiB über das Internet ist grob fahrlässig.

1.1. Zielsetzung

Übliche Modelleisenbahn-Bussyssteme wie CAN, BiDiBus, Xpressnet® oder Loconet® sind als Feldbus für die robuste Verkabelung innerhalb der Anlage geeignet. Für einen direkten Anschluss an moderne Endnutzergeräte fehlt diesen jedoch die notwendige Hardwareschnittstelle. Eine Verbindung zu aktueller Computertechnik erfolgt häufig über USB-Adapter und beschränkt sich damit auf stationäre PCs, eine Verwendung von Mobilgeräten (Smartphones, Tablets, Laptops) oder weit entfernten Computern ist nur über Umwege möglich.

Daher entstand die folgende Einbettung des BiDiB-Protokolls in den universellen und allgegenwärtigen IP-Stack. Sie ermöglicht es, die vielerorts bestehende Heimnetzwerk-Infrastruktur zur einfachen Anbindung der Modelleisenbahnansteuerung zu nutzen. Die Netzverbindung kann dabei ein Segment der Baumstruktur eines BiDiB-Systems bilden.

  • Plug & Play ohne Konfiguration
  • Zuverlässige und fehlerfreie Übertragung
  • Uneingeschränkte Übertragungsrate

1.2. Revisionsstand

Dieses Dokument beschreibt Revision 0.1 von netBiDiB, Stand 13. Dezember 2017.

1.3. Glossar

In diesem Dokument werden folgende Bezeichnungen verwendet:

Internet Protocol (IP): Ein Protokoll zur Vermittlung von Datenpaketen in und zwischen Netzwerken. Es kann dabei verschiedene Verbindungen wie Ethernet oder WLAN nutzen.
IP-Adresse: Eine 32- (bei IPv4) oder 128-Bit-Zahl (bei IPv6) zur Identifikation und Verortung eines Rechners.
Port: Eine 16-Bit-Zahl, mit der sich mehrere Verbindungen oder Dienste unterscheiden lassen, die dasselbe Transportprotokoll verwenden.
Transmission Control Protocol (TCP): Ein zuverlässiges, verbindungsorientiertes, paketvermitteltes Transportprotokoll für einen Datenstrom.
User Datagram Protokoll (UDP): Ein minimales, verbindungsloses Transportprotokoll für einzelne Datenpakete.
Server: Der Kommunikationsteilnehmer bei TCP, welcher Verbindungen annimmt.
Client: Der Kommunikationsteilnehmer bei TCP, welcher aktiv Verbindungen öffnet.
netBiDiB-Teilnehmer: Eine physische oder logische Instanz (d.h. eine Baugruppe oder ein laufendes Programm), die als Server oder Client einem netBiDiB-System teilnehmen kann.
Host: Die zentrale Instanz eines BiDiB-Systems, welche die Kontrolle über verbundene Knoten ausübt - i.d.R. ein PC-Programm.
Knoten (Node): Ein Teilnehmer im BiDiB-System, i.d.R. eine Hardware-Baugruppe.
Businterface (Interface): Die Stelle im Bus, an der sich die Knoten anmelden.
Descriptor: Eine Informationsstruktur zur Identifikation und Beschreibung eines Teilnehmers, bestehend mindestens aus einer Unique-ID, einem Produktnamen sowie einem vom Anwender gewählten Namen.

2. Netzwerk

2.1. Architektur

Die Kommunikation zwischen zwei Teilnehmern ist verbindungsorientiert. Eine Busebene mit mehreren BiDiB-Knoten wird durch eine zentrale Instanz gebildet, an der sich die Knoten anmelden: das (Bus-)Interface (kann auch im Hostprogramm integriert sein), welches zu jedem Knoten eine eigene Verbindung aufrecht erhält.

Gleichzeitig kann ein Knoten mit mehreren Interface-Teilnehmern verbunden sein, ist aber höchstens an einem von diesen angemeldet.

Teilnehmer werden in zwei Gruppen unterschieden:

  • Server akzeptieren eingehende Verbindungen. Sie verkünden anderen Teilnehmern ihre Anwesenheit im Netzwerk.
  • Clients öffnen von sich aus Verbindungen zu einem oder mehreren Servern.

Diese Klassifizierung ist nur für den Verbindungsaufbau nach dem Client-Server-Modell entscheidend und impliziert nicht die Rolle des Teilnehmers in einem BiDiB-System. Diese wird erst mit der Anmeldung des Knotens beim Interface festgelegt, bei der die beiden ein gerichtetes Kontrollverhältnis eingehen.

Um Interoperabilität zu garantieren, ist jedoch festgelegt, dass

  • ein Teilnehmer mit Interfacerolle (z.B. ein Hostprogramm) als Client agiert und
  • ein Teilnehmer mit Knotenrolle als Server agiert.

Darüber hinaus darf ein Teilnehmer auf demselben Port sowohl als Client als auch als Server agieren. Dies ermöglicht es beiden Seiten in P2P-Manier, eine TCP-Verbindung zu beginnen und bei Nichtgebrauch zu beenden.

Ein Programm, das mehrere unabhängige Teilnehmer in verschiedenen Rollen implementiert, soll unterschiedliche Ports dafür verwenden.

2.2. Verbindungsaufbau

Prinzipiell gliedert sich eine netBiDiB-Verbindung in folgende Teilaspekte:

  1. Discovery: Finden und Erkennen von netBiDiB-Teilnehmern

    Discovery dient dazu, BiDiB-Knoten zu entdecken und deren BiDiB-Fähigkeiten, Netzwerkadresse und Port für die folgenden Vorgänge zu erfahren. Wegen der dabei nötigen Broadcast-Nachrichten im Netzwerk wird hierfür UDP benutzt. Discovery hilft bei einer anwenderfreundlichen Ausgestaltung des Verbindungsaufbaus.

  2. Linkaufbau: Öffnen der Verbindung

    Mit der Aufnahme der TCP-Verbindung wird ein Kommunikationskanal zwischen zwei netBiDiB-Teilnehmern geöffnet. Zu Beginn werden die Identitäten der beteiligten Teilnehmer ausgetauscht, der Client wird dadurch auch für den Server sichtbar.

    Eine solche Verbindung mit identifiziertem Gegenüber nennen wir Link.

    Der Link kann durch das Schließen der Verbindung aufgelöst werden.

  3. Pairing: Miteinander-Vertraut-Machen von Teilnehmern

    Dies dient dazu, BiDiB-Hostprogramme (bzw. allgemein Interfaces) und BiDiB-Knoten bekannt zu machen und ungewollte Verbindungen mit nicht autorisierten Teilnehmern zu verhindern. Beim Pairing werden andere netBiDiB-Teilnehmer im Netzwerk als prinzipiell mögliche Partner bestimmt und gespeichert. Ein gegenseitiges Vertrautmachen sagt noch nichts über das tatsächliche Kontrollverhältnis aus, ein netBiDiB-Teilnehmer kann mit vielen anderen Teilnehmern zugleich vertraut sein.

    Einen Link, dessen zwei Teilnehmer einander vertrauen, nennen wir paired.

    Der Pairing-Vorgang ist nur einmalig bei der Erstinbetriebnahme erforderlich.

  4. Kontrolle: Anmelden zur Steuerung

    Der Aufbau einer Steuerverbindung zwischen zwei Teilnehmern wird als Logon bezeichnet. Voraussetzung hierfür ist ein (irgendwann vorher) durchgeführtes, erfolgreiches Pairing. Nach erfolgtem Logon kann der Host den Knoten kontrollieren – beginnend mit der BiDiB-Nachricht MSG_SYS_GET_MAGIC.

    Ein Kontrollverhältnis zweier Teilnehmer kann von jeder der beiden Seiten aufgelöst werden, dies ist unabhängig vom Link.

2.4. Teilnehmer

Ein netBiDiB-Teilnehmer muss folgende Bedingungen erfüllen, um als standardkonform zu gelten:

  • Unterstützung des im folgenden beschriebenen Protokolls zum Etablieren eines Links und des Knoten-Logon
  • Eigene Identifikation als netBiDiB-Teilnehmer mittels UID, Produktname und Username
  • Merken des Vertrauens zu mindestens einem anderem Teilnehmer
  • Anzeige des Status der Verbindung bzw. eines Pairingvorgangs
  • Interaktionsmöglichkeit zum Auslösen/Akzeptieren/Ablehnen eines Pairings
  • Interaktionsmöglichkeit zum Auflösen der Kontrollverbindung (oder mehr)
  • Interaktionsmöglichkeit zum Entzug des Vertrauens zu einzelnen (oder allen) gemerkten Teilnehmern

Ein als Client agierender Teilnehmer muss darüber hinaus über eine Möglichkeit verfügen, mindestens eine Verbindung zu öffnen. Der Hostname bzw. die IP-Adresse und der Port des Servers müssen dabei frei wählbar sein, etwa anhand eines Konfigurationseintrages oder durch direkte Eingabe. Eine zusätzliche Möglichkeit zur Auswahl der mittels Discovery gefundenen Server ist optional aber wünschenswert.

Ein Teilnehmer mit graphischer Benutzeroberfläche muss bei der Anzeige anderer Teilnehmer deren Produktname und Username verwenden.

Als Interaktionsmöglichkeit genügt, gerade an Teilnehmern ohne graphische Oberfläche, ein einzelner Knopf. Ein kurzer Knopfdruck soll hier ein Pairing auslösen bzw. akzeptieren und gleichzeitig eine eventuell bestehende Kontrollverbindung beenden. Ein langer Knopfdruck soll allen gespeicherten Teilnehmern das Vertrauen entziehen.

3. Protokoll

3.1. Discovery

Dieser Teil ist noch nicht final verabschiedet.

3.1.1. UDP-Transport

Das User Datagram Protocol (siehe RFC 768) ist ein minimales, verbindungsloses Netzwerkprotokoll zur Übertragung einzelner Datentelegramme. Diese sogenannten Datagramme enthalten Quellport und Zielport zur Identifikation des verantwortlichen Dienstes, ein Längenfeld, eine Prüfsumme und die Nutzdaten. Die Datagramme werden in Pakete des Internet Protocol eingebettet, die u.a. Quell- und Zieladresse vorgeben.

Ein UDP-Datagramm für BiDiB ist prinzipiell wie folgt aufgebaut:

DATAGRAM ::= SOURCE_PORT  DEST_PORT  LENGTH  CHECKSUM  MESSAGE_SEQ
SOURCE_PORT ::= 0x0000 | 0xC000 … 0xFFFF
DEST_PORT ::= 0xC000 … 0xFFFF
LENGTH ::= 0x0008 … 0xFFFF
CHECKSUM ::= 0x0000 … 0xFFFF
MESSAGE_SEQ ::= ε | MESSAGE  MESSAGE_SEQ

Die erste Nachricht im Datagramm muss eine MSG_LOCAL_PROTOCOL_SIGNATURE sein, die einen String mit dem Präfix "BiDiB" als Inhalt hat. Ungenügende Pakete müssen verworfen werden.

Für die Pakete bei BiDiB-Discovery gelten folgende Bestimmungen:

  • Es ist seitens des Netzwerkes nicht garantiert, dass UDP-Pakete in der Sendereihenfolge beim Empfänger eintreffen, obwohl dies (speziell bei einem lokalen Netz) in aller Regel der Fall ist. Daher müssen alle Nachrichten eines Discovery-Broadcasts zusammen in nur einem Datagramm gesendet werden.
  • Es soll ein dynamischer Quellport verwendet werden, unter dem das sendende Programm Antworten empfangen kann. Für AVAILABLE-Broadcasts, die nicht beantwortet werden, kann auch 0 verwendet werden.
  • Nachrichten im Discovery verwenden keine Sequenznummern, MNUM wird als 0 übertragen.

Für Broadcast-Pakete bei BiDiB-Discovery gilt darüber hinaus:

  • Es wird der Zielport 62875 verwendet. Dieser liegt in der Dynamic Ports Range.
  • Es soll die Zieladresse 255.255.255.255 (IPv4: limited broadcast) bzw. ff02::1 (IPv6: link-local all nodes address) verwendet werden.

Um Broadcasts von BiDiB-Discovery zu empfangen, muss die Socket-Option SO_REUSEADDR verwendet werden, um auch anderen Anwendungen auf demselben Rechner den Empfang zu ermöglichen.

3.1.2. Ablauf

Discovery ist eine Komfortfunktion, die das Einbinden eines Netzwerkknotens ohne Konfigurationsdialog ermöglicht. Wo dies nicht funktioniert, ist die manuelle Eingabe von Netzwerkinterface, IP-Adresse und Port nötig.

Ein Client sendet dazu Discover-Datagramme mit folgendem Inhalt als Broadcast über BiDiB-UDP:

MSG_LOCAL_PROTOCOL_SIGNATURE "BiDiB…"
MSG_LOCAL_DISCOVER

Ein Server kündigt seinen Dienst mit Announcement-Datagrammen über BiDiB-UDP an. Sie sollen beim Start des Servers und regelmäßig in einem Intervall von etwa 5 Sekunden als Broadcast gesendet werden. Beim Empfang eines BiDiB-Datagramms mit einer MSG_LOCAL_DISCOVER wird ein Announcement-Datagramm als Unicast an den Absender (Quell-IP-Adresse und -Port) gesendet.

Ihr Inhalt besteht aus mindestens einer Nachricht mit der UID des Servers, gefolgt mindestens von einer Nachricht mit Verbindungsmöglichkeiten:

MSG_LOCAL_PROTOCOL_SIGNATURE  "BiDiB…"
MSG_LOCAL_LINK  DESCRIPTOR_UID  0x…
[ MSG_LOCAL_LINK  DESCRIPTOR_P_VERSION  0  7
  MSG_LOCAL_LINK  DESCRIPTOR_PROD_STRING  "Typ"
  MSG_LOCAL_LINK  DESCRIPTOR_USER_STRING  "Name" ]
MSG_LOCAL_ANNOUNCE  SERVER_TCP_NODE  tcp_port
[…]

Das Senden des kompletten Descriptors ist optional.

Ein Client beginnt mit dem Discover-Schritt automatisch beim Programmstart oder wenn eine neue Verbindung eingerichtet werden soll. Empfängt ein Client ein Announcement eines Servers, mit dem er bereits vertraut ist, soll er automatisch zu diesem eine Verbindung aufbauen. Zu den unbekannten Servern soll nur dann eine Verbindung aufgebaut werden, wenn der Anwender dies wünscht.

3.2. Verbindung

3.2.1. TCP-Transport

Das Transmission Control Protocol (siehe RFC 793 und weitere) überträgt einen bidirektionalen, byte-orientierten, zuverlässigen Datenstrom zwischen zwei Endpunkten. Es garantiert die korrekte Auslieferung der Daten in der vorgegebenen Reihenfolge und eignet sich daher auch zur Übertragung über störungsempfindliche Kanäle wie WLAN. Darüber hinaus wird es von Firewalls in Standardkonfiguration seltener behindert als UDP. BiDiB verwendet TCP für die Übertragung von Steuernachrichten zwischen Knoten.

Die Endpunkte werden jeweils durch IP-Adresse und Portnummer identifiziert. Für BiDiB werden Portnummern aus dem Bereich der dynamischen Ports verwendet (49152-65535), diese werden vom Betriebssystem dynamisch an Programme vergeben werden. Der serverseitige Port soll auch vom Anwender einstellbar sein, als Default wird 62875 genutzt.

Der Datenstrom ist wie folgt aufgebaut:

STREAM ::= EMITTER  MESSAGE_SEQ
MESSAGE_SEQ ::= ε | MESSAGE  MESSAGE_SEQ
EMITTER ::= 0x08  0x00  0x00  MSG_LOCAL_PROTOCOL_SIGNATURE  'B'  'i'  'D'  'i'  'B'

Der Datenstrom besteht aus einer Folge von BiDiB-Nachrichten. Diese unterscheiden sich in lokale Nachrichten und normale, an den angemeldeten Knoten gerichtete Nachrichten. Normale Nachrichten werden vom Knoten erst dann interpretiert, wenn er erfolgreich angemeldet ist.

EMITTER bezeichnet die erste Nachricht und muss zwingend eine MSG_LOCAL_PROTOCOL_SIGNATURE sein, die einen String mit dem Präfix "BiDiB" als Inhalt hat. Dies ermöglicht die Erkennung eines versehentlichen, protokollfremden Datenstroms. Scheitert die Prüfung, wird die Verbindung unmittelbar geschlossen. MSG_LOCAL_PROTOCOL_SIGNATURE darf (und soll) auch während der Übertragung wiederholt werden um die TCP-Pakete zu kennzeichnen.

Bei der Datenübertragung ist das maximal mögliche Antwortvolumen von 48 Bytes je Zielknoten zu beachten und fallweise der Datenstrom pro Zielknoten zu drosseln. Für Nachrichten an den angemeldeten Knoten (Adresse 0) sowie für den Upstream wird die TCP-Flusskontrolle zur Beschränkung genutzt.

Um eine möglichst geringe Latenz zu erreichen, sollen Teilnehmer die Socket-Option TCP_NODELAY setzen.

3.2.2. Linkaufbau

Ein Client ermöglicht dem Anwender, zu beliebigen Adressen und Ports eine TCP-Verbindung aufzunehmen. Unterstützt ein Client Discovery, öffnet er automatisch Verbindungen zu bekannten Servern, sobald diese sichtbar werden.

Jeder Teilnehmer verfügt über einen Descriptor, der neben der Unique-ID zur Identifikation vor allem den Produktnamen und den Usernamen zur anwenderfreundlichen Darstellung enthält sowie weitere nützliche Details zur Auswahl eines Links. Ein Host soll als Produktnamen den Programmnamen und als Username einen vom Anwender wählbaren Namen verwenden, beispielsweise den Dateinamen der Anlagendatei oder den Computernamen. Für die Unique-ID soll ein Host eine Seriennummer zufällig generieren und in der Anlagendatei hinterlegen, Klassenbits hat er nicht gesetzt.

Nach dem Öffnen der TCP-Verbindung beginnen beide Teilnehmer mit dem Senden ihres Deskriptors:

MSG_LOCAL_PROTOCOL_SIGNATURE  "BiDiB"
MSG_LOCAL_LINK  DESCRIPTOR_UID  0x...
MSG_LOCAL_LINK  DESCRIPTOR_P_VERSION  0  7
MSG_LOCAL_LINK  DESCRIPTOR_PROD_STRING  "Typ"
MSG_LOCAL_LINK  DESCRIPTOR_USER_STRING  "Name"

Den Empfang der DESCRIPTOR_UID quittiert das Gegenüber mit MSG_LOCAL_LINK und einem Status, ob ihm die Unique-ID bereits vertraut ist (STATUS_PAIRED) oder nicht (STATUS_UNPAIRED).

Sobald beide Seiten den Pairing-Status empfangen haben, ist der Link aufgebaut. Haben beide Seiten STATUS_PAIRED gesendet, gilt der Link als paired und eine Knotenanmeldung kann erfolgen.

3.2.3. Pairing

Sind die beiden Teilnehmer nicht miteinander vertraut, so muss ein explizites Pairing durch den Anwender durchgeführt werden. Dieser bestätigt dabei an beiden Teilnehmern, dass der Link legitim ist. Erst danach wird die Kontrollausübung erlaubt.

Eine solche Bestätigung des Vertrauens kann prinzipiell auf beliebigem Wege erfolgen, z.B. durch Hinzufügen eines Konfigurationseintrages. Um das Pairing nutzerfreundlich zu gestalten, sieht BiDiB jedoch auch einen Handshake im Protokoll vor. Damit ist es möglich, durch einen einfachen Knopfdruck auch ohne graphische Oberfläche die Bestätigung durchzuführen.

Der Handshake ist symmetrisch aufgebaut. Er kann von jedem der Teilnehmer mit einem PAIRING_REQUEST initiiert werden. Beim Empfang eines Antrags von einem noch nicht vertrauten Gegenüber zeigt der Teilnehmer dies an, wartet dann eine Zeit lang auf die Annahme durch den Anwender und sendet selbst einen PAIRING_REQUEST sobald eine explizite Bestätigung erfolgt.

Ein Antrag wird mit einem Pairing-Status zur Zustimmung (STATUS_PAIRED) oder Ablehnung (STATUS_UNPAIRED) beantwortet, entweder sofort bei bereits feststehendem Verhalten oder nach der Anwenderinteraktion.

Wurde der Antrag angenommen, speichern beide Teilnehmer beim Empfang von STATUS_PAIRED den neuen Partner als vertrauenswürdig, sodass das Pairing beim nächsten Verbindungsaufbau nicht erneut durchgeführt werden muss. Der Link gilt nun als paired und ein Logon kann erfolgen.

Durch das Senden von MSG_LOCAL_LINK STATUS_UNPAIRED kann das Vertrauen jederzeit wieder entzogen werden. Eine Steuerung ist dann nicht mehr möglich.

3.2.4. Anmeldung

Auf einem paired Link kann sich der Knoten nun beim Businterface anmelden. Stehen mehrere Möglichkeiten zur Auswahl, entscheidet sich der Knoten für einen davon. Insbesondere nach dem Starten des Knotens soll hier nach dem initialen Announcement ein wenig gewartet werden, um allen interessierten Clients einen Linkaufbau zu ermöglichen. Der Knoten soll dasjenige Interface bevorzugen, bei dem er zuletzt (für längere Zeit) angemeldet war, ein Anlagenbetrieb kann so mit demselben Hostprogramm fortgesetzt werden, das bereits bei Betriebsschluss aktiv war. Ebenfalls bevorzugt werden sollen Links, auf denen zuletzt ein PAIRING_REQUEST empfangen wurde.

Der Knoten sendet zur Anmeldung MSG_LOCAL_LOGON mit seiner Unique-ID. Das Interface kann den Logon akzeptieren (MSG_LOCAL_LOGON_ACK) oder verweigern (MSG_LOCAL_LOGON_REJECTED), in letzterem Falle soll der Knoten evtl. bestehende andere Links durchprobieren.

Wurde der Logon akzeptiert, ist der Knoten nun angemeldet und lässt sich kontrollieren. Das Interface kann den Knoten nun in seine Nodetabelle eintragen (und eventuell mittels MSG_NODE_NEW zu seinem Host melden), der Host kann nun mit MSG_SYS_GET_MAGIC und dem typischen Protokollstart beginnen.

Die Anmeldung kann von beiden Seiten jederzeit zurückgenommen werden, vom Interface mittels MSG_LOCAL_LOGON_REJECTED und vom Knoten mittels MSG_LOCAL_LOGOFF.

3.3. Beispiele

Eine typische Startsequenz sieht beispielhaft folgendermaßen aus (die beiden Teilnehmer sind bereits miteinander vertraut):

  Host (Client) 0x0D 933C8A6C                                             Knoten (Server) 0x0D 0278456B
Discovery:
MSG_LOCAL_PROTOCOL_SIGNATURE  "BiDiB"                              UDP>
MSG_LOCAL_DISCOVER                                                 UDP>
                                                                        <UDP  MSG_LOCAL_PROTOCOL_SIGNATURE  "BiDiB"
                                                                        <UDP  MSG_LOCAL_LINK  DESCRIPTOR_UID  0xC000 0D 0278456B
                                                                        <UDP  MSG_LOCAL_ANNOUNCE  SERVER_TCP_NODE  0xF5  0x9B
Verbindung (auf Port 0xF59B / 628759):
                                                               SYN TCP>
                                                                        <TCP SYN/ACK
                                                               ACK TCP>
Beide Teilnehmer senden EMITTER als erste Nachricht
MSG_LOCAL_PROTOCOL_SIGNATURE  "BiDiB"                              TCP> <TCP  MSG_LOCAL_PROTOCOL_SIGNATURE  "BiDiB"
und beginnen (unabhängig voneinander), die Teile ihres Descriptors zu senden (in beliebiger Reihenfolge):
MSG_LOCAL_LINK  DESCRIPTOR_UID  0x00000D933C8A6C                   TCP> <TCP  MSG_LOCAL_LINK  DESCRIPTOR_PROD_STRING  "Raspi-Ethernet-Hub"
                                                                        <TCP  MSG_LOCAL_LINK  DESCRIPTOR_USER_STRING  "Messeanlage-Master"
                                                                        <TCP  MSG_LOCAL_LINK  DESCRIPTOR_P_VERSION  0  6
                                                                        <TCP  MSG_LOCAL_LINK  DESCRIPTOR_UID  0xC0000D0278456B
Der Empfang der UIDs etabliert den Link und wird jeweils mit dem Pairing-Status bestätigt:
MSG_LOCAL_LINK  STATUS_PAIRED  0x00000D933C8A6C  0xC0000D0278456B  TCP>
                                                                        <TCP  MSG_LOCAL_LINK  STATUS_PAIRED  0xC0000D0278456B 0x00000D933C8A6C
(der Host sendet hier weiter seinen Descriptor)
MSG_LOCAL_LINK  DESCRIPTOR_P_VERSION  0  7                         TCP>
MSG_LOCAL_LINK  DESCRIPTOR_PROD_STRING  "Wizard"                   TCP>
MSG_LOCAL_LINK  DESCRIPTOR_USER_STRING  "Richard"                  TCP>
Der Knoten meldet sich nun an:
                                                                        <TCP  MSG_LOCAL_LOGON  0xC0000D0278456B
MSG_LOCAL_LOGON_ACK  0x00  0xC0000D0278456B                        TCP>
MSG_SYS_GET_MAGIC                                                  TCP>
                                                                        <TCP  MSG_SYS_MAGIC  0xAFFE
MSG_SYS_GET_P_VERSION                                              TCP>
MSG_NODETAB_GETALL                                                 TCP>
MSG_FEATURE_GETALL                                                 TCP>

Beachtenswert ist die unterschiedliche Reihenfolge und das Durcheinander bei den MSG_LOCAL_LINK im Beispiel. Die einzige Einschränkung ist, dass erst nach dem Senden der eigenen und dem Empfang der fremden UID der Pairing-Status (STATUS_PAIRED bzw. STATUS_UNPAIRED) gesendet wird. Descriptorteile außer der UID können auch jederzeit auf einem bereits aufgebauten Link gesendet werden, etwa wenn sich der Name des Teilnehmers ändert.

Sind die Teilnehmer nicht miteinander vertraut, so ist ein Pairing durch den Anwender nötig und die Verbindung beginnt beispielsweise wie folgt:

  Host (Client) 0x0D 933C8A6C                                             Knoten (Server) 0x0D 0278456B
                                                                 SYN TCP>
                                                                          <TCP SYN/ACK
                                                                 ACK TCP>
Beide Teilnehmer beginnen:
MSG_LOCAL_PROTOCOL_SIGNATURE  "BiDiB"                                TCP> <TCP  MSG_LOCAL_PROTOCOL_SIGNATURE  "BiDiB"
MSG_LOCAL_LINK  DESCRIPTOR_UID  0x00000D933C8A6C                     TCP> <TCP  MSG_LOCAL_LINK  DESCRIPTOR_PROD_STRING  "Raspi-Ethernet-Hub"
MSG_LOCAL_LINK  DESCRIPTOR_PROD_STRING  "Wizard"                     TCP> <TCP  MSG_LOCAL_LINK  DESCRIPTOR_USER_STRING  "Messeanlage-Master"
                                                                          <TCP  MSG_LOCAL_LINK  DESCRIPTOR_P_VERSION  0  6
                                                                          <TCP  MSG_LOCAL_LINK  DESCRIPTOR_UID  0xC0000D0278456B
Der Empfang der UIDs etabliert den Link und wird jeweils mit dem Pairing-Status bestätigt:
MSG_LOCAL_LINK  STATUS_UNPAIRED  0x00000D933C8A6C  0xC0000D0278456B  TCP>
MSG_LOCAL_LINK  DESCRIPTOR_P_VERSION  0  7                           TCP>
MSG_LOCAL_LINK  DESCRIPTOR_USER_STRING  "Richard"                    TCP> <TCP  MSG_LOCAL_LINK  STATUS_UNPAIRED  0xC0000D0278456B 0x00000D933C8A6C
Der Link ist nun unpaired (es genügt dazu auch UNPAIRED von nur einer Seite).

[Anweder löst Pairing am Host aus]
MSG_LOCAL_LINK  PAIRING_REQUEST  0x00000D933C8A6C  0xC0000D0278456B  TCP>
Der Knoten signalisiert den eingegangenen Request und wartet.                                                                  [Timeout im Knoten]
                                                                          <TCP  MSG_LOCAL_LINK  STATUS_UNPAIRED  0xC0000D0278456B 0x00000D933C8A6C
Der Request wurde nicht im gegebenen Zeitraum akzeptiert, der Link ist weiter unpaired.
[Anwender löst Pairing am Host aus] (erneut)
MSG_LOCAL_LINK  PAIRING_REQUEST  0x00000D933C8A6C  0xC0000D0278456B  TCP>
                                                                                                             [Anwender löst Pairing am Knoten aus]
                                                                          <TCP  MSG_LOCAL_LINK  PAIRING_REQUEST  0xC0000D0278456B 0x00000D933C8A6C
Nach einem ausgelösten Pairing werden die empfangenen Pairing-Requests jeweils akzeptiert:
MSG_LOCAL_LINK  STATUS_PAIRED  0x00000D933C8A6C  0xC0000D0278456B    TCP> <TCP  MSG_LOCAL_LINK  STATUS_PAIRED  0xC0000D0278456B 0x00000D933C8A6C
Der Link ist nun paired und der Knoten meldet sich an:
                                                                          <TCP  MSG_LOCAL_LOGON  0xC0000D0278456B
MSG_LOCAL_LOGON_ACK  0x00  0xC0000D0278456B                          TCP>
MSG_SYS_GET_MAGIC                                                    TCP>

Die Reihenfolge der beiden Nachrichten bei der Annahme des Pairings ist beliebig. Genauso denkbar ist:

                                                                         …
MSG_LOCAL_LINK  PAIRING_REQUEST  0x00000D933C8A6C  0xC0000D0278456B  TCP>
                                                                          <TCP  MSG_LOCAL_LINK  STATUS_PAIRED  0xC0000D0278456B 0x00000D933C8A6C
                                                                          <TCP  MSG_LOCAL_LINK  PAIRING_REQUEST  0xC0000D0278456B 0x00000D933C8A6C
MSG_LOCAL_LINK  STATUS_PAIRED  0x00000D933C8A6C  0xC0000D0278456B    TCP>

Die Annahme des Pairings kann auch ohne einen zweiten PAIRING_REQUEST erfolgen, wenn ein Teilnehmer den anderen bereits kennt. Für den ersten Teilnehmer ändert sich dadurch nichts.

4. Lokale Nachrichten

Lokale Nachrichten dienen zum Aushandeln der Transportverbindung. Sie sind vom Aufbau identisch zu normalen BiDiB-Nachrichten, werden aber nicht an andere Busteilnehmer weitergeroutet. Lokale Nachrichten werden nicht in das Sequencing einbezogen. Ihr MSG_ADDR_STACK ist leer, MSG_ADDR und MSG_NUM sind mit 0x00 kodiert.

  • MSG_LOCAL_PROTOCOL_SIGNATURE:

    Mit dieser Nachricht wird die Art des Datenstromes angekündigt. Der Dateninhalt ist eine Bytefolge, die mit den 5 ASCII-Zeichen 'B' 'i' 'D' 'i' 'B' beginnen muss.

    Weitere Zeichen hinter 'BiDiB' sind möglich und erwünscht, um den Absender für Debuggingzwecke zu kennzeichnen. Diese weiteren Zeichen haben sonst keine Bedeutung und dürfen nicht ausgewertet werden.

    Die Nachricht hat keine Antwort zur Folge, der Empfänger muss aber den String 'BiDiB' abprüfen. Sollte die Prüfung scheitern, wird die TCP-Verbindung geschlossen, es handelt sich offensichtlich um protokollfremde Daten.

  • MSG_LOCAL_LINK:

    Mit dieser Nachricht wird ein Link hergestellt und bestätigt sowie dessen Status geändert. Es folgen ein OPCODE und davon abhängig zusätzliche Daten. Sie kann von beiden Seiten der Verbindung und zu jeder Zeit gesendet werden.

    Kodierung des Opcode für Linkverwaltung
    WertNameBedeutung
    0xFF BIDIB_LINK_DESCRIPTOR_UID Der Sender baut von seiner Seite den Link (fallweise neu) auf.
    Es folgt die Unique-ID des Senders (7 Byte).
    Der Empfänger antwortet mit STATUS_PAIRED oder STATUS_UNPAIRED.
    0x00 BIDIB_LINK_DESCRIPTOR_PROD_STRING Der Sender verkündet seinen Produktnamen, entsprechend String 0 im Namespace 0 (siehe MSG_STRING).
    Es folgt ein Byte SIZE (0…24) und dementsprechend viele CHARs.
    0x01 BIDIB_LINK_DESCRIPTOR_USER_STRING Der Sender verkündet seinen Usernamen, entsprechend String 1 im Namespace 0 (siehe MSG_STRING).
    Es folgt ein Byte SIZE (0…24) und dementsprechend viele CHARs.
    0x80 BIDIB_LINK_DESCRIPTOR_P_VERSION Der Sender verkündet seine unterstützte Protokollversion.
    Es folgen 2 Bytes, Kodierung wie MSG_SYS_P_VERSION.
    0xFC BIDIB_LINK_PAIRING_REQUEST Der Sender initiiert ein Pairing beziehungsweise entgegnet den Handschlag. Vorraussetzung ist ein bereits aufgebauter Link (d.h. ausgetauschte UIDs). Eine Nachricht mit diesem Opcode darf nur infolge einer expliziten Anwenderinteraktion erfolgen.
    Es folgen 14 Byte mit der Unique-ID des Senders und der Unique-ID des beabsichtigten Empfängers.
    Der Empfänger antwortet (eventuell verzögert) mit STATUS_PAIRED oder STATUS_UNPAIRED.
    0xFD BIDIB_LINK_STATUS_UNPAIRED Der Sender verweigert das Vertrauen.
    Es folgen 14 Byte mit der Unique-ID des Senders und der Unique-ID des beabsichtigten Empfängers.
    Sender und Empfänger setzen ihren Linkstatus auf unpaired. Eine Überprüfung der Unique-IDs ist dazu nicht nötig.
    0xFE BIDIB_LINK_STATUS_PAIRED Der Sender spricht das Vertrauen aus. Vorraussetzung ist ein bereits aufgebauter Link (d.h. ausgetauschte UIDs).
    Es folgen 14 Byte mit der Unique-ID des Senders und der Unique-ID des beabsichtigten Empfängers.
    Der Empfänger merkt sich den Partner und setzt seinen Linkstatus auf paired, wenn er dem Sender vertraut. Eine Überprüfung der Unique-IDs ist möglich aber optional.
  • MSG_LOCAL_LOGON:

    Mit dieser Nachricht wird die Anmeldung durch den Knoten eingeleitet, er möchte sich vom Host kontrollieren lassen. Vorraussetzung ist ein paired Link. Das Businterface antwortet mit MSG_LOCAL_LOGON_ACK oder MSG_LOCAL_LOGON_REJECTED. Es folgen 7 Byte:

    MSG_LOCAL_LOGON Parameter
    ParameterBeschreibung
    UID[7] Die Unique-ID des Knotens.

    Hinweis: Die Klassenbits der anzumeldenden Unique-ID müssen dabei nicht unbedingt mit denen der beim Linkaufbau verwendeten Unique-ID übereinstimmen.

  • MSG_LOCAL_LOGON_ACK:

    Mit dieser Nachricht wird ein LOGON durch das Interface bestätigt. Der Host kann nun mit MSG_SYS_MAGIC und dem Einlesen des Knotens beginnen. Vorraussetzung ist ein paired Link. Es folgen 8 Byte:

    MSG_LOCAL_LOGON_ACK Parameter
    ParameterBeschreibung
    NODE Die lokale BiDiB-Adresse, unter der das Interface den Knoten eingebucht hat, oder 0 falls das Interface (z. B. im Host) keine eigene Busebene darstellt.
    UID[7] Die Unique-ID des Knotens.

    Hinweis: NODE wird dabei nicht für das Routing benötigt, das erledigt das Interface anhand der TCP-Verbindung. Sie ist nur für Debugging im Knoten bestimmt.

    Nur wenn die empfangene Unique-ID identisch zu der internen Unique-ID des Knotens ist, ist die Anmeldung gültig.

  • MSG_LOCAL_LOGON_REJECTED:

    Mit dieser Nachricht wird ein LOGON durch das Interface abgelehnt beziehungsweise ein bestehende Kontrollverhältnis wieder aufgelöst. Es folgen 7 Byte:

    MSG_LOCAL_LOGON_REJECTED Parameter
    ParameterBeschreibung
    UID[7] Die Unique-ID des betroffenen Knotens.
  • MSG_LOCAL_LOGOFF:

    Mit dieser Nachricht meldet sich ein Knoten vom Interface ab und unterliegt damit nicht mehr der Kontrolle durch den Host. Er interpretiert danach nur noch lokale Nachrichten. Es folgen 7 Byte:

    MSG_LOCAL_LOGON Parameter
    ParameterBeschreibung
    UID[7] Die Unique-ID des Knotens.
  • MSG_LOCAL_DISCOVER:

    Mit dieser Nachricht bittet ein Client alle Server im Netz, ihre Dienste anzukündigen. Es folgen keine Daten.

    Ein Server antwortet mit MSG_LOCAL_LINK DESCRIPTOR UID und einer oder mehreren MSG_LOCAL_ANNOUNCE.

  • MSG_LOCAL_ANNOUNCE:

    Mit dieser Nachricht kündigt ein Server allen Clients im Netz seine Dienste an. Es folgen ein OPCODE und davon abhängig zusätzliche Daten:

    Kodierung des Opcode für Serverdienste
    WertNameBedeutung
    0x00 BIDIB_ANNOUNCEMENT_SERVER_TCP_NODE Der Teilnehmer stellt einen BiDiB-TCP-Server bereit. Es folgen 2 Byte (TCP_PORTH und TCP_PORTL, in Network Byte Order!) mit der Portnummer des Servers. Die IP-Adresse des Servers ist die Senderadresse des UDP-Pakets.
  • MSG_LOCAL_SYNC:

    Diese Nachricht wird regelmäßig vom Interface zur Synchronisation der BiDiB-Systemzeit gesendet. Die Nachricht kodiert den Zeitpunkt des Absendens einmal als BiDiB-Systemzeitstempel und einmal als Zeitstempel mit der Systemzeit des Computers, auf dem das Interface läuft. Die netBiDiB-Teilnehmer synchronisieren ihre Uhren über das Network Time Protocol (NTP, siehe RFC 5905), mit der MSG_LOCAL_SYNC gibt das Interface dann nur noch den Offset zwischen UTC und BiDiB Systemzeit vor.

    MSG_LOCAL_SYNC Parameter
    ParameterBeschreibung
    TIMEL BiDiB Systemzeitstempel, 16 bit little endian.
    TIMEH
    UTC[8] Millisekunden seit dem 1. Januar 1970 00:00:00 UTC (Unix Epoch), 64 bit little endian.

    Mit der Referenz auf eine NTP-synchronisierte Uhr wird der negative Einfluss der variablen Netzwerklatenz und TCP-Flusskontrolle vermieden. Dennoch soll ein Knoten die Nachricht verwerfen, wenn seine Systemuhrzeit um mehr als eine Sekunde von dem übertragenen Wert abweicht.

    Sollte ein Knoten über keine NTP-Synchronisierung verfügen, so muss er den BiDiB-Systemzeitstempel bestmöglich interpretieren, z.B. durch Berücksichtigung der typischen Netzwerklatenz (die in der Regel in einem lokalen Netzwerk im Bereich unter 5 ms liegt).