Cloud Zone is brought to you in partnership with:

My name is Bruno Terkaly and I am a Developer Evangelist in Northern California. Over the past few months I have been presenting a wide variety of demos and slides highlighting the wealth of new features in Visual Studio 2008. Bruno is a DZone MVB and is not an employee of DZone and has posted 51 posts at DZone. You can read more from them at their website. View Full User Profile

Augmented Reality, Windows 8, and Cloud Computing – Part 3: Cloud Back-End

11.27.2012
| 2827 views |
  • submit to reddit

TitleDescriptionLink
Augmented Reality applications need a Web Service Back-End. Here is a 90-Day No obligation, totally free offer to use Windows Azure as your web service for Windows 8 Clients.You get: Compute / 750 small compute hours per month, Web sites / 10 web sites, Mobile services / 10 mobile services, Relational database / 1 SQL database, SQL reporting / 100 hours per month, Storage / 35GB with 50,000,000 storage transactions, Bandwidth / unlimited inbound & 25GB outbound, CDN / 20GB outbound with 500,000 transactions, Cache / 128MB, Service bus / 1,500 relay hours and 500,000 messageshttp://www.microsoft.com/click/services
/Redirect2.ashx?CR_CC=200114759
image
Step 0: What we will build. Augmented Reality, Windows 8, and Cloud Computing–How to implement with real codeHigh level introduction to our finished application.http://blogs.msdn.com/b/brunoterkaly/archive/2012
/11/05/step-0-what-we-will-build-
augmented-reality-windows-8-and-cloud-computing-how-to-implement-with-real-code.aspx#
Step 1–Augmented Reality, Windows 8, and Cloud Computing–How to implement with real codeIntroduction. What is Augmented Realityhttp://blogs.msdn.com/b/brunoterkaly/archive/2012/10/29/
step-1-augmented-reality-windows-8-and-cloud-computing-
how-to-implement-with-real-code.aspx#
Step 2–Augmented Reality, Windows 8, and Cloud Computing–How to implement with real codeBuilding the first part of our Azure back-end.http://blogs.msdn.com/b/brunoterkaly/archive/2012/10/30/
step-2-augmented-reality-windows-8-and-
cloud-computing-how-to-implement-with-real-code.aspx#
Step 3–Augmented Reality, Windows 8, and Cloud Computing–How to implement with real code (Implementing the Cloud Back-End)This post provides all source code and explanation for the Azure back-end. This is the back-end for the augmented reality Windows 8 Client.http://blogs.msdn.com/b/brunoterkaly/archive/2012/11/05
/step-3-augmented-reality-windows-8-and-cloud-computing-how-
to-implement-with-real-code-implementing-the-cloud-back-end.aspx#
Step 4–Augmented Reality, Windows 8, and Cloud Computing–How to implement with real code ...This post provides all source code and explanation for the Windows 8 Client (Augmented Reality Demo). The augmented reality Windows 8 Client calls into the Azure back-end described in step 3 above.http://blogs.msdn.com/b/brunoterkaly/archive/2012/11/06/
step-4-augmented-reality-windows-8-and-cloud-computing-how-to-implement-with-real-code-implementing-the-
windows-8-client.aspx#
Source Code - Web Service Back EndThis is the Windows Azure Project that Windows 8 Clients call intohttp://sdrv.ms/Qoqb1J
Source Code - Windows 8 ClientThis is the Augmented Reality Windows 8 Clienthttp://sdrv.ms/T38uBC
This is the finished augmented reality client. 
image
  1. I have completed the code. Now it is time to blog about it.
  2. Notice that it has augmented reality data overload on top of a live photo
  3. It also has a satellite image
  4. You can use the GPS simulator to change locations
    • My system doesn't have a GPS device and yours probably does not either
  5. The information displayed is a mash-up of the Google Maps and information from the National Oceanic and Atmospheric Administration
  6. I will provide all source code.
A zoom-in of the augmented reality data 
002
  1. A little better resolution to see what is happening.
This is a Windows Azure Back-end 
003
  1. It is hosted in a Microsoft Data Center
  2. The image above is running locally (in an emulator)
  3. This running application can be scaled to meet any demand by Windows 8 clients
  4. The style of Azure application is (MVC Web API), described in future posts
