私は少し前に小規模なプロジェクトに取り組み、集中制御のために KNX 照明システムを .NET バックエンドに接続する必要がありました。当初は、通常の IoT と同じように、HTTP リクエストを送信するだけで完了するものだと考えていました。しかし、KNX のロジックは消費者向けのスマート ホームのロジックとはまったく異なることがわかりました。数日間苦労した後、私は原則と規範を理解しました。後でトラブルに巻き込まれようとしている人のために時間を節約するために、それらを書き留めました。
この記事は 2 つの部分に分かれています。前半では KNX ライティングの仕組みについて説明し、後半では .NET 8 で実行可能な例を示します。これが完全であるとは保証しませんが、私自身が実際に実行したものであることは保証します。
1. KNX 照明はどのように制御されますか?
まず私の最初の誤解を訂正させてください: KNX スイッチ パネルとランプの間直接配線接続はありません。パネルは KNX バスにのみ接続され、ライトはアクチュエーターによって制御される強電流回路に接続されます。この 2 つは「グループ アドレス」によって論理的に結び付けられます。
物理層: 1 つのバス、2 セットのループ
最も一般的に使用される KNX は、専用ツイスト ペア (KNX TP) です。バスは信号と電力 (通常は DC 29 V) を同時に送信します。強電流側には別の 220V 回路があり、アクチュエーター内のリレーによってオン/オフが切り替えられます。したがって、配線の際、KNX バスは弱電流ブリッジを介して配線され、強電流から完全に分離され、耐干渉能力は想像以上に優れています。
グループアドレス:ブロードキャスト+フィルター
これが KNX の中心的な概念です。これを理解すれば、あとはスムーズです。
各デバイスには 1 つあります物理アドレスのようなフォーマット 1.1.2ID カードに相当し、デバッグや診断に使用され、日常業務における機能連携には関与しません。 「誰が誰をコントロールするのか」を本当に決定するものは何でしょうか?グループアドレス(グループアドレス、GA)、通常は次のように書かれます。 1/1/1 このスラッシュ形式は本質的には関数ラベルです。
作業方法は、放送: パネルをクリックすると、パネルは特定のグループ アドレスと値を含むメッセージをバスに送信します。バス上のすべてのデバイスがこのメッセージを受信できますが、グループ アドレスが一致するエグゼキュータのみが応答し、他のデバイスは無視されます。
これは、KNX システムの中央制御がダウンしているにもかかわらず、基礎となるスイッチがまだ利用可能な理由を説明しています。機能ロジックはグループ アドレスを通じてデバイス間で直接バインドされており、コマンドの発行に中央コントローラーに依存しません。
センサー、アクチュエーター、ETS
KNX 照明システムには 3 種類の役割があります。
- センサー: パネル、人体センサー、照度センサー、制御メッセージの開始を担当します。
- アクチュエータ: スイッチアクチュエータ、調光アクチュエータ、強電流回路を直接制御し、一致するグループアドレスを受信すると動作します。
- ETS: KNX 公式エンジニアリング構成ソフトウェア。エンジニアはこれを使用して、センサーとアクチュエーターを同じグループ アドレスにバインドします。この構成は 1 回限りであり、システムは構成後に独立して実行できます。
メッセージタイプ: スイッチ、調光、シーン
異なる関数には異なるデータ型が使用されます。
- スイッチ1ビットメッセージ、値を使用
1はい、0はい、DPT 1.001 に対応しています。 - 相対調光4ビットメッセージ、値を使用
1~7薄暗い、9~15明るくする、0停止。 - シーン1バイトのメッセージでその値がシーン番号に対応し、複数のアクチュエーターを同じシーングループアドレスにバインドしてワンクリックで雰囲気を切り替えることができます。
ボタンを押すだけでプロセスが完了
ライトのオンとオフの切り替えを例にとると、データ フローは次のとおりです。
- パネルを押してください。
- パネルはバスにメッセージをブロードキャストします: グループ アドレス
1/1/1、価値1; - バス上のすべてのデバイスは受信し、リッスンするだけです
1/1/1スイッチアクチュエータの主張: - アクチュエータがリレーを閉じ、ライトが点灯します。
- 次に、エグゼキュータは別のグループ アドレスを渡します (例:
1/1/2)ブロードキャストステータスフィードバックとパネルのインジケーターが同時に点灯します。
フローチャート LR サブグラフ CFG[“ETS 配置阶段”]
ETS[“ETS 软件
绑定组地址 GA 1/1/1″]
サブグラフの終了 BUS[“KNX 总线侧(控制信号 + 供电)”]
PWR[“KNX 电源 + 扼流圈
约 29V DC”]
BUSLINE((“KNX バス”)) パネル[“开关面板 / 传感器
物理地址 1.1.2″]
活動[“开关执行器
物理地址 1.1.3
监听 GA 1/1/1″]
最後のサブグラフ POWER[“强电侧”]
交流[“220V 交流强电”]
ランプ[“灯具”]
ETS-を終了します。 「構成バインディング」 .-> パネル ETS -。 “構成バインディング” .-> ACT PWR –> BUSLINE PANEL –>|”① ブロードキャストメッセージ
GA 1/1/1 = 1 (on) “| BUSLINE BUSLINE –>|”② すべてのデバイスが受信、
アクチュエータ応答一致のみ GA”| ACT AC –> ACT ACT –>|”③ リレー閉”| LAMP ACT –>|”④ ステータスフィードバック
GA 1/1/2 = 1″| BUSLINE BUSLINE –>|”⑤ フィードバックメッセージ”| PANEL
2. .NET 8 での KNX 照明制御の例
コードのこの部分は私が実際に実行したものです。環境は .NET 8 コンソール プログラムであり、ライブラリは KNX.net。ルーティングとトンネリングという 2 つの KNXnet/IP 接続方法をサポートします。 APIは複雑ではなく、十分です。
プロジェクトの構築とパッケージ化
dotnet new console -n KnxLightingDemo -f net8.0
cd KnxLightingDemo
dotnet add package KNX.net
NuGet リソウ KNX.net著者はlifeemotionsの人です。
完全なコード
using KnxLib;
// 这两个组地址要按你 ETS 项目里的实际配置改
const string SwitchGroupAddress = "1/1/1"; // 开关控制
const string StatusGroupAddress = "1/1/2"; // 状态反馈
// Routing 模式,走 KNXnet/IP 多播
// 如果网关不支持 Routing,换成 KnxConnectionTunneling,下面会讲
var connection = new KnxConnectionRouting();
connection.KnxEventDelegate += OnKnxEvent;
Console.WriteLine("正在连接 KNX 总线...");
connection.Connect();
Console.WriteLine("连接成功。输入 on / off 控制灯具,输入 status 读取状态,输入 q 退出。");
// 启动时主动读一次当前状态
connection.RequestStatus(StatusGroupAddress);
while (true)
{
Console.Write("> ");
var input = Console.ReadLine()?.Trim().ToLower();
if (input == "q") break;
switch (input)
}
connection.Disconnect();
// 事件处理:总线上收到的报文都会进这里
static void OnKnxEvent(string address, string state)
{
if (address != "1/1/2") return;
var isOn = ParseSwitchState(state);
Console.WriteLine($"\n[状态反馈] {address} = {(isOn ? "ON" : "OFF")} (原始值: {state})");
}
// 这里是个坑,下面单独说
static bool ParseSwitchState(string raw)
{
if (string.IsNullOrWhiteSpace(raw)) return false;
if (raw == "1" || raw.Equals("true", StringComparison.OrdinalIgnoreCase)
|| raw.Equals("on", StringComparison.OrdinalIgnoreCase))
return true;
return false;
}
実際のデバッグ中にいくつかの問題が発生しました
1. ルーティングまたはトンネリングはゲートウェイに依存します。
例では、 KnxConnectionRoutingマルチキャスト方式。ゲートウェイがルーティングをサポートしていない場合、またはネットワーク環境がマルチキャストを許可していない場合は、トンネリングを変更する必要があります。
var connection = new KnxConnectionTunneling(
remoteIP: "192.168.1.100", // KNX IP 接口地址
remotePort: 3671,
localIP: "192.168.1.50", // 本机 IP
localPort: 3671 // 本机监听端口
);
KNXnet/IP 標準ポートは次のとおりです。 3671。トンネリングモードではネイティブ localPort ゲートウェイは到達可能である必要があり、Windows ファイアウォールは受信トラフィックを許可することを忘れません。そうしないと、接続されていてもイベントが受信されません。
2.イベントの場合 state フォーマットは必ずしも希望どおりであるとは限りません。
KNX.net KnxEventDelegate 与えられた state は文字列です。バージョンまたは DPT が異なると、形式が異なる場合があります。そうかもしれません "1"、"True" あるいは他の何か。最初からそのまま使ってた bool.Parse時々爆発します。コードには次のように書かれています ParseSwitchState 互換性があること。最初にオリジナルを実行することをお勧めします state 急いで分析しないで、入力して見てください。
3. RequestStatus プッシュを待つのではなく、アクティブな読み取りです。
起動と入力 status タイムチューン RequestStatusGroupValueRead をバスに送信し、エグゼキュータはそれを受信した後に GroupValueResponse を返します。これを調整しないと、ステータスが変化したときにメッセージを受動的に受信することしかできません。実際のプロジェクトでは、初期化フェーズ中に関係するすべての状態を読み取ることをお勧めします。そうしないと、インターフェイスの初期状態が空になります。
4. グループ アドレスと DPT は一致する必要があります。
ETS で確認します。スイッチ制御グループ アドレスは DPT 1.001 を使用し、ステータス フィードバックは通常 1.001 (または 1.002) です。フィードバック DPT がこれではない場合、解析ロジックを変更する必要があります。 KNX.net 自体は FromDataPoint このようなメソッドですが、イベントで取得される文字列の形式は安定していません。最終的には明示的な文字列判定を使用しました。これは単純で粗雑ではありますが、トラブルを引き起こしにくいものです。
5. コンソール プログラムでは UI スレッドの問題はありませんが、WinForms/WPF に変更する場合は注意が必要です。
KNX.net のイベント コールバックは UI スレッド上にありません。インターフェース上のステータスを更新したい場合は、次のことを行う必要があります。 Control.Invoke または Dispatcher.Invoke 元に戻すと、クロススレッド例外が発生します。この落とし穴は KNX とは関係ありませんが、余談です。
やっと
KNX に初めて触れると、グループ アドレス、物理アドレス、ETS などの概念がたくさんあるように感じるかもしれませんが、「ブロードキャスト + グループ アドレス フィルタリング」の核心を理解したら、あとは DPT を確認してネットワークを調整するだけです。これは、消費者向けのワイヤレス ソリューションと同じ考え方ではありません。KNX は、配線コストとデバッグしきい値を犠牲にして、決定性、長寿命、およびベンダー間の相互運用性を追求します。