Using Reactive extensions for feeding test sensor-readings in Windows Phone

An interesting technology you might have heard of is Reactive Extension (MSDN Rx Site). It’s available for different types of applications, although  you may need to add the necessary assemblies through NuGet. But in WP7.5 it’s included in the SDK. The only thing you need are references to Microsoft.Phone.Reactive and System.Observable.  Let’s start with a very simple scenario : simulating the PositionChanged-event of the GeoCoordinateWatcher. I know that the Mango-emulator allows me to simulate Geographical position, but it’s a nice starting point. My application consists out of a very simple Page which shows a Bing mapcontrol. I set the Zoomlevel to 10, and we’re set to go. The code is fairly simple : 1: private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) 2: { 3: GeoCoordinateWatcher watcher = new GeoCoordinateWatcher(); 4: watcher.MovementThreshold = 1; 5: watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged); 6: 7: watcher.Start(); 8: } 9:   10: void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e) 11: { 12: map1.Dispatcher.BeginInvoke(()=> map1.Center = e.Position.Location); 13: } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }   Now let’s try to simulate some changes in our position: Let’s travel from South England to France, passing Dover and Calais. Let’s start by creating a simple function that gives me back an GeoPositionEventArgs every 50 ms : 1: #if DEBUG 2: static double l = 0; 3:   4: private static IEnumerable<GeoPositionChangedEventArgs<GeoCoordinate>> GetLocations() 5: { 6: while (true) 7: { 8: System.Threading.Thread.Sleep(50); 9: l += .001; 10:   11: yield return new GeoPositionChangedEventArgs<GeoCoordinate> 12: (new GeoPosition<GeoCoordinate>(DateTimeOffset.Now, new GeoCoordinate(51, l))); 13: } 14: } 15: #endif .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Now let’s create a Thread that calls this functions, and uses Rx for feeding the eventargs to the eventhandler : 1: private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) 2: { 3: GeoCoordinateWatcher watcher = new GeoCoordinateWatcher(); 4: watcher.MovementThreshold = 1; 5: watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged); 6:   7: #if DEBUG 8: System.Threading.Thread thr = new System.Threading.Thread(() => 9: { 10: var test = GetLocations().ToObservable(); 11: test.Subscribe(ea => watcher_PositionChanged(null, ea)); 12: }); 13:   14: thr.Start(); 15: #endif 16: 17: watcher.Start(); 18: } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }   The ToObservable-function turns my IEnumerable<T> into an IObservable<T>. The Subscribe-function binds it with the eventhandler. Run the app (in debug-mode, of course), and you’ll see the map slowly moving East passing from England to France. Now let’s try to use the same concept with the Accelerometer. I create a simple page with three TextBlock-controls for displaying the X,Y and Z-components of my accelaration. In here we’ll have to do similar stuff with SensorReadingEventArgs<AccelerometerReading>. In AccelerometerReading I need to set the Acceleration-property which is of type Vector3 (with X,Y,Z). The problem that arrises here is that the setter of Accelartion is declared as internal, so I cannot use this from my code. The solution can be found at Microsoft Patterns and Practices site, which has some recipes for creating alternatives for the sensor-classes (here). Instead of the AccelerometerReading-class I can use AccelerometerSensorReading-class and the SettableAccelerometerSensorReading-class. The name of the latter already describes it : it will allow me to set the Acceleration-property. Let’s have a look at the result : 1: private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e) 2: { 3: AccelerometerAdapter acc = new AccelerometerAdapter(); 4: acc.TimeBetweenUpdates = TimeSpan.FromSeconds(1); 5:   6: acc.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<AccelerometerSensorReading>>(acc_CurrentValueChanged) 7: acc.Start(); 8:   9: #if DEBUG 10: System.Threading.Thread thr = new System.Threading.Thread(() => 11: { 12: var test = GetReadings().ToObservable(); 13: test.Subscribe(ea => acc_CurrentValueChanged(null, ea)); 14: }); 15:   16: thr.Start(); 17: #endif 18: } 19:   20: void acc_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerSensorReading> e) 21: { 22: ContentPanel.Dispatcher.BeginInvoke(() => 23: { 24: textBlock1.Text = e.SensorReading.Acceleration.X.ToString(); 25: textBlock2.Text = e.SensorReading.Acceleration.Y.ToString(); 26: textBlock3.Text = e.SensorReading.Acceleration.Z.ToString(); 27: }); 28: } 29:   30: #if DEBUG 31:   32: static float f = 0f; 33: public static IEnumerable<SensorReadingEventArgs<AccelerometerSensorReading>> GetReadings() 34: { 35: while (true) 36: { 37: System.Threading.Thread.Sleep(500); 38: var acc = new SettableAccelerometerSensorReading(); 39: acc.SetAcceleration(new Vector3(f, 0f, 0f)); 40: f += .1f; 41: if (f > Math.PI) 42: { 43: f = (float)-Math.PI; 44: } 45: var reading = new SensorReadingEventArgs<AccelerometerSensorReading>(); 46:   47: yield return new SensorReadingEventArgs<AccelerometerSensorReading>() { SensorReading = acc }; 48: } 49: } 50: #endif .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }   And there you go. Also tried it with the virtual Motion-sensor, unfortunately I got stuck there. I’m missing a SettableAttitudeReading-class, and I’ve been trying to create it since a few days, but I’m close to giving up. I guess there’s a reason for not having it in the patterns-library. Follow @PiekenPuil !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs"); Tweet

