BACnet.Protocol.BvlcFunction (bacstack v0.1.0-dev.1)

Copy Markdown View Source

A BVLC Function is the payload of a BACnet Virtual Link Layer (BVLL) message used on BACnet/IP networks (ASHRAE 135 Annex J). Each function code corresponds to a different operation: Register-Foreign-Device, Read-Broadcast-Distribution-Table, Write-Broadcast-Distribution-Table, and several others used for BBMD and Foreign Device management.

This module models the seven management BVLC functions that carry structured payloads (as opposed to the five simple NPDU-carrier functions that are represented as atoms in BACnet.Protocol.bvlc/0). It is the central "CHOICE" type for BVLC in the library: the function field (an atom from the :bvlc_result_purpose constants) acts as the discriminant and determines the shape of the data field.

BACnet Specification References

  • Annex J.2 defines the BACnet Virtual Link Layer (BVLL) and the BVLC Function field (1 octet) together with the overall message format (Type 0x81, Length, Function, Data).
  • J.2.2-J.2.9 give the exact purpose and octet layout for each management function handled here (Write-BDT 0x01, Read-BDT 0x02, Read-BDT-Ack 0x03, Register-Foreign-Device 0x05, Read-FDT 0x06, Read-FDT-Ack 0x07, Delete-FDT-Entry 0x08).
  • J.2.1 and J.2.1.1 define the companion BVLC-Result (0x00) and its result codes (see BACnet.Protocol.BvlcResult and the :bvlc_result_format constants).
  • J.4.3-J.4.5 and J.5 describe how a BBMD uses these functions to maintain the Broadcast Distribution Table (BDT) and Foreign Device Table (FDT) and to forward broadcasts.

Supported BVLC Functions and Data Shapes

Only the functions listed below are decoded/encoded by this module. All other function codes (including the five NPDU carriers and Secure-BVLL 0x0C) are handled elsewhere or return {:error, :unsupported_bvlc_function}.

Function AtomCodedata ShapeSpec Reference
:bvlc_write_broadcast_distribution_table0x01[BroadcastDistributionTableEntry.t()]J.2.2
:bvlc_read_broadcast_distribution_table0x02nilJ.2.3
:bvlc_read_broadcast_distribution_table_ack0x03[BroadcastDistributionTableEntry.t()]J.2.4
:bvlc_register_foreign_device0x05non_neg_integer() (TTL in seconds, 1..65535)J.2.6
:bvlc_read_foreign_device_table0x06nilJ.2.7
:bvlc_read_foreign_device_table_ack0x07[ForeignDeviceTableEntry.t()]J.2.8
:bvlc_delete_foreign_device_table_entry0x08ForeignDeviceTableEntry.t() (with time_to_live and remaining_time set to nil)J.2.9

Construction & Gotchas

iex> alias BACnet.Protocol.{BvlcFunction, Constants, ForeignDeviceTableEntry}
iex> require Constants
iex> ttl = 3600
iex> fun = %BvlcFunction{
...>   function: Constants.macro_assert_name(:bvlc_result_purpose, :bvlc_register_foreign_device),
...>   data: ttl
...> }
iex> fun.data
3600

Special cases you must know:

Examples

Register-Foreign-Device (TTL = 3600 s):

iex> alias BACnet.Protocol.{BvlcFunction, Constants}
iex> require Constants
iex> fun = %BvlcFunction{
...>   function: Constants.macro_assert_name(:bvlc_result_purpose, :bvlc_register_foreign_device),
...>   data: 3600
...> }
iex> BvlcFunction.encode(fun)
{:ok, {5, <<14, 16>>}}

Write-Broadcast-Distribution-Table with a single entry (two-hop mask):

