Skip to content

Commit bc75750

Browse files
author
CI
committed
Sync to GitHub
1 parent fa242ac commit bc75750

3 files changed

Lines changed: 117 additions & 111 deletions

File tree

lib/bacnet/stack/transport/mstp_transport.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ if Code.ensure_loaded?(Circuits.UART) do
1818

1919
# TODO: Convert Master Node FSM to :gen_statem?
2020

21+
# For testing we can use `socat -d -d pty,rawer,echo=0 pty,rawer,echo=0` in the future
22+
# Output will contain two lines of `N PTY is /dev/pts/{number}` with can then be opened
23+
# using Circuits.UART.open(pid, "dev/pts/{number}")
24+
2125
alias __MODULE__
2226
alias __MODULE__.EncodingTools
2327
alias __MODULE__.ReceiveFSM

lib/bacnet/stack/transport/mstp_transport/receive_fsm.ex

Lines changed: 1 addition & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ if Code.ensure_loaded?(Circuits.UART) do
55
# It is implemented using :gen_statem and is the controlling process for the UART port,
66
# and as such receives transport data directly.
77

8+
alias __MODULE__.StateData
89
alias BACnet.Protocol.Constants
910
alias BACnet.Stack.Transport.MstpTransport
1011
alias BACnet.Stack.Transport.MstpTransport.EncodingTools
@@ -38,117 +39,6 @@ if Code.ensure_loaded?(Circuits.UART) do
3839
@param_n_min_cobs_length 5
3940
@param_n_max_cobs_length 2043
4041

