Skip to content

Commit 224ecab

Browse files
author
CI
committed
Sync to GitHub
1 parent 350f22f commit 224ecab

1 file changed

Lines changed: 105 additions & 100 deletions

File tree

lib/bacnet/stack/transport/mstp_transport.ex

Lines changed: 105 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ if Code.ensure_loaded?(Circuits.UART) do
484484
:supervisor
485485
])
486486

487-
validate_open_opts(opts2)
487+
validate_open_opts(opts2, "open/2")
488488

489489
GenServer.start_link(__MODULE__, {callback, Map.new(opts2)}, genserver_opts)
490490
end
@@ -497,6 +497,91 @@ if Code.ensure_loaded?(Circuits.UART) do
497497
GenServer.call(transport, :close)
498498
end
499499

500+
@doc """
501+
Get the current transport state.
502+
503+
This function is important when disabling token passing and
504+
waiting for the transport to transition to the IDLE or NO_TOKEN state,
505+
to then be able to shut down the transport gracefully.
506+
507+
See also `disable_token_passing/1`.
508+
"""
509+
@spec get_state(TransportBehaviour.transport()) :: :idle | :no_token | atom()
510+
def get_state(transport) when is_server(transport) do
511+
GenServer.call(transport, :get_state)
512+
end
513+
514+
@doc """
515+
Disables the transport's token passing (only if master node).
516+
517+
Disabling the token passing will try to pass on the token, if held,
518+
as soon as possible, but only if the successor is known.
519+
If the successor is unknown or a timeout occurrs, the token will be dropped.
520+
The consequence of dropping the token will be that the remaining
521+
MS/TP master nodes will notice the lost token and generate a new token.
522+
523+
Whether it transitions to IDLE or NO_TOKEN state depends on
524+
its current state and could even change later on from IDLE to NO_TOKEN.
525+
Once the transport reaches IDLE or NO_TOKEN, the transport can be
526+
safely shut down.
527+
528+
When the token passing is disabled, sending any frame that does not
529+
involve sending a reply is disabled and return an error.
530+
531+
After disabling the transport token passing, it can only be re-enabled
532+
by restarting the transport.
533+
"""
534+
@spec disable_token_passing(TransportBehaviour.transport()) :: :ok | {:error, term()}
535+
def disable_token_passing(transport) when is_server(transport) do
536+
GenServer.call(transport, :disable_token_passing)
537+
end
538+
539+
@doc """
540+
Configures the transport.
541+
542+
Only some of the available `t:open_options/0` can be configured,
543+
unsupported options can only be changed by re-starting the transport completely.
544+
545+
The following options are supported:
546+
- `baudrate`
547+
- `log_communication`
548+
- `log_communication_rcv`
549+
- `max_info_frames`
550+
- `max_master_address`
551+
552+
For a description of each option, see `open/2`.
553+
554+
Note that reconfiguring the baudrate on the fly MAY lead to invalid frames!
555+
May also lead to dropping token.
556+
"""
557+
@spec configure(TransportBehaviour.transport(), open_options()) :: :ok | {:error, term()}
558+
def configure(transport, opts) when is_server(transport) and is_list(opts) do
559+
unless Keyword.keyword?(opts) do
560+
raise ArgumentError, "configure/2 expected a keyword list, got: #{inspect(opts)}"
561+
end
562+
563+
validate_open_opts(opts, "configure/2")
564+
565+
Enum.each(opts, fn
566+
# Supported options
567+
{key, _val}
568+
when key in [
569+
:baudrate,
570+
:log_communication,
571+
:log_communication_rcv,
572+
:max_info_frames,
573+
:max_master_address
574+
] ->
575+
true
576+
577+
{key, _val} ->
578+
raise ArgumentError,
579+
"configure/2 does not supported option " <> inspect(key)
580+
end)
581+
582+
GenServer.call(transport, {:configure, Map.new(opts)})
583+
end
584+
500585
@doc """
501586
Get the broadcast address.
502587
"""
@@ -714,94 +799,6 @@ if Code.ensure_loaded?(Circuits.UART) do
714799
is_integer(destination) and destination >= 0 and destination <= 255
715800
end
716801