The application architecture 
image
  1. We will build a Windows 8 Client in a future post
    • That is where the augmented reality is actually taking place
  2. Our front end web services tier supports our Windows 8 Client
    • We will deploy this tier to a Microsoft Data Center
  3. The Application Services Tier will be Google Maps and the National Oceanic Atmospheric Agency (NOAA)
  4. This could be architected for even greater scale.
    • You could leverage message queues and background processes (worker roles)
  5. It does currently leverage threading for parallel look ups of data mash-ups
    • This means I call Google Maps and NOAA at the same time using .NET Tasks
  6. The next step is to finish building the cloud server.
  7. From there I will show the code behind the Windows 8 client
Focusing on the Cloud Back-End 
image
  1. In Step 2 you could see how to create:
    • A Windows Azure Cloud Project with:

  1 MVC 4 Web Role

  Web Role Type = ASP.NET Web API

Starting the server 
image
  1. It is a Windows Azure Cloud app
  2. It was previously blogged about here
  3. But we need to add more to this project.
Visual Studio 2012 - Solution Explorer 
image
  1. You can see one solution with two projects:
    • Project 1: Location_WebRole
      • This is where we do all the work, adding code
    • Project 2: LocationWebService
      • This is the configuration project that allows us to scale our application once we deploy it to the cloud.
How to build the Azure Cloud Application Back-End 
image
  1. We are going to do 3 things here:
    • Modify Existing Files
    • Add a folder to hold our code
    • Add new classes
  2. Modify Files
    • ValuesController.cs
  3. Add Folder
    • HelperObjects
  4. Add classes (HelperObjects)
    • CityFromGps.cs
    • DataExtractor.cs
    • LocationInfo.cs
ValuesController.cs 
image
  1. This is the entry point for clients making http calls
  2. We only need one method in there.
    • The Get() method responds to Windows 8 client requests

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Location_WebRole.HelperObjects;

namespace Location_WebRole.Controllers
{
    public class ValuesController : ApiController
    {
        // location contains lat/long, "37.788345,-122.404679", for example
        public LocationInfo Get(string location)
        {
            string[] columns = location.Split(',');
            CityFromGps city = new CityFromGps();
            return city.ReverseGeoLoc(columns[1], columns[0]);
        }
 
    }
}

Code Walkthrough
Line 11ValuesController.cs was built by Visual Studio when we created the project. It is the entry point for Windows 8 client requests.
Line 14We have just one Get() method. It is executed automatically by Windows 8 clients. The Windows client will issue the commands in Table A
Line 16Split the GPS coordinates. columns[0] will be 37.785530, and columns[1] will be -122.405672
Line 17Our helper class that actually does all the processing
Line 18Return the JSON answers back to the Windows 8 Client
Table A
Our cloud project running in emulatorhttp://127.0.0.1:81/api/values?location=37.785530,-122.405672
Our cloud project running in a Microsoft Data Centerhttp://locationwebservice.cloudapp.net/api/values?location=37.785530,-122.405672
The main workhorse - CityFromGps.cs 
011
  1. This class does most of the hard work.
  2. It uses concurrent programming techniques to conduct data mash-ups.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Location_WebRole.HelperObjects;

namespace Location_WebRole.Controllers
{
    // My custom string manipulator. Nows how to parse all the XML structures
    public class CityFromGps
    {

        // Method that does all the lookups based on longitude and latitude.
        public LocationInfo ReverseGeoLoc(string longitude, string latitude)
        {
            // Return data is LocationInfo
            LocationInfo loc_info = new LocationInfo();
            DataExtractor de = new DataExtractor(); // a helper class to make this threading code readable
            loc_info.longitude = longitude;
            loc_info.latitude = latitude;

            try
            {
                //
                // Get Data
                //

                XmlDocument[] xmldocs = new XmlDocument[3] { new XmlDocument(), new XmlDocument(), new XmlDocument() };

                Task<string>[] tasks = new Task<string>[3]
                {
                    Task<string>.Factory.StartNew(() =>
                        {
                            xmldocs[0].Load("http://maps.googleapis.com/maps/api/elevation/xml?locations=" + latitude + "," + longitude + "&sensor=false");
                            XmlNodeList weatherList = xmldocs[0].SelectNodes("//ElevationResponse/result");
                            loc_info.elevation = (Convert.ToDouble(weatherList[0]["elevation"].InnerText) * 3.2808399).ToString();
                            return "";
                        }),
                    Task<string>.Factory.StartNew(() =>
                        {
                            // Get Transit and Neighborhood Info
                            xmldocs[1].Load(string.Format("http://maps.googleapis.com/maps/api/geocode/xml?latlng={0},{1}&sensor=false", latitude, longitude));
                            loc_info.bus_and_neighborhood = de.GetTransitAndNeighborhood(xmldocs[1]);
                            return "";
                        }),
                    Task<string>.Factory.StartNew(() =>
                        {
                            // Get Weather Info
                            xmldocs[2].Load(string.Format("http://graphical.weather.gov/xml/sample_products/browser_interface/ndfdXMLclient.php?lat={0}&lon={1}&product=time-series&maxt=maxt&mint=mint", latitude, longitude));
                            loc_info.max_temp = de.GetMaxTemp(xmldocs[2]);
                            loc_info.min_temp = de.GetMinTemp(xmldocs[2]);
                            return "";
                        })
                };
                //Block until all tasks complete. This is much faster.
                Task.WaitAll(tasks);
                return loc_info;
            }
            catch (Exception ex)
            {
                loc_info.error = "(Location lookup failed: ) " + ex.Message;
                return loc_info;
            }

        }

    }

}