41-
defmodule StateData do
42-
@moduledoc false
43-
44-
@typedoc """
45-
Receive State Data for the MS/TP Transport Receive State Machine.
46-
47-
From ASHRAE 135 Clause 9.5.2:
48-
49-
DataCRC: Used to accumulate the CRC on the data field of a frame.
50-
DataLength: Used to store the data length of a received frame.
51-
DestinationAddress: Used to store the destination address of a received frame.
52-
EventCount: Used to count the number of received octets or errors. This is used in the detection of link activity.
53-
FrameType: Used to store the frame type of a received frame.
54-
HeaderCRC: Used to accumulate the CRC on the header of a frame.
55-
Index: Used as an index by the Receive State Machine, up to the value of DataLength+1.
56-
InputBuffer[]: An array of octets, used to store octets as they are received. InputBuffer is indexed from 0 to InputBufferSize-1.
57-
GoodHeader: A Boolean flag set to TRUE or FALSE by the CheckHeader procedure (see Clause 9.5.8).
58-
ReceivedInvalidFrame: A Boolean flag set to TRUE by the Receive State Machine if an error is detected during the reception of a frame.
59-
ReceivedValidFrame: A Boolean flag set to TRUE by the Receive State Machine if a valid frame is received.
60-
SilenceTimer: A timer with nominal 5 millisecond resolution used to measure and generate silence on the medium between octets.
61-
It is incremented by a timer process and is cleared by the Receive State Machine when activity is detected and
62-
by the SendFrame procedure as each octet is transmitted. Since the timer resolution is limited and the timer is
63-
not necessarily synchronized to other machine events, a timer value of N will actually denote intervals between N-1 and N.
64-
SourceAddress: Used to store the Source Address of a received frame.
65-
"""
66-
@type t :: %__MODULE__{
67-
transport_master: pid(),
68-
uart_port: pid(),
69-
local_address: 0..254,
70-
opts: %{
71-
baudrate: non_neg_integer(),
72-
log_communication: boolean()
73-
},
74-
data_crc_header: non_neg_integer(),
75-
data_crc: non_neg_integer(),
76-
data_length: non_neg_integer(),
77-
destination_address: 0..255,
78-
event_count: integer(),
79-
frame_type: MstpTransport.frame_type(),
80-
frame_type_raw: 0..255,
81-
header_crc: non_neg_integer(),
82-
index: non_neg_integer(),
83-
input_buffer: iodata(),
84-
good_header: boolean(),
85-
received_invalid_frame: boolean(),
86-
received_valid_frame: boolean(),
87-
silence_timer: term() | nil,
88-
silence_timestamp: non_neg_integer() | nil,
89-
source_address: 0..254
90-
}
91-
92-
@fields [
93-
:transport_master,
94-
:uart_port,
95-
:local_address,
96-
:opts,
97-
:data_crc_header,
98-
:data_crc,
99-
:data_length,
100-
:destination_address,
101-
:event_count,
102-
:frame_type,
103-
:frame_type_raw,
104-
:header_crc,
105-
:index,
106-
:input_buffer,
107-
:good_header,
108-
:received_invalid_frame,
109-
:received_valid_frame,
110-
:retry_count,
111-
:silence_timer,
112-
:silence_timestamp,
113-
:source_address
114-
]
115-
@enforce_keys @fields
116-
defstruct @fields
117-
118-
@spec new(pid(), pid(), Keyword.t()) :: t()
119-
def new(master, uart_port, opts) do
120-
new_opts =
121-
opts
122-
|> Map.new()
123-
|> Map.put_new(:baudrate, 38400)
124-
|> Map.put_new(:log_communication, false)
125-
126-
%__MODULE__{
127-
transport_master: master,
128-
uart_port: uart_port,
129-
local_address: Map.fetch!(new_opts, :local_address),
130-
opts: Map.drop(new_opts, [:local_address]),
131-
data_crc_header: 0,
132-
data_crc: 0,
133-
data_length: 0,
134-
destination_address: 0,
135-
event_count: 0,
136-
frame_type: :unknown,
137-
frame_type_raw: 0,
138-
header_crc: 0,
139-
index: 0,
140-
input_buffer: [],
141-
good_header: false,
142-
received_invalid_frame: false,
143-
received_valid_frame: false,
144-
retry_count: 0,
145-
silence_timer: nil,
146-
silence_timestamp: nil,
147-
source_address: 0
148-
}
149-
end
150-
end
151-
15242
defmacrop log_debug_comm(state, message_or_fun) do
15343
quote bind_quoted: [message_or_fun: message_or_fun, state: state],
15444
generated: true,
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
defmodule BACnet.Stack.Transport.MstpTransport.ReceiveFSM.StateData do
2+
@moduledoc false
3+
4+
alias BACnet.Stack.Transport.MstpTransport
5+
6+
@typedoc """
7+
Receive State Data for the MS/TP Transport Receive State Machine.
8+
9+
From ASHRAE 135 Clause 9.5.2:
10+
11+
DataCRC: Used to accumulate the CRC on the data field of a frame.
12+
DataLength: Used to store the data length of a received frame.
13+
DestinationAddress: Used to store the destination address of a received frame.
14+
EventCount: Used to count the number of received octets or errors. This is used in the detection of link activity.
15+
FrameType: Used to store the frame type of a received frame.
16+
HeaderCRC: Used to accumulate the CRC on the header of a frame.
17+
Index: Used as an index by the Receive State Machine, up to the value of DataLength+1.
18+
InputBuffer[]: An array of octets, used to store octets as they are received. InputBuffer is indexed from 0 to InputBufferSize-1.
19+
GoodHeader: A Boolean flag set to TRUE or FALSE by the CheckHeader procedure (see Clause 9.5.8).
20+
ReceivedInvalidFrame: A Boolean flag set to TRUE by the Receive State Machine if an error is detected during the reception of a frame.
21+
ReceivedValidFrame: A Boolean flag set to TRUE by the Receive State Machine if a valid frame is received.
22+
SilenceTimer: A timer with nominal 5 millisecond resolution used to measure and generate silence on the medium between octets.
23+
It is incremented by a timer process and is cleared by the Receive State Machine when activity is detected and
24+
by the SendFrame procedure as each octet is transmitted. Since the timer resolution is limited and the timer is
25+
not necessarily synchronized to other machine events, a timer value of N will actually denote intervals between N-1 and N.
26+
SourceAddress: Used to store the Source Address of a received frame.
27+
"""
28+
@type t :: %__MODULE__{
29+
transport_master: pid(),
30+
uart_port: pid(),
31+
local_address: 0..254,
32+
opts: %{
33+
baudrate: non_neg_integer(),
34+
log_communication: boolean()
35+
},
36+
data_crc_header: non_neg_integer(),
37+
data_crc: non_neg_integer(),
38+
data_length: non_neg_integer(),
39+
destination_address: 0..255,
40+
event_count: integer(),
41+
frame_type: MstpTransport.frame_type(),
42+
frame_type_raw: 0..255,
43+
header_crc: non_neg_integer(),
44+
index: non_neg_integer(),
45+
input_buffer: iodata(),
46+
good_header: boolean(),
47+
received_invalid_frame: boolean(),
48+
received_valid_frame: boolean(),
49+
silence_timer: term() | nil,
50+
silence_timestamp: non_neg_integer() | nil,
51+
source_address: 0..254
52+
}
53+
54+
@fields [
55+
:transport_master,
56+
:uart_port,
57+
:local_address,
58+
:opts,
59+
:data_crc_header,
60+
:data_crc,
61+
:data_length,
62+
:destination_address,
63+
:event_count,
64+
:frame_type,
65+
:frame_type_raw,
66+
:header_crc,
67+
:index,
68+
:input_buffer,
69+
:good_header,
70+
:received_invalid_frame,
71+
:received_valid_frame,
72+
:retry_count,
73+
:silence_timer,
74+
:silence_timestamp,
75+
:source_address
76+
]
77+
@enforce_keys @fields
78+
defstruct @fields
79+
80+
@spec new(pid(), pid(), Keyword.t()) :: t()
81+
def new(master, uart_port, opts) do
82+
new_opts =
83+
opts
84+
|> Map.new()
85+
|> Map.put_new(:baudrate, 38400)
86+
|> Map.put_new(:log_communication, false)
87+
88+
%__MODULE__{
89+
transport_master: master,
90+
uart_port: uart_port,
91+
local_address: Map.fetch!(new_opts, :local_address),
92+
opts: Map.drop(new_opts, [:local_address]),
93+
data_crc_header: 0,
94+
data_crc: 0,
95+
data_length: 0,
96+
destination_address: 0,
97+
event_count: 0,
98+
frame_type: :unknown,
99+
frame_type_raw: 0,
100+
header_crc: 0,
101+
index: 0,
102+
input_buffer: [],
103+
good_header: false,
104+
received_invalid_frame: false,
105+
received_valid_frame: false,
106+
retry_count: 0,
107+
silence_timer: nil,
108+
silence_timestamp: nil,
109+
source_address: 0
110+
}
111+
end
112+
end

0 commit comments

Comments
 (0)