717-
@doc """
718-
Get the current transport state.
719-
720-
This function is important when disabling token passing and
721-
waiting for the transport to transition to the IDLE or NO_TOKEN state,
722-
to then be able to shut down the transport gracefully.
723-
724-
See also `disable_token_passing/1`.
725-
"""
726-
@spec get_state(TransportBehaviour.transport()) :: :idle | :no_token | atom()
727-
def get_state(transport) when is_server(transport) do
728-
GenServer.call(transport, :get_state)
729-
end
730-
731-
@doc """
732-
Disables the transport's token passing (only if master node).
733-
734-
Disabling the token passing will try to pass on the token, if held,
735-
as soon as possible, but only if the successor is known.
736-
If the successor is unknown or a timeout occurrs, the token will be dropped.
737-
The consequence of dropping the token will be that the remaining
738-
MS/TP master nodes will notice the lost token and generate a new token.
739-
740-
Whether it transitions to IDLE or NO_TOKEN state depends on
741-
its current state and could even change later on from IDLE to NO_TOKEN.
742-
Once the transport reaches IDLE or NO_TOKEN, the transport can be
743-
safely shut down.
744-
745-
When the token passing is disabled, sending any frame that does not
746-
involve sending a reply is disabled and return an error.
747-
748-
After disabling the transport token passing, it can only be re-enabled
749-
by restarting the transport.
750-
"""
751-
@spec disable_token_passing(TransportBehaviour.transport()) :: :ok | {:error, term()}
752-
def disable_token_passing(transport) when is_server(transport) do
753-
GenServer.call(transport, :disable_token_passing)
754-
end
755-
756-
@doc """
757-
Configures the transport.
758-
759-
Only some of the available `t:open_options/0` can be configured,
760-
unsupported options can only be changed by re-starting the transport completely.
761-
762-
The following options are supported:
763-
- `baudrate`
764-
- `log_communication`
765-
- `log_communication_rcv`
766-
- `max_info_frames`
767-
- `max_master_address`
768-
769-
For a description of each option, see `open/2`.
770-
771-
Note that reconfiguring the baudrate on the fly MAY lead to invalid frames!
772-
May also lead to dropping token.
773-
"""
774-
@spec configure(TransportBehaviour.transport(), open_options()) :: :ok | {:error, term()}
775-
def configure(transport, opts) when is_server(transport) and is_list(opts) do
776-
unless Keyword.keyword?(opts) do
777-
raise ArgumentError, "configure/2 expected a keyword list, got: #{inspect(opts)}"
778-
end
779-
780-
Enum.each(opts, fn
781-
{:baudrate, val} when is_integer(val) and val > 0 ->
782-
true
783-
784-
{:log_communication, val} when is_boolean(val) ->
785-
true
786-
787-
{:log_communication_rcv, val} when is_boolean(val) ->
788-
true
789-
790-
{:max_info_frames, val} when is_integer(val) and val > 0 ->
791-
true
792-
793-
{:max_master_address, val} when is_integer(val) and val > 0 ->
794-
true
795-
796-
{key, val} ->
797-
raise ArgumentError,
798-
"configure/2 received unsupported combination - key: " <>
799-
inspect(key) <> ", value: " <> inspect(val)
800-
end)
801-
802-
GenServer.call(transport, {:configure, Map.new(opts)})
803-
end
804-
805802
@doc false
806803
def init({callback, opts}) do
807804
new_opts =
@@ -3279,7 +3276,7 @@ if Code.ensure_loaded?(Circuits.UART) do
32793276
end
32803277

