Skip to main content
Version: 4.2 (beta)

BACnetServer

BACnet is a protocol developed by ASHRAE for building automation and control networking, specifically designed to meet the communication needs of building automation and control systems for applications such as heating, ventilating, air-conditioning control, lighting control, access control and fire detection systems. HSYCO conforms to a functional subset of the BACnet protocol, as defined in ANSI/ASHRAE Standard 135. The BACnet/SC (Secure Connect) datalink follows Annex YY of ANSI/ASHRAE Standard 135-2024. The BACnetServer I/O Server reports Protocol_Version 1 and Protocol_Revision 17. HSYCO can be configured as a BACnet client or server device. BACnet support is implemented as an I/O Server with a data point representation that you can use in the EVENTS language and Java to read and write BACnet’s objects and properties, and to manage asynchronous notification services.

note

The BACnet Vendor Identification Number that has been issued by ASHRAE to HSYCO S.r.l. (formerly Home Systems Consulting SpA) is 590.

Communication​

The BACnetServer I/O Server supports two alternative datalinks, selected with the transport option:

  • BACnet/IP (transport=ip, the default), where the BACnet messaging protocol is transported over standard IP networks, using UDP on the local network. Routing of BACnet traffic is currently not supported, but clients on remote routed subnets can reach the server through a BBMD, see Foreign Device Registration.
  • BACnet/SC (transport=sc), where the BACnet messaging protocol is transported over TLS-secured WebSocket connections. See BACnet/SC below.

You should configure only one I/O Server for each LAN used for BACnet/IP traffic. Support for multiple BACnet/IP local networks is achieved by configuring one I/O Server for each network.

Segmentation​

The BACnetServer I/O Server supports segmented messages in both directions (its Device object reports segmented-both):

  • responses that don’t fit the client’s maximum APDU size are automatically split into segments, honoring the client’s max-APDU, max-segments and segmentation-accepted parameters; when the client can’t accept segments, the request is aborted with the segmentation-not-supported reason
  • incoming segmented requests are reassembled before they are processed

Segmentation timing is controlled by the apdusegmenttimeout, apduretries and segmentwindow options, while the size of what can be reassembled is controlled by maxapdu. Requests of up to 64 segments are accepted, the maximum number that can be advertised as an exact value, and reported as the Max_Segments_Accepted property of the Device object; a client that exceeds either that count or maxapdu × 64 total octets is aborted with the buffer-overflow reason.

HSYCO Configuration​

Add a BACnetServer I/O Server in the I/O Servers section of the Settings and set its parameters:

Communication​

  • IP Address: broadcast IP address of the LAN used for BACnet traffic (e.g. 192.168.1.255). Not used when transport=sc.
  • IP Port: TCP/IP port to use, leave blank to use default port 47808. Not used when transport=sc.

High Availability​

  • Shutdown when inactive: defaults to false.

Options​

IDDefaultValuesDescription
deviceid5900000 ... 4194302BACnet device identifier assigned to the HSYCO BACnetServer.
disableverbosedumpfalsetruewhen verbose log is enabled, don’t write IP packets dump to the log files
falsewhen verbose log is enabled, all BACnet IP packets are written to the log files
eventslogfalsetrueif the general eventsLog option is also true in System Settings, BACnet events for this gateway are written in the log files
falseBACnet events for this gateway are not written in the log files, even if the eventsLog option is true in System Settings
maxsubscriptionsunlimited1 ... Nnumber of maximum subscriptions allowed at the same time. When the limit is reached, the oldest subscriptions are discarded to make room for the new ones
transportipipthe BACnet/IP datalink is used, over UDP
scthe BACnet/SC datalink is used, and HSYCO operates as an SC hub
apdusegmenttimeout2000millisecondstime to wait for the acknowledgment of a transmitted segment before retrying
apduretries30 ... Nnumber of retries of a segment that is not acknowledged within the segment timeout
segmentwindow161 ... 127segmentation window size, i.e. the number of segments sent before waiting for an acknowledgement
maxapdu147650, 128, 206, 480, 1024, 1476maximum APDU length accepted, advertised in the I-Am, as the Max_APDU_Length_Accepted property of the Device object, and in the confirmed COV notifications sent to the subscribers. It limits the size of the requests the clients send to HSYCO, not the size of the responses HSYCO returns: those are sized by the maximum APDU length each client declares in its own request. Ignored when transport=sc, where the negotiated maxnpdu is used instead

Foreign Device Registration Options​

These options only apply when transport=ip. Setting bbmd makes the server register as a foreign device (ANSI/ASHRAE 135, Annex J) with a BACnet Broadcast Management Device, so that clients on remote routed subnets can discover it: the Who-Is requests broadcast on the remote networks are forwarded to HSYCO by the BBMD, and the server's broadcasts — I-Am responses and unconfirmed COV notifications — are sent both on the local network and to the BBMD, which distributes them to its own network and to the other registered foreign devices. Confirmed requests and responses always travel directly between the clients and the server.

