コンテンツにスキップ

UNS(Unified Namespace)コネクタ

**UNS(Unified Namespace)**コネクタは、コネクタ設定と受信ペイロードからISA-95に準拠したトピック階層を構築し、注入された_uns_topicキーを持つJSONペイロード、またはメトリクス配列内でデータをラップするSparkplugBスタイルのエンベロープを発行するプロセッサです。Walker ReynoldsとISA-95標準によって普及したUnified Namespaceにプラントデータを整理するための正準的な構成要素です。

コネクタタイプ:

  • UNS - ISA-95トピックでペイロードを装飾し、出力をJSONまたはSparkplugBとして再構築するステートレスプロセッサ
  • ✅ ISA-95階層:エンタープライズ / サイト / エリア / ライン / セル
  • ✅ オプションのペイロード駆動の動的トピックレベル(マッピング)
  • ✅ 2つの出力形式:json(パススルー + _uns_topic)とsparkplugb(メトリクス配列を持つエンベロープ)
  • ✅ 空の階層レベルを優雅にスキップ
  • ✅ SparkplugB出力上のメッセージごとのタイムスタンプ(Unixミリ秒)
{
"type": "UNS",
"config": {
"enterprise": "Acme",
"site": "Milan",
"area": "Assembly",
"line": "Line1",
"cell": "Station3",
"outputFormat": "json"
}
}

ペイロードからの動的トピックレベル

Section titled “ペイロードからの動的トピックレベル”
{
"type": "UNS",
"config": {
"enterprise": "Acme",
"site": "Milan",
"area": "Assembly",
"mappings": [
{ "inputKey": "machine_id", "topicLevel": "machine" },
{ "inputKey": "shift_id", "topicLevel": "shift" }
],
"outputFormat": "json"
}
}
{
"type": "UNS",
"config": {
"enterprise": "Acme",
"site": "Milan",
"area": "Packaging",
"line": "Line2",
"outputFormat": "sparkplugb"
}
}

必須。トップレベルのISA-95エンタープライズ(会社/部門名)。

{ "enterprise": "Acme" }

必須。物理的なサイト(プラント、工場、建物)。

{ "site": "Milan" }

オプション。サイト内の機能エリア。

{ "area": "Assembly" }

オプション。エリア内の生産ライン。

{ "line": "Line1" }

オプション。ライン内の特定のセルまたはワークステーション。

{ "cell": "Station3" }

オプション。ペイロードからトピックレベルへのマッピングの配列。各マッピングについて、コネクタはdata[inputKey]を検索し、<topicLevel>/<value>をトピックに追加します。

{
"mappings": [
{ "inputKey": "machine_id", "topicLevel": "machine" },
{ "inputKey": "shift_id", "topicLevel": "shift" }
]
}

動作:

  • 各エントリにはinputKeytopicLevelの両方が必須
  • 欠落した入力キーはエラーチャネル経由で報告され、トピックレベルは省略されます
  • 非文字列の入力値はfmt.Sprintf("%v", ...)で強制変換されます

必須。以下のいずれかである必要があります:

  • json - _uns_topicが注入された元のペイロードのパススルー
  • sparkplugb - メトリクスが{ name, value }ペアのリストである{ topic, timestamp, metrics }エンベロープ
{ "outputFormat": "sparkplugb" }

トピックレベルは/で結合されます。空のオプションレベル(エリア、ライン、セル)はスキップされます。マッピングは宣言された順序で表示されます。

例:

設定:

{
"enterprise": "Acme",
"site": "Milan",
"area": "Assembly",
"line": "Line1",
"mappings": [
{ "inputKey": "machine_id", "topicLevel": "machine" }
]
}

受信ペイロード:

{ "machine_id": "M-007", "temperature": 24.5 }

結果のトピック:

Acme/Milan/Assembly/Line1/machine/M-007

入力:

{
"machine_id": "M-007",
"temperature": 24.5,
"pressure": 5.2
}

設定:

{
"enterprise": "Acme",
"site": "Milan",
"area": "Assembly",
"line": "Line1",
"mappings": [
{ "inputKey": "machine_id", "topicLevel": "machine" }
],
"outputFormat": "json"
}

