C Sharpens you up

http://qiita.com/yuba に移しつつあります

IEEE1888のコード例(その1:C#でコンポーネントアクセス)

IEEE1888を検索ワードにしたトラフィックが思った以上にあるのでコード例を追加していくことにします。

IEEE1888についての概説はこちら。

コンポーネントへのアクセスをC#で記述してみます。今後、レジストリへのアクセスと、それぞれJavaで記述した場合についても追加していきます。

1. WSDLの取り込み

コンポーネントWSDLとして、フタバ企画さんの公開されているhttp://www.futaba-kikaku.jp/services/jyukyu.php?wsdlを使わせてもらいましょう(内容的には、規格開発元の東大が作成しているWSDLと同じです)。

Visual Studioでプロジェクトを作ったら、【参照設定】を右クリック→【サービス参照の追加】→【詳細設定】→【Web参照の追加】と進みます*1
f:id:Sampo:20130716023521p:plain
WSDLのURLを入力して【→】をクリックし、Web参照名としてわかりやすく"IEEE1888Component"とでも設定しておきましょう(ここに設定した文字列が、自動生成されるクライアントプロキシコードの名前空間名になります)。

これでWSDLが取り込まれクライアントプロキシコードができました。

2. クライアントクラスを作る

クライアントプロキシができれば、あとはこれがメソッドを公開しているので何でも質問して答えてもらうだけ、と行きたいのですが…
IEEE1888の場合、問い合わせデータも返答データも少し複雑な構造体となっています。一回のアクセスに複数の質問を乗せることができるようになっているのと、回答が長くなった場合のページングを可能にしているためなのですが。

簡単に問い合わせができるようにクラスにまとめます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ComponentClient.IEEE1888Component;
using System.Web.Services.Protocols;

public class Client
{
    FIAPStorage proxy;

    public Client(String url)
    {
        proxy = new FIAPStorage { Url = url };
    }

    /// <summary>
    /// ポイントの最新値を取得します。
    /// 値が返らなかった場合はnullを返します。
    /// </summary>
    /// <exception cref="SoapException">SOAP通信上のエラーが発生した、もしくはサーバがエラーを返しました。</exception>
    public value FetchLatest(String pointId)
    {
        // 問い合わせ構造体を作ります
        transport t = new transport
        {
            header = new header
            {
                query = new query
                {
                    id = Guid.NewGuid().ToString(),
                    key = new[] { new key
                    {
                        id = pointId,
                        attrName = attrNameType.time,
                        selectSpecified = true,
                        select = selectType.maximum
                    }}
                }
            }
        };

        // 問い合わせを実行し、帰ってきたデータが規格通りでエラー応答でもないことを確認します
        proxy.query(ref t);
        if (t.header == null || t.header.error != null || t.header.OK == null || t.body == null)
        {
            throw new SoapException();
        }

        // 帰ってきたデータから時刻・値ペアをひとつだけ取りだして返します
        if (t.body.point == null) return null;
        return t.body.point
            .SelectMany(p => p.value)
            .FirstOrDefault();
    }
}

単なる最新値の問い合わせのみで、複数のポイントについてまとめて問い合わせるとか時刻範囲を指定するとか返答が長い場合にページングするとか考慮していないので、必要なところは書き足してください(凝るといくらでも凝れちゃいますよ)。

3. 呼び出してみる

ここまで用意できたらあとは簡単。
このクラスを使って、フタバ企画さんの用意してくれているサーバに「東京電力の最新の電力使用率」を問い合わせてみましょう。

Client client = new Client("http://www.futaba-kikaku.jp/services/jyukyu.php");
var v = client.FetchLatest("http://futaba-kikaku.jp/epco/tepco/balance");
Console.Out.WriteLine("{0} {1}", v.time, v.Value);

するとこの通り。

2013/07/16 2:30:00 48.5

時刻とともに"48.5"という値が取れました。

*1:Web参照? WCF使わないの? という突っ込みは勘弁してください。あれ嫌いで。