Updating WP7 live tiles without push notifications

While experimenting with push notifications for updating your live tiles, I found the ShellTileSchedule-class. It sounded interesting enough to play around with it. On MSDN I found following description for this class : Creates an object which allows an application to schedule updates of its tile's background image.  The ShellTileSchedule has some properties like the recurrence and the interval. The interval is an enumeration which goes from hourly to monthly : Another Property is the RemoteImageUri. Because of the word "Remote" I assume that the image has to be remote (that was a hard one ). So for testing this thing I first set up a website, with simply a png-image (62*62 – I copied Background.png and changed it a bit with Paint). Let's set up our schedule. This has to be done in the Application_Launching: private void Application_Launching(object sender, LaunchingEventArgs e) { sts = new ShellTileSchedule(); sts.Interval = UpdateInterval.   sts.Recurrence = UpdateRecurrence.Interval; sts.RemoteImageUri = new Uri(String.Format("http://localhost:51177/Site/Tiles/1.png", TileNr.ToString())); sts.Start(); } After starting the application I had to wait for an hour before my tile changed. Changing the clock settings didn't do the job either, but after an hour, finally the tile changed. This could be useful for pulling tiles, instead of pushing. Get a tile every hour for showing the weather conditions in your area. Now about this "Remote"-thing. Can I use a local png-file for changing the tile this way ? My first try was to add a png-file, and than refer to it this way: sts.RemoteImageUri = new Uri("/LocalTile/5.png",UriKind.Relative);   That was not good. Also tried it with "/TilesTest;component/LocalTile/5.png", but also no success. I needed to get the absolute path. In Silverlight I can use App.Current.Host.Source and Windows Phone is Silverlight, right. But I cannot use the Source-property here, although I can see it in my Locals-window:   OK, another try : let's use this code: Uri uri = new Uri(new Uri( "file:///Applications//Install//27F6C4CB-1192-44AD-A970-635F12689A08//Install"), "//LocalTile//5.png"); sts.RemoteImageUri = uri; OK, I know it's not very useful, because every user that has this application, will also have another GUID. Still : I do it for serving science . Result :   What happened to my GUID and stuff jQuery152010964315148992043_1315308924440 Last try, Let's simplify by using this : Uri uri = new Uri( "file:///Applications//Install//27F6C4CB-1192-44AD-A970-635F12689A08//Install//LocalTile//5.png");   And now I get this : OK, I quit. Remote indeed means Remote. Tweet