lib60870は電力系統の監視制御向けに設計されたオープンソースCライブラリであり、IEC 60870-5-101(シリアル)および104(TCP/IP)規格に準拠した通信スタックを提供します。本ドキュメントでは、同ライブラリを用いたサーバーノードの初期化手順、モジュール構成の解説、および実務で頻出するテレメトリ送信と制御コマンド処理の実装パターンを技術的に解説します。
通信サーバーの構築手順
IEC 60870-5-104準拠の応答ノードを構築するには、以下の初期化フローに従います。ライブラリは優先度別のメッセージキューを内蔵しており、アプリケーションの特性に応じてバッファサイズを調整可能です。
/* キュー容量の定義とインスタンス生成 */
#define TX_QUEUE_HIGH 16
#define TX_QUEUE_LOW 16
CS104_Slave comm_endpoint = CS104_Slave_create(TX_QUEUE_HIGH, TX_QUEUE_LOW);
/* リッスン設定の適用 */
CS104_Slave_setLocalAddress(comm_endpoint, "0.0.0.0");
/* ASDU受信ハンドラの登録 */
CS104_Slave_setASDUReceivedCallback(comm_endpoint, process_master_request, NULL);
/* 接続待ちスレッドの起動 */
if (!CS104_Slave_startServer(comm_endpoint)) {
/* エラー処理: ポット占有または設定不正 */
return -1;
}
主要設定パラメータ
| 設定項目 | 既定値 | 動作仕様 | 適用ケース |
|---|---|---|---|
| TCPポート | 2404 | 標準IANA割り当て番号 | 基本ネットワーク構成 |
| キュー容量 | 10 | 高/低優先度別バッファサイズ | データバースト発生環境 |
| 接続タイムアウト | 30秒 | ハンドシェイク応答待機上限 | 回線品質が不安定な現場 |
アーキテクチャとモジュール構成
リポジトリは機能ごとに明確に分割されており、プロトコルスタックの理解と保守性を高めています。
src/hal/:ハードウェア抽象層。OS依存のソケット操作やタイマー処理を分離。src/iec60870/:プロトコルコア。101/104のエンコード・デコードおよび状態遷移制御を実装。examples/:各種ユースケースの参照実装。TLS対応サーバーや冗長構成クライアントを含む。tests/:自動単体テスト。パケット生成・解析の検証スイート。
プロトコルコア概念:ASDU構造
ASDU(Application Service Data Unit)は制御局と制御対象局間で交換される基本伝送単位です。開発時には以下の要素を正確にマッピングする必要があります。
- タイプ識別子:データの物理的意味を定義(例:M_ME_NA_1は計測値、M_SP_NA_1は単一状態情報)。
- 送信理由:サイクル送信、スポラディック送信、アクティベーションコマンドなど。
- 共通アドレス:データ発生源または宛先のステーション識別子。
- 情報オブジェクト:個別のアドレス、測定値、品質ビットを含むペイロード配列。
CS101とCS104の伝送方式比較
| 項目 | IEC 60870-5-101 | IEC 60870-5-104 |
|---|---|---|
| 伝送媒体 | RS232/RS485シリアル | Ethernet (TCP/IP) |
| トポロジ | ポイント・トゥ・ポイント/マルチドロップ | クライアント-サーバー型 |
| 主要用途 | 現地制御装置と制御盤間の近距離接続 | 広域制御センターと変電所間の遠隔監視 |
実装シナリオ:周期性テレメトリと制御応答
1. 計測値の定期送信
制御局に対して定周期でデータをプッシュする場合、ASDUの生成からキュー投入までの手順をメインループまたは専用タイマータスクに組み込みます。
void transmit_periodic_telemetry(CS104_Slave node, float raw_voltage) {
/* パラメータ取得と変換 */
CS104_LinkLayerParams* tx_params = CS104_Slave_getLinkLayerParams(node);
int16_t scaled_val = (int16_t)(raw_voltage * 10.0f);
uint8_t station_id = 5;
/* ASDUフレームの構築 */
CS101_ASDU* pdu = CS101_ASDU_create(tx_params, false, CS101_COT_PERIODIC,
0, station_id, false, false);
if (pdu == NULL) return;
/* 情報オブジェクトの注入 */
CS101_InfoObject_MeasuredValueScaled* obj =
(CS101_InfoObject_MeasuredValueScaled*)MeasuredValueScaled_create(NULL,
2001, scaled_val, IEC60870_QUALITY_GOOD);
CS101_ASDU_addInformationObject(pdu, (CS101_InformationObject*)obj);
CS101_InformationObject_destroy((CS101_InformationObject*)obj);
/* 送信キューへの登録とメモリ解放 */
CS104_Slave_enqueueASDU(node, pdu);
CS101_ASDU_destroy(pdu);
}
2. 遠隔制御コマンドの処理
制御局からのアクティベーション要求を受信した場合、ASDUタイプを判定し、情報オブジェクトからアドレスと動作値を抽出します。
bool handle_single_command(CS101_ASDU received_frame) {
if (CS101_ASDU_getTypeID(received_frame) != C_SC_NA_1) {
return false;
}
CS101_InformationObject* payload = CS101_ASDU_getElement(received_frame, 0);
if (!payload) return false;
uint16_t target_addr = CS101_InformationObject_getObjectAddress(payload);
bool select_execute = CS101_SingleCommand_getState((CS101_SingleCommand*)payload);
/* 制御デバイスへの命令発行 */
apply_switch_action(target_addr, select_execute);
/* リソースの適切な解放 */
CS101_InformationObject_destroy(payload);
return true;
}
メモリ管理とエラー耐性
組み込み環境や長周期運用を想定し、lib60870は以下の設計方針を採用しています。
- 事前割り当て:サーバーインスタンス生成時にキューバッファを固定確保し、実行中のヒープ断片化を抑制。
- 厳密なリターンチェック:APIの戻り値を必ず検証し、無効なポインターアクセスを防止。
- 再接続制御:TCP切断検知時に内部状態をリセットし、再リスンまたはクライアント側からの再接試行を許可。
高度な通信機能
TLS暗号化:mbedTLSを組み込むことでIEC 62351-3準拠のセキュアチャネルを構成可能です。X.509証明書と秘密鍵のパスを初期化パラメータに渡すだけで、平文TCPから暗号化TCPへの移行が実現します。
冗長化サポート:重要変電所向けに、複数IPエンドポイントを登録し、アクティブパスのダウン時に自動的に待機系へフェールオーバーする構成をサポートしています。
デバッグとトラブルシューティング
通信確立やデータ異常の解析には、以下の手法が有効です。
- パケット解析:WiresharkのIEC 60870-5-104ディスセクタを用い、APCI(制御情報)とASDU(ユーザーデータ)の整合性を検証。
- ロギングレベルの引き上げ:ビルドオプションで詳細トレースを有効化し、状態遷移と再送カウンタの動作を追跡。
- 環境分離:仮想ネットワークインターフェース(veth/loopback)を用い、ファイアウォールやNATの影響を排除した結合テストを実施。
- ユニットテストの活用:
tests/配下のテストハーネスを参照し、カスタムASDUのエンコード/デコードロジックを検証。