# BACnet

BACnet is a data communication protocol for **B**uilding **A**utomation and **C**ontrol **net**works. A data communication protocol is a set of rules governing the exchange of data over a computer network. The rules take the form of a written specification that spells out what is required to conform to the protocol.

For more information, see [BACnet.org](https://www.bacnet.org/).

## BACnet Glossary

### Device

The device represents a server that is managing one or more BACnet objects. A device has a unique device instance number (which is sufficient for addressing if using the same network interface) and a unique UDP port as device address (in the format `<ip-address>:<port-number>`) which can be used for addressing throughout the entire LAN. Technically, the device is an object with the name `device`. The device instance in fact is its object instance with the additional requirement to be unique.

### Object

An object reflects a physical hardware actor or sensor (i.e., an I/O device). BACnet defines a list of standardized object types (such as analog-input, analog-output, binary-input, binary-output, etc.). Object types are identified by a fixed number or by a fixed ASCII string identifier. Depending on the installation, a device may serve an arbitrary number of object instances of arbitrary type. A device may, for example, host 3 analog-inputs, 1 analog-value, and two binary-outputs. An object is addressed using its type and numeric instance ID, which must only be unique within the device.

### Property

Every object contains a type-dependent set of properties. The most important property that exists in every object is the `present-value` property. This is conceptually very similar to the process-variable (PV) of other industry protocols. Like object types, the properties are identified by a fixed number or by a fixed ASCII string (e.g., `present-value`). Examples of other properties are `version` or `object-name`. The property is the final data-endpoint where values can be read from or written to. The value type can be any scalar value, arrays of scalars, or specific complex types (this depends on the object type).

For unambiguously addressing any data endpoint (in BACnet: `property`), you must provide the following information:

* At the [Cybus::Connection](https://docs.cybus.io/documentation/services/service-commissioning-files/resources/cybus-connection):
  1. `deviceAddress` (e.g., `192.168.2.160:43712`)
  2. `deviceInstance` (e.g., `27335`)
* At the [Cybus::Endpoint](https://docs.cybus.io/documentation/services/service-commissioning-files/resources/cybus-endpoint):
  1. `objectType` (e.g., `analog-input`)
  2. `objectInstance` (e.g., `2`)
  3. `property` (e.g., `present-value`)

{% hint style="warning" %}
If only one device is running on a given host (with fixed IP), the port can be omitted from the `deviceAddress` field.
{% endhint %}

* [Connection Properties](https://docs.cybus.io/connectors/shop-floor-connectors/bacnet/bacnetconnection)
* [Endpoint Properties](https://docs.cybus.io/connectors/shop-floor-connectors/bacnet/bacnetendpoint)

## Service Commissioning File Example

The following example demonstrates how to configure a BACnet connection with endpoints for read, write, and subscribe operations on BACnet objects.

{% file src="<https://2355450750-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGzXPesVecsUM1eHBfwea%2Fuploads%2Fgit-blob-afd776051f07420b1d168c7d79f9a8d8470b8a0a%2Fbacnet-example.yml?alt=media>" %}

{% code title="bacnet-example.yml" lineNumbers="true" %}

```yaml
# ----------------------------------------------------------------------------#
# BACnet Service Commissioning File Example
# ----------------------------------------------------------------------------#
# Copyright: Cybus GmbH
# Contact: support@cybus.io
# ----------------------------------------------------------------------------#
# Source Interface Definition - BACnet
# ----------------------------------------------------------------------------#

description: |
  Sample commissioning file for BACnet protocol connectivity and data mapping

metadata:
  name: BACnet Protocol Connectivity
  icon: https://www.cybus.io/wp-content/uploads/2019/03/Cybus-logo-Claim-lang.svg
  provider: cybus
  homepage: https://www.cybus.io
  version: 0.0.1

parameters:
  IP_Address:
    type: string
    default: 192.168.10.30

  Port_Number:
    type: number
    default: 47808

  Device_Instance:
    type: number
    default: 2000

  initialReconnectDelay:
    type: integer
    default: 1000

  maxReconnectDelay:
    type: integer
    default: 30000

  factorReconnectDelay:
    type: integer
    default: 2

resources:
  # Define the connection to the device.
  bacnetConnection:
    type: Cybus::Connection
    properties:
      protocol: Bacnet
      targetState: connected
      connection:
        deviceInstance: !ref Device_Instance
        deviceAddress: !sub '${IP_Address}:${Port_Number}'
        connectionStrategy:
          initialDelay: !ref initialReconnectDelay
          maxDelay: !ref maxReconnectDelay
          incrementFactor: !ref factorReconnectDelay

  # The BACnet protocol supports endpoints of type read, write, and subscribe.
  # Below are examples of how to configure such operations.
  # Read endpoint
  bacnetReadBinaryOutput:
    type: Cybus::Endpoint
    properties:
      protocol: Bacnet
      connection: !ref bacnetConnection
      # Specifying the topic here instead of using a Mapping block allows us to remove an extra hop.
      read:
        objectType: binary-output
        objectInstance: 303
        property: present-value

  # Write endpoint
  bacnetWriteBinaryOutput:
    type: Cybus::Endpoint
    properties:
      protocol: Bacnet
      connection: !ref bacnetConnection
      write:
        objectType: binary-output
        objectInstance: 303
        property: present-value
        priority: 8
        propertyTag: 7

  # Subscription endpoint
  bacnetSubscribeBinaryOutput:
    type: Cybus::Endpoint
    properties:
      protocol: Bacnet
      connection: !ref bacnetConnection
      subscribe:
        objectType: binary-output
        objectInstance: 303
        property: present-value
        interval: 1000
```

{% endcode %}

### Input Format on Write

To write data to BACnet, you must send a request to the MQTT endpoint of the service using a `/set` suffix with a JSON object in the following format:

{% code lineNumbers="true" %}

```json
{ "value": "<value>" }
```

{% endcode %}

### Output Format on Write

No response message is written to the `/res` topic of the endpoint for write operations.

### Output Format on Read

For a read endpoint, you can include a correlation `id` in the payload of the message request to ensure correct identification of responses to specific requests.

When data is read, results are published to the `/res` topic of the endpoint. The output message is an object with the following format:

{% code lineNumbers="true" %}

```json
{
  "value": "<value>",
  "timestamp": "<msSinceEpoch>",
  "id": "<correlation id>"
}
```

{% endcode %}
