昨日(2/8)のUX-TVでお見せした、.NET Gadgeteerで計測した温度を、Push NotificationでWP7端末に通知する方法を解説します。
このポストを試す前に、http://blogs.msdn.com/b/hirosho/archive/2012/02/07/tipsfordotnetgadgeteerwiththermometerandlcd.aspx を予め読んでおいてください。
準備として、http://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 = "http://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);3738 // 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に配信もしくは取りに行くなどすれば、スタイリッシュでしょう。