32813278
# credo:disable-for-lines:50 Credo.Check.Refactor.CyclomaticComplexity
3282-
defp validate_open_opts(opts) do
3279+
defp validate_open_opts(opts, mfa) when is_binary(mfa) do
32833280
case opts[:baudrate] do
32843281
nil ->
32853282
:ok
@@ -3289,21 +3286,23 @@ if Code.ensure_loaded?(Circuits.UART) do
32893286

32903287
term ->
32913288
raise ArgumentError,
3292-
"open/2 expected baudrate to be a non negative integer, " <>
3289+
mfa <>
3290+
" expected baudrate to be a non negative integer, " <>
32933291
"got: #{inspect(term)}"
32943292
end
32953293

32963294
case opts[:local_address] do
32973295
nil ->
32983296
raise ArgumentError,
3299-
"open/2 expected local_address to be present (absent in opts)"
3297+
mfa <> " expected local_address to be present (absent in opts)"
33003298

33013299
term when is_integer(term) and term >= @min_master_addr and term <= @max_slave_addr ->
33023300
:ok
33033301

33043302
term ->
33053303
raise ArgumentError,
3306-
"open/2 expected local_address to be a valid address in the range of 0-254, " <>
3304+
mfa <>
3305+
" expected local_address to be a valid address in the range of 0-254, " <>
33073306
"got: #{inspect(term)}"
33083307
end
33093308

@@ -3316,7 +3315,8 @@ if Code.ensure_loaded?(Circuits.UART) do
33163315

33173316
term ->
33183317
raise ArgumentError,
3319-
"open/2 expected log_communication to be a boolean, " <>
3318+
mfa <>
3319+
" expected log_communication to be a boolean, " <>
33203320
"got: #{inspect(term)}"
33213321
end
33223322

@@ -3329,7 +3329,8 @@ if Code.ensure_loaded?(Circuits.UART) do
33293329

33303330
term ->
33313331
raise ArgumentError,
3332-
"open/2 expected log_communication_rcv to be a boolean, " <>
3332+
mfa <>
3333+
" expected log_communication_rcv to be a boolean, " <>
33333334
"got: #{inspect(term)}"
33343335
end
33353336

@@ -3342,7 +3343,8 @@ if Code.ensure_loaded?(Circuits.UART) do
33423343

33433344
term ->
33443345
raise ArgumentError,
3345-
"open/2 expected max_info_frames to be a positive integer, " <>
3346+
mfa <>
3347+
" expected max_info_frames to be a positive integer, " <>
33463348
"got: #{inspect(term)}"
33473349
end
33483350

@@ -3355,21 +3357,23 @@ if Code.ensure_loaded?(Circuits.UART) do
33553357

33563358
term ->
33573359
raise ArgumentError,
3358-
"open/2 expected max_master_address to be an integer in the range 0-127, " <>
3360+
mfa <>
3361+
" expected max_master_address to be an integer in the range 0-127, " <>
33593362
"got: #{inspect(term)}"
33603363
end
33613364

33623365
case opts[:port_name] do
33633366
nil ->
33643367
raise ArgumentError,
3365-
"open/2 expected port_name to be present (absent in opts)"
3368+
mfa <> " expected port_name to be present (absent in opts)"
33663369

33673370
term when is_binary(term) ->
33683371
:ok
33693372

33703373
term ->
33713374
raise ArgumentError,
3372-
"open/2 expected port_name to be a binary, " <>
3375+
mfa <>
3376+
" expected port_name to be a binary, " <>
33733377
"got: #{inspect(term)}"
33743378
end
33753379

@@ -3394,7 +3398,8 @@ if Code.ensure_loaded?(Circuits.UART) do
33943398

33953399
term ->
33963400
raise ArgumentError,
3397-
"open/2 expected supervisor to be a valid supervisor reference, " <>
3401+
mfa <>
3402+
" expected supervisor to be a valid supervisor reference, " <>
33983403
"got: #{inspect(term)}"
33993404
end
34003405
end

0 commit comments

Comments
 (0)