Current section
Files
Jump to
Current section
Files
lib/bacnet/protocol/services/ack/atomic_write_file_ack.ex
defmodule BACnet.Protocol.Services.Ack.AtomicWriteFileAck do
# TODO: Docs
alias BACnet.Protocol.APDU.ComplexACK
alias BACnet.Protocol.ApplicationTags
alias BACnet.Protocol.Constants
require Constants
@type t :: %__MODULE__{
stream_access: boolean(),
start_position: integer()
}
@fields [:stream_access, :start_position]
@enforce_keys @fields
defstruct @fields
@service_name Constants.macro_assert_name(
:confirmed_service_choice,
:atomic_write_file
)
@spec from_apdu(ComplexACK.t()) :: {:ok, t()} | {:error, term()}
def from_apdu(
%ComplexACK{
service: @service_name,
payload: [
tagged: {tag, start_pos, _len}
]
} = _ack
)
when tag in [0, 1] do
with {:ok, {:signed_integer, start_position}} <-
ApplicationTags.unfold_to_type(:signed_integer, start_pos) do
struc = %__MODULE__{
stream_access: tag == 0,
start_position: start_position
}
{:ok, struc}
end
end
def from_apdu(_ack) do
{:error, :invalid_service_ack}
end
@spec to_apdu(t(), 0..255) :: {:ok, ComplexACK.t()} | {:error, term()}
def to_apdu(ack, invoke_id \\ 0)
def to_apdu(%__MODULE__{} = ack, invoke_id)
when invoke_id in 0..255 do
with {:ok, start_pos, _header} <-
ApplicationTags.encode_value({:signed_integer, ack.start_position}) do
new_ack = %ComplexACK{
invoke_id: invoke_id,
sequence_number: nil,
proposed_window_size: nil,
service: @service_name,
payload: [
tagged: {if(ack.stream_access, do: 0, else: 1), start_pos, byte_size(start_pos)}
]
}
{:ok, new_ack}
end
end
def to_apdu(%__MODULE__{} = _ack, _invoke_id) do
{:error, :invalid_parameter}
end
end