C# Programming

Image

簡単なモバイルアプリケーション開発5
XML Web Service で Amedas の観測所IDを取得する。

開発環境: Visual Studio 2005

1.目次

1.目次
2.目的
3.参考書
4.作り方
5.まとめ

2.目的

W-Zero3では、位置データ(緯度、経度、郵便番号)を基地局から取得できます。この位置データを利用することにして、Google Map のような地図や、天気図を表示したり、郵便番号から住所を取り出すなど、いろいろな応用ができます。

ここでは、位置データ(緯度、経度、郵便番号)から、Amedas の気温を取得するアプリケーションを作ります。そのための準備段階として、緯度、経度から、最近傍のアメダスの観測所のIDを返す XML Web Serviceを作ります。

http://uchukamen.com/amedas.asmx

3.参考書

  1. C#研究室.Live Space / W-ZERO3
  2. デジタル台風:アメダス統計

4.作り方

 

4.1 基本動作

緯度、経度がわかれば、そこの気温を知ろうと思えば、いちばん近いアメダスの観測所のデータを取得すればよいことになります。これをW-Zero3 のアプリケーションで組めばよいわけです。ここで問題になってくるのが、アメダス観測所のデータをどのように持たせ、処理するかです。アメダスの観測所は2000か所以上あります。単純に1か所に、ID...4バイト、地名...100バイト、緯度...8バイト、経度...8バイトで、約128バイトとして、256KB程度になります。

方法 メリット デメリット
WZero3 側でEXCEL / SQL CEでデータをもつ
  • 観測所データを取得するために通信の必要がない。(しかし、現在の天気情報を取得するには、通信が必要。)
  • データを更新する場合、クライアントでデータを更新しなければならないので、数が多いと常に最新のデータにするための管理が大変。
  • データ処理のためにW-Zero3側に処理負荷がかかる。
XML Web Service でサーバー側でデータをもつ
  • クライアント側でデータを持つ必要がない
  • データの更新はサーバ側だけ

 

  • 通信コストがかかる

ということで、ここではアメダスの観測所のデータをXML Web Service で取得することにします。

4.2 Amedas観測所データの作成

まずは、ローカルネットにSQLサーバーを用意して、そこでAmedas観測所データの作成を行います。

全国のアメダス観測所は、2000以上あります。このデータはたとえば東京のように、降水量、風向、風速、気温、日照時間を知ることができます。ところが、このデジタル台風の横浜のデータを見ると、場所によっては、データが測定されていない場所があります。そこで、現在の緯度、経度から、温度を知るためには、観測所ID、観測所の名前、緯度、経度、温度を計測しているかどうか、最低5項目が必要になります。

そこで、SQLサーバーに次のようなテーブルを作成します。

キー 列名 データ型 長さ
Image ID int 4
  地名 nvarchar 50
  緯度 float 8
  経度 float 8
  気温フラグ tinyint 1

あとは、次のように観測所のデータを入力します。気温計測フラグは1が気温を計測している、0は計測していないという意味です。下の例ですと、船泊は気温を計測していない観測所ということになります。

ID 地名 緯度 経度 気温フラグ
11001 宗谷岬 45.52 141.935 1
11011 船泊 45.437 141.035 0
11012 幌泊 45.455 141.038 1
11016 稚内 45.415 141.678 1

4.3 緯度、経度から最近傍の観測所IDを返すストアドを作る

ローカルのSQLサーバーに上記 Amedas テーブルができたところで、緯度、経度から最近傍の観測所IDを返すストアドを作ります。緯度、経度から正確な距離を出すためには、地球の形状を考慮した三角関数での処理が必要ですが、ここでは距離が十分に近く、直線で近似できることを前提に 緯度の差の2乗+経度の差の2乗 が最小になる観測所、かつ気温フラグが1の観測所のIDを返します。

CREATE PROCEDURE GetNearestAmedasCode
@緯度 float,
@経度 float AS

SELECT TOP 1 MIN (POWER((@緯度 - 緯度), 2) + POWER((@経度 - 経度),2 ) ) 
  AS DIST, ID, 緯度, 経度, 地名 
FROM amedas
WHERE 気温フラグ=1 
GROUP BY ID, 緯度, 経度, 地名 
ORDER BY DIST

では、次のように、宗谷岬と船泊の座標で実行して確認します。

EXEC GetNearestAmedasCode 45.52, 141.935
EXEC GetNearestAmedasCode 45.5437, 141.035

結果は次のようになります。

DIST ID 緯度 経度 地名
0 11001 45.52 141.935 宗谷岬
1 処理行数
DIST ID 緯度 経度 地名
7.8766900000006E-03 11012 45.455 141.038 幌泊
1 処理行数

2つ目のクエリは、船泊ではなく、幌泊が帰ってきます。

