背景
セキュリティポリシーの要件により、プログラムからPLCへマスタとしてアクセスすることができません。
解決策:PLCをマスタとして動作させ、プログラムはスレーブとして受動的にデータを取得し、その値の変化に基づいて処理を実行します。
解決策
- NModbus4コンポーネントを使用してスレーブを実装
- 単一アプリケーション内で複数のポートを開き、異なるPLC信号を区別
スレーブリスナー実装コード
// IPアドレスとポート番号の設定
var slaveEndpoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), Convert.ToInt32(slavePort));
var networkListener = new TcpListener(slaveEndpoint);
// スレーブインスタンスの作成
var modbusSlaveInstance = ModbusTcpSlave.CreateTcp(slaveUnitId, networkListener);
// データストアの初期化(保持レジスタ、入力レジスタ、コイル、ディジタル入力用)
modbusSlaveInstance.DataStore = DataStoreFactory.CreateDefaultDataStore(holdingRegisterCount, inputRegisterCount, coilCount, discreteInputCount);
// データ書き込みイベントハンドラの登録
modbusSlaveInstance.DataStore.DataStoreWrittenTo += HandleDataModificationEvent;
データ変更イベント処理
/// <summary>
/// Modbusデータ書き込みイベントを処理するメソッド
/// </summary>
/// <param name="sender">イベント発生元</param>
/// <param name="eventArgs">イベントデータ</param>
private void HandleDataModificationEvent(object sender, DataStoreEventArgs eventArgs)
{
// Modbusデータタイプに基づいて処理を分岐
switch (eventArgs.ModbusDataType)
{
case ModbusDataType.HoldingRegister:
{
ProcessHoldingRegisterUpdate();
break;
}
case ModbusDataType.InputRegister:
{
// 入力レジスタ更新処理
// ProcessInputRegisterUpdate();
break;
}
case ModbusDataType.Coil:
{
// コイル更新処理
break;
}
case ModbusDataType.Input:
{
// ディジタル入力更新処理
// ProcessDiscreteInputUpdate();
break;
}
default:
break;
}
}
重要な注意事項
- スレーブIDはシステム内で一意である必要があります
- リスナーを開始するIPアドレスは0.0.0.0を指定してください
- データの読み書き時には、スレーブアドレスを正しく区別してください