# BACnet

> BACnet/IP-Geräte der Gebäudeautomation anbinden - Geräteinstanz, Adressierung über Objekttyp und Instanz, Gerätesuche über Who-Is und presentValue.

Der Treiber **BACnet** spricht mit Anlagen der Gebäudeautomation über BACnet/IP. Jedes Tag
liest den aktuellen Wert (**present value**) eines BACnet-Objekts: den Messwert eines
analogen Eingangs, den Zustand eines binären Ausgangs, die Stellung eines Multi-State-Werts.
Legen Sie im [Connector](connector) ein Gerät unter dem Treiber BACnet an; der Bereich
zeigt nur die Felder, die dieses Protokoll verwendet.

## Verbindung {#connection}

| Feld | Bedeutung | Standard |
| --- | --- | --- |
| **Hostadresse** | IP-Adresse oder Hostname des BACnet-Geräts (oder des Routers, der für es antwortet). Ein Name wird beim Verbinden in seine IPv4-Adresse aufgelöst; ein Name, den dieser Rechner nicht auflösen kann, lässt das Gerät ohne Verbindung, und der Grund sagt das. | leer |
| **Port** | UDP-Port des Geräts, 1 bis 65535. Ein leeres Feld zeigt 47808, den Standard von BACnet/IP, grau, und das Gerät wird über diesen Port erreicht; ein mit 0 gespeichertes Gerät liest sich genauso. | 47808 |
| **Geräte-ID** | Die Instanznummer des Geräts, also die Nummer seines Objekts Device, eindeutig im BACnet-Netz. | 0 |

Die Kopfzeile des Geräts zeigt den zusammengesetzten Endpunkt, zum Beispiel
`bacnet://192.168.0.30:47808/1234`. Das Verbinden sendet eine Anfrage nach der Größe der
Objektliste des Geräts, um zu bestätigen, dass die Anlage antwortet; die Objektliste selbst
wird nicht durchlaufen. Diese Antwort ist die Verbindung: Ein Gerät, das nicht antwortet,
bleibt offline, statt als verbunden zu erscheinen, und der Grund (der UDP-Port ist schon
belegt, eine Adresse, die keine Adresse ist) wird auf die Seite Ereignisse und in die
Protokolldatei des Tages geschrieben. Für diesen Treiber gibt es keine Felder für das
Abfrageintervall: Seine Tags werden einmal je Sekunde gelesen.

## Adressierung {#addressing}

Ein BACnet-Tag wird über zwei typisierte Felder auf der Karte Quelle des Tags adressiert,
ganz ohne Freitextadresse:

| Feld | Bedeutung | Angenommene Werte | Standard |
| --- | --- | --- | --- |
| **Objekttyp** | Welche Art BACnet-Objekt gelesen wird. | die neun Typen unten | `AnalogInput` |
| **Instanz** | Die Instanznummer des Objekts innerhalb seines Typs. | 0 und aufwärts | 0 |

Die angebotenen Objekttypen und ihre üblichen BACnet-Typcodes:

| Objekttyp | Code | Der aktuelle Wert hält |
| --- | --- | --- |
| `AnalogInput` | 0 | eine gemessene Zahl |
| `AnalogOutput` | 1 | eine befohlene Zahl |
| `AnalogValue` | 2 | eine gespeicherte Zahl |
| `BinaryInput` | 3 | inaktiv/aktiv |
| `BinaryOutput` | 4 | inaktiv/aktiv |
| `BinaryValue` | 5 | inaktiv/aktiv |
| `MultiStateInput` | 13 | eine Zustandsnummer ab 1 |
| `MultiStateOutput` | 14 | eine Zustandsnummer ab 1 |
| `MultiStateValue` | 19 | eine Zustandsnummer ab 1 |

`AnalogInput` 5 am Gerät 1234 bedeutet "der aktuelle Wert des analogen Eingangs 5 dieses
Geräts". Jeder Lesevorgang fragt die Eigenschaft `presentValue` des Objekts ab; andere
Eigenschaften sind nicht adressierbar. Die Zeile **Quelladresse (Bus)** auf der Karte
Quelle, die nur gelesen wird, zeigt das zusammengesetzte Paar `type,instance`, während Sie
tippen.

## Datentypen {#data-types}

Die Auswahl **Datentyp** bietet vier Typen an. Wählen Sie den, der zum Objekt passt:

| Datentyp | Passt zu | Hinweise |
| --- | --- | --- |
| Float | analogen Objekten | ein aktueller Wert vom Typ Real; Werte doppelter Genauigkeit werden auf Float verengt |
| Boolean | binären Objekten | ein aktueller Wert vom Typ Boolean oder die aufgezählten 0 und 1, mit denen ein binäres Objekt antwortet |
| Int32 | Multi-State- und anderen ganzzahligen Werten | vorzeichenbehaftete, vorzeichenlose und aufgezählte Antworten landen alle hier |
| String | Werten vom Typ Zeichenkette | Text, wie das Gerät ihn sendet |