The registration is renewed automatically at half the configured time-to-live, and re-established with periodic retries when the BBMD becomes unreachable. Registration failures are reported in the log, at most one line per minute; communication on the local network is never affected by the state of the registration.

The server itself is not a BBMD: BBMD-role requests received from other devices — foreign device registrations, broadcast distributions, table reads and writes — are refused with the NAK code.

IDDefaultValuesDescription
bbmdhost or host:portaddress of the BBMD to register with, e.g. 192.168.10.1 or 192.168.10.1:47808; the default port is 47808. When not set, foreign device registration is disabled
bbmdttl6001 ... 65535registration time-to-live in seconds, renewed by HSYCO at every half bbmdttl. Lower values make a stale registration expire sooner on the BBMD, at the cost of more frequent renewals

BACnet/SC Options​

These options are only used when transport=sc.

IDDefaultValuesDescription
binduriwss://<address>:<port>the WebSocket URI the SC hub listens on, for example wss://0.0.0.0:47808
certfilefile pathPEM file with the operational certificate. When set together with keyfile, PEM files are used instead of the Java keystores
keyfilefile pathPEM file with the private key of the operational certificate
cafilethe certfile filefile pathPEM file with the issuer (CA) certificates used to validate the certificates of the connecting nodes
keystoresecrets/hsyco.keysfile pathJava keystore with the operational certificate and private key, used when certfile and keyfile are not set
keystorepass<hsyco key store password>password of the keystore file
truststoresecrets/clients.keys, or secrets/hsyco.keys if secrets/clients.keys doesn’t existfile pathJava keystore with the certificates used to validate the certificates of the connecting nodes
truststorepass<hsyco client keystore password>password of the truststore file
vmacrandom6 bytes, hexthe virtual MAC address of the hub, e.g. 0a1b2c3d4e5f. When not set, a random VMAC is generated at first startup and persisted
uuidrandomUUIDthe Device UUID of the hub. When not set, a random UUID is generated at first startup and persisted
maxbvlc14971497 ... 61327maximum BVLC message length accepted
maxnpdu14971497 ... 61327maximum NPDU length accepted. It also replaces maxapdu as the maximum APDU length accepted, both on the wire and as the Max_APDU_Length_Accepted property of the Device object

BACnet/SC​

When transport=sc, the BACnetServer I/O Server operates as a BACnet/SC hub: it listens for TLS-secured WebSocket connections from SC nodes at the binduri address, and switches BACnet messages between the connected nodes and its own application layer. It does not connect to an external hub.

The TLS identity of the hub can be provided in two alternative ways:

  • as PEM files, setting the certfile and keyfile options, and optionally cafile
  • as Java keystores, setting the keystore, keystorepass, truststore and truststorepass options; when none of these are set, HSYCO’s own hsyco.keys and clients.keys files are used

The virtual MAC address and the Device UUID of the hub are generated at the first startup and persisted in the identity.ini file of the I/O Server, in the state/drivers/bacnetserver/<I/O Server name> directory, where <I/O Server name> is the I/O Server name in lower case, so that they remain stable across restarts. They can be forced to a specific value with the vmac and uuid options.

In SC mode the built-in read-only Network Port object, instance 1, describes the SC port: network type, MAC address (the hub’s virtual MAC), maximum BVLC and NPDU lengths, hub function URIs and bindings, the list of the currently connected nodes (SC_Hub_Function_Connection_Status) and the list of the failed connection requests (SC_Failed_Connection_Requests).

SC mode also adds four read-only File objects, instances 1 to 4, exposing the certificates in PEM format: the operational certificate (instance 1), two issuer certificates (instances 2 and 3) and the certificate signing request (instance 4). Their content is read with the AtomicReadFile service, using stream access. These files are read-only: AtomicWriteFile requests, as well as WriteProperty requests to File objects, are rejected with a write-access-denied error.

BACnetServer Utility​

The BACnetServer Utility provides a graphical interface to show, create and delete objects, and modify any supported property's values.

Datapoints​

The following services are supported:

  • Alarm and Event Services:
    • ConfirmedCOVNotification
    • UnconfirmedCOVNotification
    • SubscribeCOV
    • SubscribeCOVProperty
  • File Access Services:
    • AtomicReadFile (BACnet/SC only, to read the certificate File objects)
  • Object Access Services:
    • ReadProperty
    • ReadPropertyMultiple
    • WriteProperty
  • Remote Device Management Services:
    • Who-Is
    • I-Am