4.4 緯度、経度から最近傍の観測所IDを返す XML Web Service を作る

  1. Visual Studioの新規サービスで、[新しいプロジェクト]→[Web]→[ASP.NET Web サービスアプリケーション]で、WebServiceAmedas プロジェクトを作ります。

    Image

     
  2. Web.config の設定
    ローカルの SQL サーバーに接続に必要な接続文字列を Web.config に設定します。
    ...
    <
    configuration>
    <
    appSettings/>
    <
    connectionStrings>
    <
    add name="uchukamen_comConnectionString1" connectionString=".... 適切な接続文字列をセット..." />
    ...
    </
    connectionStrings>
    ....

     

  3. Amedas.asmx の実装

    緯度、経度より、最も至近のAmedasの観測所IDを取得する次のメソッド

        public int GetNearestCode(float latitude, float longitude)

    を実装します。実装自体は、典型的なADO.NET接続型なので説明は不要と思います。
     
    using System;
    using System.Data;
    using System.Web;
    using System.Collections;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.ComponentModel;
    using System.Configuration;
    using System.Data.SqlClient;
    
    namespace WebServiceAmedas
    {
        /// 
        /// WebServiceAmedas の概要の説明です
        /// 
        [WebService(Namespace = "http://uchukamen.com/")]
        [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
        [ToolboxItem(false)]
        public class Amedas : System.Web.Services.WebService
        {
    
            /// 
            /// 緯度、経度より、最も至近のAmedasの観測所IDを取得する。
            /// 
            /// 緯度
            /// 経度
            /// 
            [WebMethod]
            public int GetNearestCode(float latitude, float longitude)
            {
                string connectionString 
                   = ConfigurationManager.ConnectionStrings
                   ["uchukamen_comConnectionString1"].ConnectionString;
    
                using (SqlConnection sqlConn 
             = new SqlConnection(connectionString))
                using (SqlCommand sqlCmdStored 
             = new SqlCommand("GetNearestAmedasCode"))
                {
                    sqlCmdStored.CommandType 
                       = CommandType.StoredProcedure;
    
                    SqlParameter sqlLatitude 
              = new SqlParameter("@緯度", SqlDbType.Float);
                    sqlLatitude.Value = latitude;
                    sqlCmdStored.Parameters.Add(sqlLatitude);
    
                    SqlParameter sqlLongitude 
              = new SqlParameter("@経度", SqlDbType.Float);
                    sqlLongitude.Value = longitude;
                    sqlCmdStored.Parameters.Add(sqlLongitude);
    
                    sqlConn.Open();
                    sqlCmdStored.Connection = sqlConn;
    
                    using (SqlDataReader dr 
                       = sqlCmdStored.ExecuteReader())
                    {
                        if (dr.Read())
                        {
                            return (int)dr["ID"];
                        }
                    }
                }
                return 0;
            }
        }
    }
    

     

  4. では、実装ができたところで実行してみます。すると、次のようにIEが立ち上がり、サービスの説明画面が表示されます。
    Image

    Amedasのリンクをクリックすると、次のような IE が開き、テストができます。値のところにたとえば、好きな場所の緯度、経度情報を入れて起動ボタンを押して、動作を確認してください。

    Image

    期待した結果が帰ってくればOKです。

4.5 ホスティングサーバーへの移行

ここまでは、ローカルネットワーク内の作業なので、インターネットにこのサービスを配置する必要があります。以下は、ホスティングサーバーをお持ちということを前提の作業です。

  1. SQLサーバーのテーブルをデーターセンター側のSQL サーバーにコピーします。
  2. Web.config で、接続文字列をデーターセンター側のSQL サーバーにあわせて書き換えます。
  3. XML Web Service の発行
    [メインメニュー]→[ビルド]→[WebServiceAmedas の発行]で、ターゲットの場所を指定して、発行します。
    Image

    うまくいけば、次のようなメッセージが出力ウィンドウに表示されます。

    ------ ビルド開始: プロジェクト: WebServiceAmedas, 構成: Debug Any CPU ------

    中略

    コンパイルの完了-- エラー0、警告0

    WebServiceAmedas -> C:\Users\uchukamen\Documents\Visual Studio 2005\Projects\WebServiceAmedas\WebServiceAmedas\bin\WebServiceAmedas.dll

    ------ 発行の開始: プロジェクト: WebServiceAmedas, 構成: Debug Any CPU ------

    http://uchukamen.com/ に接続しています...

    フォルダ/ を発行しています...

    フォルダbin を発行しています...

    ========== ビルド: 1 正常終了または最新の状態、失敗、スキップ==========

    ========== 発行: 1 正常終了、失敗、スキップ==========

4.6 テスト用アプリケーションの作成

簡単に動作を確認するアプリケーションを作っておくと便利かもしれません。
Image

実装は極めて簡単で、次の通りです。

  1. 新しいプロジェクトで Windows.Forms を作成する。
  2. Web参照の追加で、http://uchukamen.com/amedas.asmx を追加する。
  3. 上のようなコントロールを追加。
  4. ボタンを押したら、次のように XML Web Service を呼び出して、結果を表示する。
    private void button1_Click(object sender, EventArgs e)
    {
       
    float lat = float.Parse(textBoxLatitude.Text);
       
    float lon = float.Parse(textBoxLongitude.Text);
        com.uchukamen.
    Amedas amedas = new com.uchukamen.Amedas();
        textBoxCode.Text = amedas.GetNearestCode(lat, lon).ToString();
    }

クリックワンスで実行できるようにしておきました。

AmedasWebServiceTest http://uchukamen.com/AmedasWebServiceTest/publish.htm

5.まとめ

以上で、緯度、経度からアメダスの温度を取得することができるようになりました。次回は、ようやく W-Zero3からこのサービスを利用して、現在の位置、時間の気温を取得するアプリケーションを作成します。