出力:

{
"machine_id": "M-007",
"temperature": 24.5,
"pressure": 5.2,
"_uns_topic": "Acme/Milan/Assembly/Line1/machine/M-007"
}

outputFormat: sparkplugbの同じ入力とベース設定:

{
"topic": "Acme/Milan/Assembly/Line1/machine/M-007",
"timestamp": 1747740875123,
"metrics": [
{ "name": "machine_id", "value": "M-007" },
{ "name": "temperature", "value": 24.5 },
{ "name": "pressure", "value": 5.2 }
]
}

timestampは処理時のUnixミリ秒です。metricsエントリの順序は保証されません(Goマップ反復は順不同)。

DataPayload → UNS → DataPayload + _uns_topic(json) OR { topic, timestamp, metrics }(sparkplugb)

1. ISA-95トピックでPLCデータをMQTTにブリッジ

Section titled “1. ISA-95トピックでPLCデータをMQTTにブリッジ”

生のPLCペイロードをUNS準拠のMQTTトピックに再構築:

{
"type": "UNS",
"config": {
"enterprise": "Acme",
"site": "Detroit",
"area": "Stamping",
"line": "PressLine1",
"outputFormat": "json"
}
}

ダウンストリームのMqttV5Writerは、_uns_topicをMQTTトピックにマップするReshapeステップを介して_uns_topicをパブリッシュトピックとして使用します。

2. IgnitionまたはHiveMQのためのSparkplugBパブリッシュ

Section titled “2. IgnitionまたはHiveMQのためのSparkplugBパブリッシュ”

多くのSCADAプラットフォーム(Ignition、HiveMQなど)はSparkplugBエンベロープを期待します。一致するようにsparkplugb出力を使用します:

{
"type": "UNS",
"config": {
"enterprise": "Acme",
"site": "Milan",
"area": "Bottling",
"line": "Filler1",
"outputFormat": "sparkplugb"
}
}

3. 顧客によるマルチテナントトピックルーティング

Section titled “3. 顧客によるマルチテナントトピックルーティング”

動的マッピングを使用してトピックに顧客識別子を埋め込む:

{
"type": "UNS",
"config": {
"enterprise": "ConnectCo",
"site": "Cloud",
"mappings": [
{ "inputKey": "tenant_id", "topicLevel": "tenant" },
{ "inputKey": "site_id", "topicLevel": "customer-site" },
{ "inputKey": "device_id", "topicLevel": "device" }
],
"outputFormat": "json"
}
}

{tenant_id: "T-1", site_id: "S-99", device_id: "D-42"}の結果のトピック:

ConnectCo/Cloud/tenant/T-1/customer-site/S-99/device/D-42

問題: ダウンストリームコンシューマが_uns_topicキーを見ない

解決策:

  1. outputFormat: jsonが設定されていることを確認(SparkplugBエンベロープはペイロード全体を置き換えます。_uns_topicの代わりにトップレベルにtopicがあります)
  2. UNSコネクタが実際にパイプラインにあることを確認 — 中間ペイロードをダンプするためにLogライターを使用

input key %q not found in payloadエラー

Section titled “input key %q not found in payloadエラー”

問題: 設定されたマッピングが、ペイロードに存在しないキーを参照している

解決策:

  1. 入力キーが上流のペイロードと正確に一致することを確認(大文字小文字を区別)
  2. 必要なキーが存在することを保証するために上流にReshapeまたはTransformを使用
  3. キーが時々欠落する場合、代わりに静的area/line/cellの一部にすることを検討

問題: 出力エンベロープが{ topic, timestamp, metrics: [] }

解決策:

  1. メトリクス配列は入力ペイロードのキーから構築されます。空の入力 → 空のメトリクス
  2. 上流コネクタが非空のペイロードを配信していることを確認

トピックに予期しないスラッシュまたは空のセグメント

Section titled “トピックに予期しないスラッシュまたは空のセグメント”

問題: トピックに//または末尾のスラッシュが含まれている