The ReadProperty and ReadPropertyMultiple services return the properties that the server actually serves for each of the supported object types: the properties required by the standard, plus the optional ones that HSYCO implements. The properties served by an object can be discovered by reading its Property_List property. Reading a property that is not served returns an unknown-property error, and reading an object that does not exist returns an unknown-object error.

The object’s properties that can be written using the WriteProperty service are listed in the supported object types table.

ReadPropertyMultiple also accepts the special all, required and optional property identifiers, returning all of the properties served for the object.

Following HSYCO’s naming convention for BACnet, all object types and properties are written in lowercase letters with no spaces or underscore characters. For example, Present_Value is written as presentvalue, and the binary input object type is written as binaryinput.

The BACnet datapoint names always begin with the same format:

<object_type>.<object_id>

where <object_type> is the object type name with no spaces and all lowercase and <object_id> is the object instance numeric identifier.

Data point names returning properties values also have the object property identifier at the end with no spaces and all lowercase characters:

<object_type>.<object_id>.<property_id>

where <property_id> is the property name with no spaces and all lowercase.

For example this datapoint

analogoutput.1.presentvalue

represents the present value of the analog output BACnet object "1".

Datapoints Table​

IDValueR/WDescription
<object_type>.<object_id>.<property_id><value>Rthe value of the <property_id> property of the <object_type>.<object_id> object, formatted according to the application datatype
<object_type>.<object_id>.<property_id>/<P><value>Wwrites the <value> in the <property_id> property of <object_type>.<object:id> object, formatted according to the application datatype. <P> is the priority, a number from 1 to 16, and only applies to the presentvalue property of commandable objects; writing an empty value relinquishes the value at that priority. If the <object_id> does not exist, it will be created as a dinamic object, that will last until HSYCO is restarted.
<object_type>.<object_id>.priorityarray[<P>]<value>Rthe priority array slot at priority <P>, a number from 1 to 16, of a commandable object. An empty value means that the slot is not commanded.
active.subscriptions<value>Rcount of active subscriptions to objects or properties.

Commandable Objects​

The analogoutput, analogvalue, binaryoutput, binaryvalue, multistateoutput and multistatevalue object types are commandable: they have a 16-slot priority array, and their Present_Value is not written directly.

Writing the presentvalue property, either with a WriteProperty request or with an EVENTS command, sets the priority array slot of the specified priority, defaulting to 16 when no priority is specified. HSYCO then recalculates the Present_Value as the value of the highest priority slot that is set, falling back to the Relinquish_Default property when all the slots are empty, and to no value at all when Relinquish_Default is not set either. The Current_Command_Priority property reports the highest priority slot that is currently set.

COV Notifications​

The BACnetServer I/O Server supports Confirmed and Unconfirmed COVSubscriptions to objects and properties. The Unconfirmed type is a less reliable notification mechanism, but more efficient in terms of network usage and devices workload. After successfully subscribing, even with the COVIncrement property set, the first Change Of Value is always notified to clients. After that, the COVIncrement property, if set, is taken into consideration when notifying clients.

A SubscribeCOV subscription notifies the Present_Value and Status_Flags properties of the monitored object, while a SubscribeCOVProperty subscription only notifies the monitored property.

Confirmed notifications must be acknowledged by the subscriber: a notification that is not acknowledged within the APDU timeout, or that is answered with an error, counts as a delivery failure, and a subscriber that fails three notifications in a row has its subscription dropped, with a warning in the log.

Supported Object Types​

Object TypeWritable Properties
accumulator* description * devicetype * eventstate * maxpresvalue * objectname * outofservice * presentvalue * pulserate * statusflags * units * valuebeforechange * valueset
analoginput* covincrement * description * devicetype * eventstate * objectname * outofservice * presentvalue * statusflags * units
analogoutput* covincrement * description * devicetype * eventstate * objectname * outofservice * presentvalue * relinquishdefault * statusflags * units
analogvalue* covincrement * description * eventstate * objectname * outofservice * presentvalue * relinquishdefault * statusflags * units
binaryinput* activetext * description * devicetype * eventstate * inactivetext * objectname * outofservice * polarity * presentvalue * statusflags
binaryoutput* activetext * description * devicetype * eventstate * inactivetext * objectname * outofservice * polarity * presentvalue * relinquishdefault * statusflags
binaryvalue* activetext * description * eventstate * inactivetext * objectname * outofservice * presentvalue * relinquishdefault * statusflags
device* databaserevision * description * modelname * objectname * systemstatus
multistateinput* description * devicetype * eventstate * numberofstates * objectname * outofservice * presentvalue * statusflags
multistateoutput* description * devicetype * eventstate * numberofstates * objectname * outofservice * presentvalue * relinquishdefault * statusflags
multistatevalue* description * eventstate * numberofstates * objectname * outofservice * presentvalue * relinquishdefault * statusflags

