Current section
Files
Jump to
Current section
Files
lib/bacnet/protocol/result_flags.ex
defmodule BACnet.Protocol.ResultFlags do
@moduledoc """
BACnet Result Flags is a three-bit bit string returned by range-reading services
(ReadRange, GetEventInformation, etc.) to describe the window of data that was
actually returned.
Bit meanings (MSB first):
| Bit | Name | Meaning when TRUE |
|-----|------------|:-----------------------------------------------------------------|
| 0 | FIRST_ITEM | Response contains the first (oldest) item of the requested range |
| 1 | LAST_ITEM | Response contains the last (newest) item of the requested range |
| 2 | MORE_ITEMS | More items matched but could not fit in this PDU / segment |
The flags allow a client to know whether it has the beginning, the end, or is
looking at a slice in the middle of a potentially large collection (trend-log
buffer, alarm summary, event log, etc.).
### BACnet Specification References
- **ASN.1** (Clause 21): `BACnetResultFlags ::= BIT STRING { first-item (0), last-item (1), more-items (2) }`
- **Primary services**: ReadRange-ACK (15.8), GetEventInformation-ACK (13.11),
and several alarm/event summary acknowledgments.
### Examples (Doc Test)
```elixir
iex> flags = %ResultFlags{first_item: true, last_item: false, more_items: true}
iex> flags.more_items
true
```
### See Also
- `BACnet.Protocol.ReadRange`
"""
alias BACnet.Protocol.ApplicationTags
# TODO: Throw argument error in encode if not valid
@typedoc """
Three Boolean flags describing a partial result set (see module docs for bit positions).
"""
@type t :: %__MODULE__{
first_item: boolean(),
last_item: boolean(),
more_items: boolean()
}
@fields [
:first_item,
:last_item,
:more_items
]
@enforce_keys @fields
defstruct @fields
@doc """
Encodes a BACnet result flags into application tags encoding.
"""
@spec encode(t(), Keyword.t()) :: {:ok, ApplicationTags.encoding_list()} | {:error, term()}
def encode(%__MODULE__{} = flags, _opts \\ []) do
{:ok, [to_bitstring(flags)]}
end
@doc """
Creates from an application tag bitstring a result flags.
"""
@spec from_bitstring(tuple()) :: t()
def from_bitstring(bitstring) when is_tuple(bitstring) and tuple_size(bitstring) == 3 do
%__MODULE__{
first_item: elem(bitstring, 0),
last_item: elem(bitstring, 1),
more_items: elem(bitstring, 2)
}
end
@doc """
Parses a BACnet result flags from application tags encoding.
"""
@spec parse(ApplicationTags.encoding_list()) ::
{:ok, {t(), rest :: ApplicationTags.encoding_list()}}
| {:error, term()}
def parse(tags) when is_list(tags) do
case tags do
[{:bitstring, {_b1, _b2, _b3} = bs} | rest] -> {:ok, {from_bitstring(bs), rest}}
_else -> {:error, :invalid_tags}
end
end
@doc """
Creates an application tag bitstring from a result flags.
"""
@spec to_bitstring(t()) :: BACnet.Protocol.ApplicationTags.primitive_encoding()
def to_bitstring(%__MODULE__{} = t) do
{:bitstring, {t.first_item, t.last_item, t.more_items}}
end
@doc """
Validates whether the given result flags is in form valid.
It only validates the struct is valid as per type specification.
"""
@spec valid?(t()) :: boolean()
def valid?(
%__MODULE__{
first_item: first_item,
last_item: last_item,
more_items: more_items
} = _t
)
when is_boolean(first_item) and is_boolean(last_item) and is_boolean(more_items),
do: true
def valid?(%__MODULE__{} = _t), do: false
end