Connecting Embedded Devices to Windows Phone 7


For our recent trip to Maker Faire, the team built a number of demos.  One included controlling a remote device and exposing data collected from a set of sensors on Windows Phone 7.  There was a main controller device that communicated with distant sensors through a mesh network (802.15.4).  The controller device includes a camera mounted on a servo that moves back and forth raking pictures of the area.  The camera can also be directed to a specific area remotely through the interface described below:

The controller device hosts a web server and connects through WiFi or a wired connection.  The user browses to the .htm page that hosts the Silverlight application.  The Silverlight application is stored on an SD card connected to the embedded device.  Once this application has been downloaded to the desktop, it sends an http request to the web server which returns an xml document (shown below).  The camera can be moved to a specific position by adding a parameter to the url (e.g. http://192.168.1.108/module/remote.data?angle=-25)    If the Server finds a parameter named ‘angle, it instructs the servo accordingly.

(Much of this is built with on the work of Elze Kool whose NET libraries supply classes for HTTPHeader, HTTPServer, HTTPSEeverWorker, IRequestHandler, and RequestParameters which make the web service work much easier.  These libraries can be found at http://www.microframework.nl/projects/multithreaded-webserver-class/)

The XML that is returned looks like this:

<?xml version="1.0" encoding="UTF-8" ?>
<root>
  <module type="Camera" timestamp="Jan-01-2009 12:16:05 AM">
    <imageUrl>http://192.168.1.108/module/camera.jpg</imageUrl>
  </module>
  <module type="Motor" timestamp="Jan-01-2009 12:16:05 AM">
    <angle>0</angle>
  </module>
  <module type="Temperature" timestamp="Jan-01-2009 12:16:05 AM">
    <temperature>24.210000000000001</temperature>
    <humidity>60.350000000000001</humidity>
  </module>
</root>

and the PC Silverlight app looks like this:

clip_image002

Now for the Windows Phone part.

This also written in Silverlight keeps the same look.

clip_image002[5]         clip_image004         clip_image002[7]

And connecting the the web service and managing the data is very easy in .NET as you can see in this example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Media.Imaging;
using Gadgeteer.RemoteMonitor.ViewModels;
using System.Xml;
using System.IO;
using System.Xml.Linq;

namespace Gadgeteer.RemoteMonitor
{
    public partial class MainPage : PhoneApplicationPage
    {

       const string imageUrl = "http://…/Module/camera.jpg";
       const string remoteDataUrl = "http://…/Module/Remote.data";

        WebClient wc;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            // Set the data context of the listbox control to the sample data
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            sldrCameraAngle.IsEnabled = false;     
            wc = new WebClient();
            wc.DownloadStringAsync(new Uri(remoteDataUrl));
            wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
        }

        void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            double angle;
            sldrCameraAngle.IsEnabled = true;
            if (!(e.Result.Contains("root"))) return;
            string xml = e.Result; 
             XDocument xDoc = XDocument.Load(new StringReader(xml));         

            var q = from c in xDoc.Descendants("module")
                    select c;

            temperatureDisplay1.TemperatureInCelsius = (int)Double.Parse(q.Elements("temperature").First().Value);
            txtHumidity.Text =  Math.Round(Double.Parse(q.Elements("humidity").First().Value), 2).ToString();
            angle = double.Parse((q.Elements("angle").First().Value));
            txtCameraAngle.Text = angle.ToString();
            sldrCameraAngle.Value = angle;

            ImageSource img = new BitmapImage(new Uri(imageUrl, UriKind.Absolute));

            imgCamera.Source = img;

            switch (Settings.TemperatureUnit)
            {
                case "Farenheit":
                    temperatureDisplay1.TemperatureScale = Components.TemperatureTypes.Farenheit;
                    break;

                case "Celsius":
                    temperatureDisplay1.TemperatureScale = Components.TemperatureTypes.Celsius;
                    break;

                case "Kelvin":
                    temperatureDisplay1.TemperatureScale = Components.TemperatureTypes.Kelvin;
                    break;
            }
        }

        private void ApplicationBarMenuItem_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/Settings.xaml", UriKind.Relative));
        }

        private void sldrCameraAngle_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            sldrCameraAngle.IsEnabled = false;
            int angle = (int) Math.Round(sldrCameraAngle.Value, 0);
            wc = new WebClient();
            wc.DownloadStringAsync(new Uri(remoteDataUrl + "?angle=" + angle.ToString()));
            wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
        }

        private void imgRefresh_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            sldrCameraAngle.IsEnabled = false;
            wc = new WebClient();
            wc.DownloadStringAsync(new Uri(remoteDataUrl + "?Guid=" + Guid.NewGuid().ToString()));
            wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
        }

    }
}

With .NET and web services, we now quickly have embedded devices talking to PCs, phones and other services in the cloud.  With this, you can put together a device that lets you peer into your yard at home from wherever you are using your Windows Phone 7.  What more could you ask for?  The ‘Internet of Things’ is an exciting area to be thinking about.


Comments (7)

  1. Peter says:

    That sounds great but… can it be done with just the phone and the .NET Micro framework board? ie no wireless router in the middle handing out DHCP addresses?

  2. Colin Miller says:

    Good point – there is a router in the mix as you point out.

  3. franck says:

    hello, very good project, can you say me what is the hardsystem you use,

    i want to create an application similar, may be with an arduino blackwido or fez domino

    thank you

  4. Colin Miller says:

    Hi Franck,

        This was built with the .NET Gadgeteer devices (blogs.msdn.com/…/net-gadgeteer.aspx) These are not commercialy available yet but hopefully by Spring.  The Gadgeteer is built around the GHI EMX module.  You might look at the GHI Cobra board as well – it is built around the same module.  

  5. Paul C says:

    I'm currently doing a similar project with the NetDuino.  I'll keep you posted as things develop.

  6. Colin Miller says:

    Great – We'd love to hear about that Paul

  7. StanDeMan says:

    Hi together,

    where can I find the whole sources in a Studio 2010 Project (really for all – mean: PC, Cobra and Phone7)? Let me know this, please. This is a great sample for demonstrating in my office.

    Thanx a lot

    StanDeMan

Skip to main content