解決策:

  1. enterprisesiteなどにスラッシュを含めないでください — コネクタがそれらを挿入します。埋め込まれたスラッシュは不正な形式のパスを生成します
  2. オプションレベルの空文字列を避けてください — ""を渡すのではなく、フィールドを未設定のままにします

SparkplugBメトリクスのソートに関する懸念

Section titled “SparkplugBメトリクスのソートに関する懸念”

問題: メトリクスの順序が実行間で一貫していない

解決策:

  1. Goマップ反復は意図的に順不同です。ダウンストリームコンシューマが順序を気にする場合、このコネクタに到達する前にメトリクスを明示的なリストに変換するReshapeを介して上流でソートします
  2. または、コンシューマに受信時にnameでソートさせます

1. UNSトピックを契約として扱う

Section titled “1. UNSトピックを契約として扱う”

トピック階層はダッシュボード、ヒストリアン、その他のMeddleパイプラインによって消費されます。一度パブリッシュされると、安定したインターフェイスとして扱ってください — 事後にarealineをリネームすることはダウンストリームコンシューマを壊します。

2. 安定した階層には静的レベルを使用

Section titled “2. 安定した階層には静的レベルを使用”

階層がペイロードに依存しない場合は、マッピングよりも静的enterprise/site/area/line/cellを優先します。マッピングは強力ですが、ペイロード形状への依存を追加します。

3. グリーンフィールドにはJSON、SCADAブリッジングにはSparkplugBを優先

Section titled “3. グリーンフィールドにはJSON、SCADAブリッジングにはSparkplugBを優先”

jsonはよりシンプルで、任意のダウンストリームコンシューマで動作します。既存のSparkplugBエコシステム(Ignition、HiveMQ Edgeなど)と相互運用する必要がある場合のみsparkplugbを使用します。

4. MQTTの前にReshapeと組み合わせる

Section titled “4. MQTTの前にReshapeと組み合わせる”

ほとんどのMQTTライターは、トピックを明示的に設定する必要があります。UNSコネクタの後、_uns_topicをパブリッシュトピックフィールドに昇格させるReshapeステップを使用します:

... → UNS → Reshape(_uns_topic → topicに移動) → MqttV5Writer

5. 組織レベルでUNSをドキュメント化

Section titled “5. 組織レベルでUNSをドキュメント化”

組織全体のためにISA-95スキーマを一度選び、すべてのサイトとラインにわたって一貫して適用します。Meddleデプロイメント間でのスキーマドリフトは、互換性のないトピックツリーを作成します。

PLC → UNS → MQTT(クラウドブローカー)

Section titled “PLC → UNS → MQTT(クラウドブローカー)”
ModbusReader → Reshape → UNS → Reshape → MqttV5Writer
  1. ModbusReader: PLCから生のレジスタデータを取得
  2. Reshape: 生のアドレスを人間が読みやすいキーにリネーム
  3. UNS: _uns_topicで装飾
  4. Reshape: _uns_topicをMQTT topicフィールドに昇格
  5. MqttV5Writer: UNSの下で整理されたクラウドブローカーにパブリッシュ
OpcuaReader → Predictive → UNS(sparkplugb) → MqttV5Writer
  1. OpcuaReader: 複数のOPC UAエンドポイントから集約
  2. Predictive: トレンド/RUL/ヘルススコアを追加
  3. UNS: 拡充されたペイロードをSparkplugBエンベロープでラップ
  4. MqttV5Writer: SparkplugB対応ブローカー(例:HiveMQ Edge → Ignition)にパブリッシュ
[サイトAパイプライン] ─┐
[サイトBパイプライン] ─┼─→ UNS → InfluxDb2Writer
[サイトCパイプライン] ─┘

各サイトパイプラインは独自のUNS設定でデータをラベル付けし、ダウンストリームコンシューマがトピックだけで曖昧さを解消できるようにします。

  • MQTT v5 - UNS装飾ペイロードをブローカーにパブリッシュ
  • MQTT v3 - レガシーMQTTパブリッシング
  • Reshape - _uns_topicをライターのトピックフィールドに昇格
  • Filter - _uns_topicパターンでフィルタリング
  • Router - UNS階層に基づくブランチルーティング