The Device object is built-in: it always exists, with the object instance set by the deviceid option, and cannot be deleted. Its identification properties (vendor name and identifier, protocol version and revision, supported services and object types, segmentation, APDU parameters and, in SC mode, the Device UUID) are read-only.

The built-in read-only Network Port object, instance 1, is always served, and describes the datalink in use: in BACnet/IP mode it reports the BACnet/IP mode, IP address, subnet mask and UDP port of the server, while in BACnet/SC mode it reports the SC port and the state of the hub, as described in the BACnet/SC section, where the built-in read-only File objects (instances 1 to 4) are also described.

Objects of all the other supported types are created either as static objects, using the BACnetServer Utility, and persisted in the objects.txt file of the I/O Server, in the config/drivers/bacnetserver/<I/O Server name> directory, or as dynamic objects, created on the fly when an EVENTS command or a WriteProperty request writes one of their properties, and lost at the next restart.

Supported Application Datatypes​

Tag#DescriptionHSYCO Data Type
0Nullnull
1Boolean0: false 1: true
2Unsigned Integer0 ... (232 - 1)
3Signed Integer-231 ... (231 - 1)
4Real (IEEE-754 floating point)floating point number (with decimal point separator)
5Double (IEEE-754 double precision floating point)double precision floating point number (with decimal point separator)
6Octet Stringthe hexadecimal representation of byte values, for example: 3b0ac2ff
7Character Stringa string. HSYCO always transmits strings using the UTF-8 character set. Strings received from the clients are also decoded when they use the ISO-8859-1, UCS-2, UCS-4, EUC-JP and IBM/Microsoft DBCS character sets
8Bit Stringa string representing a sequence of bit values, for example: 111010001
9Enumerated0 ... (232 - 1)
10Date<yyyy>/<mm>/<dd>[/<dow>]<yyyy> is the year number; a * character is a wildcard matching any year, or an unspecified value.<mm> is the month number, with January as 1; a * character is a wildcard matching any month, or an unspecified value; odd represent all odd months; even represent all even months.<dd> is the day number, starting from 1 for the first day of the month; a * character is a wildcard matching any day, or an unspecified value; odd represent all odd days; even represent all even days; last represent the last day of the month.<dow> is the week day, and is only present if set to a day of the week, and not to the wildcard/unspecified value; days are represented as mon, tue, wed, thu, fri, sat, sun
11Time<hh>:<mm>:<ss>.<ff><hh> is the hour, using a 24-hour clock from 0 to 23; a * character is a wildcard matching any hour, or an unspecified value.<mm> is the minute, from 0 through 59; a * character is a wildcard matching any minute, or an unspecified value.<ss> is the seconds, from 0 through 59; a * character is a wildcard matching any second, or an unspecified value.<ff> is the hundreds of seconds number, from 0 to 99; a * character is a wildcard matching any fraction of second, or an unspecified value.
12BACnetObjectIdentifier<object_type>.<object_id><object_type> is represented with the type name for supported types, and with the BACnet object type number for unsupported objects.<object_id> is the object instance number

Examples​

Writing the present value of an object​

USER bac = 5 : IO bacserv.analoginput.0.presentvalue = 3
TIME : IO bacserv.analoginput.0.presentvalue/8 = $myvalue

The first line sets the Present Value property of object type Analog Input, object instance 0 to the value 3. The second line is similar, but this time the priority is set to 8. Also note that the value after presentvalue/8 is from a variable. To ensure that the variable name is translated to its value, leave a space before the variable name. This way the EVENTS interpreter will automatically concatenate the strings, also replacing the variable name with its value.

Relinquishing the present value of a commandable object​

USER bac = 0 : IO bacserv.analogoutput.1.presentvalue/8 =

This command clears the priority array slot 8 of the Analog Output object instance 1. The Present Value is then recalculated from the highest priority slot that is still set, or from the Relinquish_Default property when no slot is set.

Release Notes​

4.2.0​

  • added support for the BACnet/SC (Secure Connect) datalink, with HSYCO acting as an SC hub
  • added foreign device registration with a BBMD, so that clients on remote routed subnets can discover and reach the server
  • added support for segmented messages, both for the requests received and for the responses sent
  • added support for the AtomicReadFile service, to read the BACnet/SC certificate File objects
  • added the built-in Device and Network Port objects, and the built-in File objects in BACnet/SC mode
  • added support for the priority array and the Relinquish_Default property of commandable objects
  • extended the set of writable properties of the supported object types
  • removed the command object type

4.1.0​

  • added support for Read-Property-Multiple-Service

4.0.0​

  • initial release

BACnet is a registered trademark of the American Society of Heating, Refrigerating and Air-Conditioning Engineers, Inc.