.NET Gadgeteerで温度計 - Push NotificationでWP7に通知

昨日(2/8)のUX-TVでお見せした、.NET Gadgeteerで計測した温度を、Push NotificationでWP7端末に通知する方法を解説します。

このポストを試す前に、https://blogs.msdn.com/b/hirosho/archive/2012/02/07/tipsfordotnetgadgeteerwiththermometerandlcd.aspx を予め読んでおいてください。

準備として、https://msdn.microsoft.com/ja-jp/library/ff431744(VS.92).aspx から、”トースト通知のサンプル”をダウンロードしておいてください。

前のポストで作成したプロジェクトに、Push Notificationを送信する機能を担当するクラスを追加します。

    using System.Net;
    class PushNotificationSender
    {
        public string PushChannel
        {
            get;
            set;
        }

        public void Send(string text1, string text2)
        {
            HttpWebRequest request = HttpWebRequest.Create(PushChannel) as HttpWebRequest;
            request.Method = "POST";
            string toastMessage =
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<wp:Notification xmlns:wp=\"WPNotification\">" +
                "<wp:Toast>" +
                "<wp:Text1>" + text1 + "</wp:Text1>" +
                "<wp:Text2>" + text2 + "</wp:Text2>" +
                "<wp:Param>/PageVisit.xaml?NavigatedFrom=Toast Notification</wp:Param>" +
                "</wp:Toast> " +
                "</wp:Notification>";

            byte[] msg = System.Text.Encoding.UTF8.GetBytes(toastMessage);
            request.ContentLength = msg.Length;
            request.ContentType = "text/xml";

            request. Headers.Add("X-WindowsPhone-Target", "toast");
            request.Headers.Add("X-NotificationClass", "2");

            try
            {
                using (var stream = request.GetRequestStream())
                {
                    stream.Write(msg, 0, msg.Length);
                    stream.Close();
                }
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
        }
    }

.NETでHTTPによるネットワークプログラミングをやったことがある方なら皆さんご存知の、HttpWebRequestクラスが.NET Micro Frameworkにはほぼそのままの形で用意されています。個々に挙げたコードは、Windows Phone 7のトースト通知アプリのPush Notification送信側のコード(サンプルの中のSendToastプロジェクト)をほぼそのまま利用しています。このコードだけで、Push Notificationを送る仕組みは出来上がりです。

次に、このクラスを使って温度を通知するコードを紹介します。ここでは、タッチスクリーンLCDをタッチしたら、Push Notificationを送信するものとします。

Programクラスの、ProgramStarted()メソッドの中で、WPFサブセットAPIにより、UI構築するコードに、パネルをタッチした時に呼ばれるハンドラを登録します。

            display.WPFWindow.Background = new SolidColorBrush(Color.Black);
            StackPanel panel = new StackPanel(Orientation.Vertical);
            display.WPFWindow.Child = panel;

            degreeText = new Text();
            degreeText.TextAlignment = TextAlignment.Center;
            degreeText.ForeColor = Colors.Blue;
            degreeText.Font = Resources.GetFont(Resources.FontResources.NinaB);
            panel.Children.Add(degreeText);
           
            panel.TouchDown += new Microsoft.SPOT.Input.TouchEventHandler(panel_TouchDown); ← ハンドラの登録

その付近で、PushNotificationSenderクラスのオブジェクトを一つ作成しておきます。

                pushSender = new PushNotificationSender()
                {
                    PushChannel = "https://sn1.notify.live.net/throttledthirdparty/01.00/AAGDJDCeI・・・・",
                };

PushChannelに代入しているのは、Windows Phone側でトースト通知アプリを実行して出来上がったPush Notification チャネルです。トースト通知アプリのsdkToastNotificationCSプロジェクトをWP7のEmulator、もしくは、実機でデバッグ実行します。MainPage.xaml.csの35行目からのコードのpushChannelの値が確定する部分(38行目にブレークを張ってステップ実行)でURLの値をコピーし、上の文字列にペーストします。

35            // Try to find the push channel.
36            pushChannel = HttpNotificationChannel.Find(channelName);
37
38            // If the channel was not found, then create a new connection to the push service.
39            if (pushChannel == null)
40            {
41                pushChannel = new HttpNotificationChannel(channelName);

 そして、ハンドラーコード本体は、

        private PushNotificationSender pushSender;
        void panel_TouchDown(object sender, Microsoft.SPOT.Input.TouchEventArgs e)
        {
            pushSender.Send("Gadgeteer Thermometer", degreeText.TextContent);
        }

と、下に示しているtimer_Tick(1秒毎にコールされる)でTextに格納している文字列を、Push Notificationで送信するわけです。

        void timer_Tick(GT.Timer timer)
        {
            double degree = thermoIn.ReadVoltage();
            degree = degree * 78.0 / 3.3 - 22.0;
            Debug.Print("Degree : " + degree);
            degreeText.TextContent = degree.ToString();
        }

実サービスを考えた場合、Push Notificationのチャネルの受け渡しは、例えば、Windows Azure上に温度データ通知サービスを配置するなどして、Windows Phone 7からChannel URLを予め登録し、Azure上のサービスから.NET Gadgeteerに配信もしくは取りに行くなどすれば、スタイリッシュでしょう。