Current section
Files
Jump to
Current section
Files
docs/architecture.md
# アーキテクチャ
このページは、AVModbus の内部構造を理解したい開発者向けです。
最初に使う場合は [はじめ方](getting-started.md) を参照してください。
## 基本方針
**Modbus の通信ルールと、UART や TCP でデータを運ぶ処理を分ける**ことを重視しています。
そのため、通信フレームの処理は普通の BEAM 上でもテストでき、実機固有の処理は入れ替えられます。
```text
Application
|-- AVModbus.Client / AVModbus.Server
| `-- AVModbus.PDU(読み書きする内容)
| |-- AVModbus.RTU (CRC とフレーム)
| |-- AVModbus.ASCII (LRC とフレーム)
| `-- AVModbus.TCP (MBAP とフレーム)
|
|-- Serial Transport --> AVModbus.UART --> AtomVM :uart
`-- TCP socket ------------------------> :gen_tcp
```
`AVModbus.PDU` は Function Code ごとのエンコード・デコードを担当します。
RTU・ASCII・TCP の各モジュールは、通信方式ごとのフレームを扱います。
Client / Server が接続と要求の処理を管理します。
## UART と RS485
`AVModbus.Serial.Transport` は `open/1`・`read`・`write`・`close` の共通インターフェースです。
既定の `AVModbus.UART` は AtomVM の UART を使います。
UART 番号、ピン、通信速度はアプリケーション設定から読み、`serial:` で接続ごとに上書きできます。
AtomVM 0.7 / ESP32-C5 では、UART の読み取りと次の読み取りの間にデータを失う場合がありました。
そのため、専用プロセスで継続して読み取り、受信データを上限 2,048 byte のバッファーに渡します。
RX idle timeout の既定値は、実機で確認した **20 ms** です。
Modbus RTU の送信間隔やフレーム判定の待ち時間とは別の設定です。
UART の読み取りに失敗した場合は、古い受信データを捨ててエラーを通知します。
Client / Server が UART を管理していれば再接続を試みます。
一方、アプリケーションから UART ハンドルを渡した場合は、開閉と復旧をアプリケーションが担当します。
方向切り替えが必要な RS485 モジュールでは、その処理を Transport の `write/2` に含めます。
Client / Server 自体は GPIO を操作しません。
判断理由は
[ADR 0019](https://github.com/piyopiyoex/avmodbus/blob/v0.1.0/docs/adr/0019-keep-uart-configuration-at-transport-boundary.md)
にあります。
## Client の管理
- Serial では、1 本の通信路で要求を **順番に 1 件ずつ**処理します。
- TCP では Transaction ID を使い、複数の要求と応答を対応付けます。
- 待機キューには上限があり、満杯の場合は `{:error, :queue_full}` を返します。
- タイムアウトにはキューでの待ち時間も含めます。非同期要求も結果を一度だけ通知します。
- 書き込みの二重実行を避けるため、自動リトライは明示された読み取り処理だけに限定します。
- 通信が切れた場合は、必要に応じて再接続します。
詳しい動作と API は [開発者ガイド](development.md) を参照してください。
## Server の管理
Serial Server は受信したフレームを解釈し、`AVModbus.Server` に処理を渡します。
TCP Server は接続ごとに処理を分け、遅い Client が別の接続に与える影響を抑えます。
TCP の `max_buffer`(既定 2,048 byte)は **受信ブローカーがまだ渡していないデータの上限**です。
ソケットの受信待ちや処理中のデータ、AtomVM 側のバッファーを含めた、
接続全体のメモリ使用量の上限ではありません。
接続を閉じる際は、処理中の handler も終了させます。ブローカーが強制終了した場合も、
listener が生きていれば handler を終了するための代替処理を行います。
終了待ちは無期限にならないよう制限しています。
詳細は
[ADR 0007](https://github.com/piyopiyoex/avmodbus/blob/v0.1.0/docs/adr/0007-isolate-modbus-tcp-connections.md)
に残しています。
## AtomVM での制約
- Modbus/TCP Security に必要な相互認証 TLS が使えないため、TLS の指定はエラーになります。
- ESP32-C5 では TCP の負荷を増やしすぎると、ランタイムが応答しなくなる現象を確認しています。
- RTU の既定タイミングは検証済みの UART / RS485 構成に基づきます。
これらの詳細は
[既知の TCP 制約](https://github.com/piyopiyoex/avmodbus/blob/v0.1.0/docs/limitations.md) と
[開発資料](https://github.com/piyopiyoex/avmodbus/blob/v0.1.0/docs/development/README.md)
を参照してください。