iex> alias BACnet.Protocol.{BvlcFunction, Constants, BroadcastDistributionTableEntry}
iex> require Constants
iex> entry = %BroadcastDistributionTableEntry{
...>   ip: {192, 168, 1, 10},
...>   port: 0xBAC0,
...>   mask: {255, 255, 255, 255}
...> }
iex> fun = %BvlcFunction{
...>   function: Constants.macro_assert_name(:bvlc_result_purpose, :bvlc_write_broadcast_distribution_table),
...>   data: [entry]
...> }
iex> BvlcFunction.encode(fun)
{:ok, {1, <<192, 168, 1, 10, 186, 192, 255, 255, 255, 255>>}}

Delete-Foreign-Device-Table-Entry (note the nil fields producing the short 6-octet form):

iex> alias BACnet.Protocol.{BvlcFunction, Constants, ForeignDeviceTableEntry}
iex> require Constants
iex> del = %ForeignDeviceTableEntry{
...>   ip: {10, 0, 0, 5},
...>   port: 0xBAC0,
...>   time_to_live: nil,
...>   remaining_time: nil
...> }
iex> fun = %BvlcFunction{
...>   function: Constants.macro_assert_name(:bvlc_result_purpose, :bvlc_delete_foreign_device_table_entry),
...>   data: del
...> }
iex> BvlcFunction.encode(fun)
{:ok, {8, <<10, 0, 0, 5, 186, 192>>}}

Usage Contexts

BACnet.Protocol.BvlcFunction values are produced by BACnet.Protocol.decode_bvll/3 when the incoming BVLC function code is one of the seven management values. They are primarily consumed by BACnet.Stack.BBMD (which answers Read-BDT/Read-FDT, accepts Write-BDT and Register-Foreign-Device, and emits the corresponding Ack or Result messages) and by BACnet.Stack.ForeignDevice (which emits Register, Read-BDT, Read-FDT and Distribute-Broadcast requests).

The encode side is used when a client or BBMD needs to emit a management request or response over a BACnet.Stack.Transport.IPv4Transport.

See Also

Summary

Types

t()

Represents a BACnet Virtual Link Control (BVLC) function used in BACnet/IP.

Functions

Decodes BACnet Virtual Link Control Functions into a struct.

Encodes BACnet Virtual Link Control Functions into binary data.

Types

t()

@type t() :: %BACnet.Protocol.BvlcFunction{
  data:
    [BACnet.Protocol.BroadcastDistributionTableEntry.t()]
    | [BACnet.Protocol.ForeignDeviceTableEntry.t()]
    | (delete_foreign_device_table_entry ::
         BACnet.Protocol.ForeignDeviceTableEntry.t())
    | (read_broadcast_distribution_table :: nil)
    | (read_foreign_device_table :: nil)
    | (register_foreign_device :: non_neg_integer()),
  function: BACnet.Protocol.Constants.bvlc_result_purpose()
}

Represents a BACnet Virtual Link Control (BVLC) function used in BACnet/IP.

The function field is the discriminant. Its value determines the required shape of data (see the moduledoc table). Use the BACnet.Protocol.Constants.macro_assert_name/2 helpers when constructing values for maximum safety and readability.

Functions

decode(bvlc_function, data)

@spec decode(non_neg_integer(), binary()) :: {:ok, t()} | {:error, term()}

Decodes BACnet Virtual Link Control Functions into a struct.

Supported are the following BVLC functions:

  • Delete-Foreign-Device-Table-Entry
  • Read-Broadcast-Distribution-Table
  • Read-Broadcast-Distribution-Table-Ack
  • Read-Foreign-Device-Table
  • Read-Foreign-Device-Table-Ack
  • Register-Foreign-Device
  • Write-Broadcast-Distribution-Table

encode(bvlc)

@spec encode(t()) ::
  {:ok, {bvlc_function :: non_neg_integer(), data :: binary()}}
  | {:error, term()}

Encodes BACnet Virtual Link Control Functions into binary data.

Supported are the following BVLC functions:

  • Delete-Foreign-Device-Table-Entry
  • Read-Broadcast-Distribution-Table
  • Read-Broadcast-Distribution-Table-Ack
  • Read-Foreign-Device-Table
  • Read-Foreign-Device-Table-Ack
  • Register-Foreign-Device
  • Write-Broadcast-Distribution-Table