Code Walkthrough
Lines 1 to 10Needed using statements
Line 15CityFromGps class that we've added
Line 19The ReverseGeoLoc() method. It returns JSON-formatted data for LocationInfo (a class we still need to add). It takes two parameters, logitude and latitude. It will perform a number of look ups against other web services, such as Google Maps and NOAA (NOAA - National Oceanic and Atmospheric Administration)
Lines 22 and 23Instantiate our helper objects. LocationInfo will contain the results of our data lookups. It will hold temperature, elevation, city, etc.
Line 33The XmlDocument objects that will be used for the lookups against web services
Lines 37, 44, 513 Tasks (concurrent threads if enough cores) are launched, working in parallel, performing lookups against web services.
Lines 40-41, 47-48, 54-56The actual lookups. This where the actual call to Google Maps and NOAA takes place.
Line 61Wait for all tasks to complete. This line ensures that we continue only after all 3 tasks have completed.
Line 62Return the LocationInfo object, which is now populated with data. The ASP.NET Web API automatically makes this a JSON formatted object.
DataExtractor.cs and LocationInfo.cs 
013
  1. DataExtractor.cs abstracts the complexity of parsing XML and getting the answers we need
    • Such as max temp, min temp, elevation, etc
  2. LocationInfo.cs represents the data going back to the Windows 8 client
    • It is in JSON format.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;

namespace Location_WebRole.Controllers
{
    public class DataExtractor
    {
        public string GetTransitAndNeighborhood(XmlDocument doc)
        {

            string result = "";
            bool foundneighborhood = false;
            bool foundbus = false;
            XmlNodeList xnList = doc.SelectNodes("//GeocodeResponse/result/address_component");
            foreach (XmlNode xn in xnList)
            {
                try
                {
                    switch (xn["type"].InnerText)
                    {
                        //Add whatever you are looking for below
                        case "bus_station":
                            {
                                if (foundbus)
                                    break;
                                if (result != "")
                                    result += ", ";
                                result += "Bus: " + xn["long_name"].InnerText;
                                foundbus = true;
                                break;
                            }

                        case "neighborhood":
                            {
                                if (foundneighborhood)
                                    break;
                                if (result != "")
                                    result += ", ";
                                result += "Neighborhood: " + xn["long_name"].InnerText + " (" + xn["short_name"].InnerText + ")";
                                foundneighborhood = true;
                                break;
                            }

                        default:
                            break;
                    }
                }

                catch (Exception e)
                {
                }
            }

            return result;
        }

        internal string GetMaxTemp(XmlDocument doc)
        {
            XmlNodeList xnList = doc.SelectNodes("//dwml/data/parameters/temperature");
            return xnList[0]["value"].InnerText;  // offset 0 is max temps
        }
        internal string GetMinTemp(XmlDocument doc)
        {
            XmlNodeList xnList = doc.SelectNodes("//dwml/data/parameters/temperature");
            return xnList[1]["value"].InnerText;  // offset 1 is min temps
        }
    }

}

Code Walkthrough
Line 11The method that returns the bus stop and neighborhood information.
Line 60The method that returns the max temperature info from NOAA
Line 65The method that returns the min temperature info from NOAA

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Web;

namespace Location_WebRole.HelperObjects
{
    public class LocationInfo
    {
        // Data we will lookup
        public string latitude { get; set; }
        public string longitude { get; set; }
        public string elevation { get; set; }
        public string bus_and_neighborhood { get; set; }
        public string max_temp { get; set; }
        public string min_temp { get; set; }
        public string error { get; set; }
    }
}

Code Walkthrough
Line 11Our LocationInfo structure. 

This will be returned back to the Windows 8 client, populated with data. 

The ASP.NET Web API will automatically convert this object to JSON format.

Published at DZone with permission of Bruno Terkaly, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)