You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/architecture.md
+21Lines changed: 21 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -106,6 +106,27 @@ MAC address format varies by transport:
106
106
107
107
`AnyTransport<S>` is a type-erased enum wrapping all transport types, enabling mixed-transport routing (e.g., BIP + MS/TP + Loopback on the same router).
108
108
109
+
### RS-485 Direction Control (MS/TP)
110
+
111
+
RS-485 is half-duplex — the transceiver's DE/RE pin must be toggled between transmit and receive. The stack supports three modes:
112
+
113
+
```
114
+
┌──────────────────────────┐
115
+
USB RS-485 Adapter ──────────>│ TokioSerialPort │ Auto-direction
(DE wired to UART RTS pin) │ .enable_kernel_rs485() │ (TIOCSRS485 ioctl)
121
+
└──────────────────────────┘
122
+
123
+
UART + GPIO → DE/RE ─────────>│ GpioDirectionPort<S> │ GPIO direction
124
+
(Pi hat, GPIO pin for DE) │ wraps any SerialPort │ (gpiocdev, serial-gpio feature)
125
+
└──────────────────────────┘
126
+
```
127
+
128
+
`GpioDirectionPort` is a composable wrapper — it wraps any `SerialPort` and toggles a GPIO pin via the Linux character device API (`/dev/gpiochipN`) before and after each write. This keeps `TokioSerialPort` simple and platform-independent.
129
+
109
130
## Object Model
110
131
111
132
Every BACnet object implements the `BACnetObject` trait:
The SC hub is a TLS WebSocket relay. Both clients and servers connect to it as spoke nodes. Messages are routed by VMAC address.
303
304
305
+
### MS/TP (Serial RS-485)
306
+
307
+
MS/TP is a token-passing protocol over RS-485 serial, commonly used for field-level BACnet devices. The serial I/O is abstracted behind the `SerialPort` trait, with three RS-485 direction control modes.
308
+
309
+
#### Auto-Direction (USB RS-485 Adapters)
310
+
311
+
Most USB RS-485 adapters (FTDI, CH340, CP2102) handle direction switching in hardware — no configuration needed.
// Use with BACnetClient or BACnetServer via generic_builder
323
+
letclient=BACnetClient::generic_builder()
324
+
.transport(MstpTransport::new(serial, 1, 127)) // station 1, max_master 127
325
+
.build()
326
+
.await?;
327
+
```
328
+
329
+
#### Kernel RS-485 Mode (Linux, RTS-based)
330
+
331
+
When DE/RE is wired to the UART's RTS pin, the Linux kernel can toggle it automatically via the `TIOCSRS485` ioctl. Zero userspace overhead.
332
+
333
+
```rust
334
+
letserial=TokioSerialPort::open(&config)?;
335
+
serial.enable_kernel_rs485(
336
+
false, // invert_rts: false = RTS HIGH during TX
337
+
0, // delay_before_send_us
338
+
0, // delay_after_send_us
339
+
)?;
340
+
```
341
+
342
+
#### GPIO Direction Control (RS-485 Hats)
343
+
344
+
For RS-485 hats where DE/RE is wired to a GPIO pin (e.g., Seeed Studio RS-485 Shield on Raspberry Pi with GPIO18), use `GpioDirectionPort` to wrap any `SerialPort`. Requires the `serial-gpio` feature.
0 commit comments