Der gewählte Typ muss zu dem passen, was das Objekt hält. Ein Gerät, das mit etwas anderem
antwortet, lässt den Lesevorgang dieses Tags fehlschlagen: Das Tag geht auf schlechte
Qualität, und der Grund nennt, was ankam ("Das Gerät hat mit einem Wert vom Typ Single auf
einen Punkt geantwortet, der als Integer erklärt ist."), statt dass eine umgerechnete Zahl
in Verlauf, Historie und Alarme gerät. Ein analoges Objekt als Boolean zu lesen oder ein
Real als Int32 ist genau dieser Fall. Der Rest des Geräts liest weiter; wegen eines Tags
mit falschem Typ wird nichts neu verbunden.

Ein Tag, dessen Objekt das Gerät nicht hat, schlägt beim Lesen mit der eigenen
Antwort des Geräts fehl: Der Grund sagt, dass das Gerät an dieser Adresse kein
Objekt hat, und nennt den Fehler, den es gesendet hat (`ERROR_CODE_UNKNOWN_OBJECT`).
So unterscheidet sich eine falsche Adresse von einem Gerät, das nicht mehr
antwortet. Das Gerät bleibt verbunden.

## Schreiben {#writes}

Tags, deren **Zugriff** Lesen und schreiben oder Nur schreiben ist, lassen sich schreiben. Ein
Schreibvorgang setzt den `presentValue` des Objekts in dem Datentyp, den die BACnet-Norm
dieser Art von Objekt gibt, unabhängig vom Datentyp des Tags:

| Objekt | Geschrieben als | Nimmt |
| --- | --- | --- |
| Binärer Eingang, Ausgang oder Wert | Enumerated | inaktiv (0) oder aktiv (1), aus einem Boolean-Tag oder einem Int32 mit 0 oder 1 |
| Multi-State-Eingang, -Ausgang oder -Wert | Unsigned | eine Zustandsnummer ab 1 |
| Analoger Eingang, Ausgang oder Wert | Real | eine Zahl aus einem Float- oder Int32-Tag |
| Jeder andere Objekttyp | der Datentyp des Tags | Float ein Real, Boolean ein Boolean, Int32 eine vorzeichenbehaftete Ganzzahl, String eine Zeichenkette |

Eine Befehlspriorität wird mit dem Schreibvorgang nicht gesendet. Ein Wert, den das Objekt
nicht halten kann, etwa 0 für ein Multi-State-Objekt oder 2 für ein binäres, wird abgelehnt,
bevor etwas gesendet wird, und die Ablehnung nennt den Grund. Antwortet das Gerät auf den
Schreibvorgang mit einem Fehler, meldet das Tag die Fehlerklasse und den Fehlercode, die das
Gerät gesendet hat, statt Erfolg vorzutäuschen, und das Gerät bleibt verbunden. Ein neues Tag
beginnt als Nur lesen.

## Gerätesuche {#discovery}

Die Schaltfläche Suchen des Connector sendet ein BACnet **Who-Is** als Rundruf und hört 10
Sekunden lang auf Antworten vom Typ **I-Am**. Jedes Gerät, das antwortet, wird zu einem
Kandidaten, der seine Adresse, seinen Port und seine Geräteinstanz trägt, fertig zum
Hinzufügen mit ausgefüllten Verbindungsfeldern, und es erscheint in der Liste in dem
Augenblick, in dem es antwortet, nicht erst am Ende der zehn Sekunden: Ein Suchlauf, den
Sie auf halbem Weg abbrechen, behält alles, was bereits geantwortet hatte. Der Suchlauf
durchsucht keine Objekte, Kandidaten kommen also mit null Tags an; die Paare aus Objekttyp
und Instanz tragen Sie selbst ein.

Das Who-Is geht in dem Netz hinaus, das die Karte **Suchbereich** nennt. Ihr Feld
nimmt eine IPv4-Adresse in diesem Netz, die eines Geräts oder die eigene Adresse
dieses Rechners dort (zum Beispiel `192.168.1.20`), und der Suchlauf sendet seinen
Rundruf dann nur in diesem Netz. Bleibt es leer, geht das Who-Is in jedes Netz dieses
Rechners hinaus, sodass ein Rechner mit zwei Netzwerkkarten, einem VPN oder Docker die
Geräte in jedem davon findet. Was keine vollständig ausgeschriebene IPv4-Adresse ist,
wird unter dem Feld abgelehnt, und Suchen bleibt ausgegraut, bis es berichtigt ist.

Ein Gerät, das **über einen BACnet-Router** antwortet, wird genauso hinzugefügt. Sein
Kandidat trägt die Adresse des Routers und daneben das eigene Netz des Geräts und seine
Adresse in diesem Netz; beides bleibt erhalten, wenn Sie es hinzufügen, und jeder
Lesevorgang geht an den Router und nennt das Gerät dahinter. Ein so gefundenes Gerät liest
sich daher wie jedes andere, und sein Endpunkt liest sich "Gerät über Router". Ein von Hand
angelegtes Gerät hat keine Route und wird unmittelbar an seinem Host erreicht.

## Gut zu wissen {#good-to-know}

- Nur BACnet/IP: Anlagen mit MS/TP oder BACnet/SC sind nur über einen Router erreichbar,
  der sie auf BACnet/IP darstellt, und der Suchlauf ist das, was sie findet: Die Route, auf
  der ein Gerät antwortet, wird aus dem Suchlauf übernommen, fügen Sie es also aus der
  Fundliste hinzu, statt seine Felder von Hand einzutippen.
- Auf einem Rechner mit mehreren Netzwerkschnittstellen (zwei Netzwerkkarten, ein
  VPN, Docker) wird jedes Gerät über die Schnittstelle erreicht, über die dieser
  Rechner seine Adresse leitet, dieselbe, die jedes andere Programm hier nähme; es ist
  nichts auszuwählen.
- Nur der Socket, der auf die Nachrichten der Geräte hört, liegt auf dem üblichen
  BACnet-UDP-Port 47808 dieser Station; deshalb kann eine andere BACnet-Anwendung, die
  diesen Port auf demselben Rechner ausschließlich hält, mit ihm in Streit geraten.
  Anfragen an ein Gerät gehen von einem Port aus, den das System für jeden Client wählt.
- Das zyklische Lesen liegt bei diesem Treiber für jedes Tag fest bei einer Sekunde; die
  üblichen Felder für das Abfrageintervall werden nicht gezeigt.
