ECHONET Liteのコントローラの制御関連のプログラムをC#で書きたかったのですが、ネット検索してもあまりヒットしなかったので自作しました。
サンプルコードはGithubのechonetlitecsリポジトリに置いています。
サンプルの説明
「一覧の取得」ボタンを押すとLAN内のECHONET Liteノード一覧を取得します。ノードが取得できると、下のノード欄に1つ目に取得したノードコードがセットされます。次の欄にインスタンス番号がセットされます。
「オン」「オフ」ボタンは、スイッチのオンオフを行うボタンです。図の一覧に表示されている0290は一般照明のノードコードですので「オン」「オフ」ボタンを押すと、照明を点けたり消したりできます。
ノード一覧の取得
一覧の取得はUDPマルチキャストすることによって、ノードからの返信を取得します。
ポートは3610、アドレスは224.0.23.0 です。とりあえず、PortとMulticastAddressを設定しています。
private static readonly int Port = 3610;
private static readonly string MulticastAddress = "224.0.23.0";
private static readonly UInt16 Header = 0x1081;
private static readonly UInt16 TransactionID = 0x0000;
private static readonly byte ControllerGrpCd = 0x05;
private static readonly byte ControllerClsCd = 0xFF;
private static readonly byte ControllerInsCd = 0x01;
UDPマルチキャストするとノードの返信はUDPユニキャストで返ってきます。なので、UDPマルチキャストを送信した後にUDPユニキャストで受信します。プログラムは以下です(エラー処理は省いています)。
//ノード一覧を取得するためにマルチキャストします
using (UdpClient udpClient = new UdpClient(AddressFamily.InterNetwork))
{
IPAddress address = IPAddress.Parse(MulticastAddress);
IPEndPoint ipEndPoint = new IPEndPoint(address, Port);
udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, Port));
udpClient.JoinMulticastGroup(address, IPAddress.Parse(LocalAddress));
udpClient.MulticastLoopback = true;
byte[] frame = CreateSearchFrame();
udpClient.Send(frame, frame.Length, ipEndPoint);
}
//マルチキャストの返信がユニキャストで来るので取得します
byte[] recvBytes = null;
IPEndPoint remoteEP = null;
using (UdpClient udp = new UdpClient(Port))
{
udp.Client.ReceiveTimeout = 5000; //5secでタイムアウト
recvBytes = udp.Receive(ref remoteEP);
}
これで、recvBytes[]にノード一覧のフレームデータが入っています。ノードのIPアドレスは remoteEP.Address に入っています。
listにノードデータを追加しています。
List<EObject> list = new List<EObject>();
string ipaddress = remoteEP.Address.ToString();
//取得したノードをlistに入れます
for (int i = 0; i < nodeCnt; i++)
{
EObject eo = new EObject();
eo.Number = i + 1;
eo.IPAddress = ipaddress;
eo.GroupCd = recvBytes[15 + i * 3];
eo.ClassCd = recvBytes[15 + i * 3 + 1];
eo.InstanceCd = recvBytes[15 + i * 3 + 2];
list.Add(eo);
}
ECHONET Liteとは直接関係ないですが、マルチキャストの際に自身のローカルIPアドレスを付加しておかないとUDPユニキャストが返って来ないようです。ローカルIPアドレスのプロパティを追加しました。フォームのソースコードの方に自身のローカルIPアドレスを取得するメソッドも入れています。
スイッチのオンオフ
ECHONET Liteのコントロールサンプルとして、スイッチのオンオフサンプルコードを付けています。スイッチのオンオフ用フレームをUDPユニキャストで送信するだけです。
public byte[] SwitchSet(EObject eo, bool sw)
{
byte[] sendFrame = CreateSwitchFrame(eo, sw); //スイッチ用のフレームを取得します
byte[] recvBytes = null;
IPEndPoint remoteEP = null;
using (UdpClient udp = new UdpClient(Port))
{
udp.Client.ReceiveTimeout = 5000; //5secでタイムアウト
udp.Send(sendFrame, sendFrame.Length, eo.IPAddress, Port);
recvBytes = udp.Receive(ref remoteEP);
}
return recvBytes;
}
SwitchSet()は、スイッチ用のフレーム生成するメソッドです。プロパティ番号0x80がスイッチのオンオフプロパティです。
private byte[] CreateSwitchFrame(EObject eo, bool sw)
{
byte[] frame = new byte[15];
frame[0] = (byte)(Header >> 8); //EHD1 ECHONETLiteヘッダ 1Byte 0x10固定
frame[1] = (byte)(Header & 0xFF); //EHD2 ECHONETLiteヘッダ 1Byte 0x81固定
frame[2] = (byte)(TransactionID >> 8); //TID トランザクションID 2Byte 0~65535
frame[3] = (byte)(TransactionID & 0xFF);//TID トランザクションID 2Byte 0~65535
frame[4] = ControllerGrpCd; //SEOJ 送信元オブジェクト コントローラークラスグループコード
frame[5] = ControllerClsCd; //SEOJ 送信元オブジェクト コントローラークラスコード
frame[6] = ControllerInsCd; //SEOJ 送信元オブジェクト インスタンスコード
frame[7] = eo.GroupCd; //DEOJ 送信先オブジェクト グループコード
frame[8] = eo.ClassCd; //DEOJ 送信先オブジェクト クラスコード
frame[9] = eo.InstanceCd; //DEOJ 送信先オブジェクト インスタンスコード
frame[10] = (byte)enmESV.SETC; //ESV サービスコード SETC
frame[11] = (byte)0x01; //OPC プロパティ数
frame[12] = (byte)0x80; //EPC プロパティ番号 スイッチのオンオフ
frame[13] = (byte)0x01; //PDC EDTのバイト数
frame[14] = sw ? (byte)0x30 : (byte)0x31; //0x30がスイッチオン 0x31がスイッチオフ
return frame;
}
簡単ですが、こんな感じでC#から制御できるようになりました。