Process a BACnet event

🟡 Intermediate

bacnet alarm

In this example you will learn how to subscribe to the event of a BACnet device. It is recommended to first start by reading the Notifications subscription.

  • Configure a BACnet device connection using device.bacnet.

  • Control a BACnet analog value via output.bacnet and a callback to trigger notifications.

  • Define a notification.bacnet listener that maps BACnet event states (fault, off-normal, normal) to alarm severities.

  • Generate and clear alarms automatically via a linked JS script when notifications arrive.

git checkout origin/osp-alarms-configuration .
git checkout origin/osp-web-configuration .
git checkout origin/osp-bacnet-configuration .
git checkout origin/osp-variables-configuration .
git checkout origin/osp-scripts-configuration .
git checkout origin/example-bacnet-notification .

Prerequisites

A BACNet device with a notificationClass configured and a value with limit enabled.

For this example, the BACNet device will be 341984, the notificationClass will be 0 and the value will be analog_value 1 with a authorized range of [0-100].

Note

The configuration of the notificationClass and analog_value to trigger a event is outside of the scope of this example. Please refer to the BACnet documentation for your device.

Learning goals

Steps

1. Setup the connection

First you need to configure the connection with a device. This is made in the device.bacnet file.

root/device/device.bacnet

{
    "moduleId": "modules.bacnet.bacnet-1",
    "deviceIdentifier": 341984
}

2. Create an output and variable to control the analog value

By controlling the analog_value, you can trigger the BACNet event.

root/output/output.bacnet

{
    "linkedDevice": "root.device",
    "object": {
        "instance": 1,
        "type": "ANALOG_VALUE",
        "property": "PRESENT_VALUE"
    }
}

root/value/owner.variables

{
    "moduleId": "modules.variables.variables-1",
    "default": 50.0
}

root/value/callback.ospp

{
    "linkedOutputs": [
        {
            "outputId": "root.output"
        }
    ]
}

root/value/value.ospp

{
    "name": "Set the bacnet analog value 0",
    "description": "",
    "type": "DECIMAL"
}

3. Configure the notification listener

The notification listener will listen for all event happening on the device for the notificationClass 0. When a notification arrive, the script generate_alarm.js will be called by the linkedAction.

The serial will be generated by joining the device id, value type and instance and the notification class. Here the result will be 341984-analog-value-1-0. The severity will be major for a fault, minor for a off normal state and clear for a normal state.

root/notification/notification.bacnet

{
    "processIdentifier": 10,
    "linkedDevice": "root.device",
    "instance": 0,
    "linkedAction": {
        "actionId": "root.action",
        "parameters": {
            "scriptId": {
                "type": "CONSTANT",
                "value": "root.script"
            },
            "arguments": {
                "type": "LIST",
                "values": [
                    {
                        "type": "FIELD",
                        "field": "CONTENT"
                    }
                ]
            }
        },
        "expiration": {
            "value": 5,
            "unit": "SECONDS"
        }
    }
}

root/action/action.ospp

{
    "moduleId": [
        "modules.bacnet.bacnet-1"
    ],
    "type": "RUN_SCRIPT"
}

root/script/detached.scripts

{
    "moduleId": "modules.scripts.scripts-1",
    "sourceFile": "root/script/generate-alarm.js"
}

root/script/generate-alarm.js

const data = JSON.parse(trigger.parameters);

let severity = "root.alarms.severities.warning";
switch (data.toState) {
  case "normal":
    severity = "root.alarms.severities.clear";
    break;
  case "offNormal":
  case "high-limit":
  case "low-limit":
    severity = "root.alarms.severities.minor";
    break;
  case "fault":
    severity = 600;
    break;
  default:
    break;
}

let alarmBuilder = alarms
  .newAlarmBuilder(
    `${data.initiatingDeviceIdentifier.instance}-${data.eventObjectIdentifier.typeString}-${data.eventObjectIdentifier.instance}-${data.notificationClass}`,
    severity
  )
  .setLocation("Test")
  .setSource(`${data.initiatingDeviceIdentifier.instance}`)
  .addTag("BACNet")
  .setSummary(`[${data.eventType}] ${data.messageText}`);

if (data.ackRequired) {
  alarmBuilder.addAdditionalData(
    "bacnetAcknowledgeData",
    data.bacnetAcknowledgeData
  );
}

const result = alarms.insert(alarmBuilder.build());

if (!result.success) {
  execution.reportFailure(result.message);
}

4. Visualize the data

To visualize the alarm and set the value, a dashboard, including a Value Subscription already linked to the status of your BACnet device and the test value and an Alarm Table, has been created.

The test value can be edited to trigger the off normal state and generate an alarms

root/dashboard.view

{
  "configuration": [
    {
      "type": "AlarmTable",
    },
    {
      "valueSubscriptions": {
        "values": [
          {
            "id": "root.device",
            "right": "READ"
          },
          {
            "id": "root.value",
            "right": "READ_WRITE"
          }
        ]
      },
      "id": "rAkz5KgQ",
      "type": "ValueSubscription",
      "title": ""
    }
  ],
}

5. Change the value

If you set the value to 101, an alarm will be generated.

../_images/off_normal_alarm.png

When the value is below 100, the alarm is resolved.

../_images/normal_alarm.png