Skip to content

Commit ec080ef

Browse files
author
CI
committed
Sync to GitHub
1 parent c48ee81 commit ec080ef

1 file changed

Lines changed: 55 additions & 5 deletions

File tree

lib/bacnet/stack/transport/mstp_transport.ex

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ if Code.ensure_loaded?(Circuits.UART) do
207207
answer_invoke_id: non_neg_integer() | nil,
208208
send_queue: :queue.queue(send_item()),
209209
send_timer: :timer.tref() | nil,
210+
disable_maintenance_pfm: boolean(),
210211
disable_token_passing: boolean(),
211212
autobaud_baudrate: non_neg_integer() | nil,
212213
autobaud_baudrates_pending: [non_neg_integer()] | nil,
@@ -244,6 +245,7 @@ if Code.ensure_loaded?(Circuits.UART) do
244245
:answer_invoke_id,
245246
:send_queue,
246247
:send_timer,
248+
:disable_maintenance_pfm,
247249
:disable_token_passing,
248250
:autobaud_baudrate,
249251
:autobaud_baudrates_pending,
@@ -865,11 +867,7 @@ if Code.ensure_loaded?(Circuits.UART) do
865867
866868
There are no options at this time.
867869
"""
868-
@spec reply_postponed(
869-
portal :: TransportBehaviour.portal(),
870-
destination :: source_address(),
871-
opts :: Keyword.t()
872-
) ::
870+
@spec reply_postponed(TransportBehaviour.portal(), source_address(), Keyword.t()) ::
873871
:ok
874872
| {:error, term()}
875873
| {:error, :slave_mode}
@@ -881,6 +879,20 @@ if Code.ensure_loaded?(Circuits.UART) do
881879
GenServer.call(portal, {:reply_postponed, destination, opts}, @call_timeout)
882880
end
883881

882+
@doc """
883+
Enables or disables maintenance POLL_FOR_MASTER in the case the successor node is known.
884+
If the successor node is unknown, POLL_FOR_MASTER will be regardless done.
885+
886+
This function is only for development and testing purpose. It must not be used in production.
887+
Periodic maintenance polling for masters is required to find new nodes in between this node
888+
and the next current successor node. Nodes may come up and go down any time, which
889+
the BACnet specification accounts for and thus includes a POLL_FOR_MASTER mechanism.
890+
"""
891+
@spec set_maintenance_pfm(TransportBehaviour.transport(), boolean()) :: :ok
892+
def set_maintenance_pfm(transport, state) when is_server(transport) and is_boolean(state) do
893+
GenServer.call(transport, {:disable_maintenance_pfm, not state})
894+
end
895+
884896
@doc false
885897
def init({callback, opts}) do
886898
new_opts =
@@ -946,6 +958,7 @@ if Code.ensure_loaded?(Circuits.UART) do
946958
answer_invoke_id: nil,
947959
send_queue: :queue.new(),
948960
send_timer: nil,
961+
disable_maintenance_pfm: false,
949962
disable_token_passing: false,
950963
autobaud_baudrate: nil,
951964
autobaud_baudrates_pending: nil,
@@ -1296,6 +1309,33 @@ if Code.ensure_loaded?(Circuits.UART) do
12961309
end
12971310
end
12981311

1312+
defp do_handle_continue(
1313+
:done_with_token,
1314+
%State{
1315+
local_address: local_addr,
1316+
disable_maintenance_pfm: true,
1317+
disable_token_passing: false,
1318+
state_machine: %{ns: ns, ps: ps, token_count: tokens} = state_machine
1319+
} =
1320+
state
1321+
)
1322+
when local_addr < @min_slave_addr and
1323+
ns != rem(ps + 1, state.opts.max_master_address + 1) and
1324+
tokens >= @param_n_poll - 1 do
1325+
log_debug(fn ->
1326+
"BacMstpTransport: Reached state DONE_WITH_TOKEN and skipping maintenance POLL_FOR_MASTER, " <>
1327+
"skipping to USE_TOKEN instead (maintenance PFM disabled)"
1328+
end)
1329+
1330+
new_state = %{
1331+
state
1332+
| state_machine: %{state_machine | frame_count: 0, token_count: 0},
1333+
transport_state: :use_token
1334+
}
1335+
1336+
{:noreply, new_state, {:continue, :use_token}}
1337+
end
1338+
12991339
# If token passing is disabled, do not engage maintenance PFM, instead:
13001340
# - If successor known, pass it to the successor
13011341
# - If successor unknown, drop the token
@@ -1752,6 +1792,16 @@ if Code.ensure_loaded?(Circuits.UART) do
17521792
{:reply, {:error, :slave_mode}, state}
17531793
end
17541794

1795+
defp do_handle_call({:disable_maintenance_pfm, pfm_state}, _from, %State{} = state)
1796+
when is_boolean(pfm_state) do
1797+
log_debug(fn ->
1798+
"BacMstpTransport: Received disable_maintenance_pfm request with " <>
1799+
"value #{pfm_state}"
1800+
end)
1801+
1802+
{:reply, :ok, %{state | disable_maintenance_pfm: pfm_state}}
1803+
end
1804+
17551805
defp do_handle_call(_call, _from, state) do
17561806
{:noreply, state}
17571807
end

0 commit comments

Comments
 (0)