Wednesday, May 30, 2012

Generating Fake GPS Data

Why Fake Data?

One of the more interesting bits to the project is being able to generate fake GPS tracks to feed to the API. We need to be able to demonstrate the real-time aspects of the solution without having to have someone drive around and collect the data. Also it would be nice be able to generate tracks based on who we are demoing to. Perhaps a simulated drive from the iVision office to a clients office.

So, the goal is to be able to generate fake GPS tracks that we can feed to the iGOR application while demoing the real-time updating of the maps. We also need to be able to generate these tracks from any two points, and they should follow the streets and roads available in a logical way.

Google driving directions seems like a good place to start, and I found a great tool to help. GPS Babel is a free application that can take the data generated from Google Maps (and many other sources) and generate a standard GPX file.

So we want a page in our application that looks something like this:


We will have the user enter their start and destination addresses into Google Maps hosted in a browser control. They will then copy the link generated from the directions into the text box and press the Go button.



This will save the resulting HTML to a file that can be picked up by GPS Babel and converted into GPX. A lot more straight forward than it sounds, I promise.

First thing to do is download/install GPS Babel (follow the link above). Make a note of the location you install it as you will need it later. Now in our web browser control we can set our url to http://map.google.com.

Now lets wire up our Go button event like this:
private void cmdGo_Click(object sender, EventArgs e)
        {
            try
            {
                _isBuilding = true;
                var newURI = new Uri(txtTrackURI.Text + "&output=js");
                webBrowser.ScriptErrorsSuppressed = true;
                webBrowser.Url = newURI;
            }
            catch (Exception)
            {
                MessageBox.Show("Link does not appear to be valid. Please chech the track uri and try again.",
                                "Invalid Track URI", MessageBoxButtons.OK, MessageBoxIcon.Asterisk,
                                MessageBoxDefaultButton.Button1);
                _isBuilding = false;
            }
        }

As you can see we set a form level bool to true (I will come back to this later), take the text from the textbox and append a query parameter. This parameter tells Google to output the resulting page in a special format that can be imported by GPS Babel. We then update the web browser controls uri to this new location. Lets take a look at the Document Complete event of our control:

        private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            if (_isBuilding)
            {
                var gpsBabelLocation = Properties.Settings.Default.GPSBabelLocation + @"\gpsbabel.exe";
                var tempFolder = Properties.Settings.Default.LocalTempFolder;

                var localMapFilePath = tempFolder + @"\map.txt";
                var localGPXFilePath = tempFolder + @"\gpx_data.gpx";

                var fs = new FileStream(localMapFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
                var file = new StreamWriter(fs, Encoding.ASCII);
                file.WriteLine(webBrowser.DocumentText);
                file.Close();

                var p = new Process
                {
                    StartInfo =
                    {
                        FileName = gpsBabelLocation,
                        Arguments = @"-t -i google -f " + localMapFilePath + @" -o gpx,suppresswhite=0,logpoint=0,humminbirdextensions=0,garminextensions=0 -F " + localGPXFilePath,
                        UseShellExecute = false
                    }
                };

                p.Start();
                p.WaitForExit();

                TextReader tr = new StreamReader(localGPXFilePath);
                var viewer = new GPXViewer { Doc = tr.ReadToEnd() };
                tr.Close();
                viewer.ShowDialog();

                webBrowser.GoBack();
                txtTrackURI.Text = null;
            }

            _isBuilding = false;
        }

Ah, there is that _isBuilding again. As you can see we are using it to control whether or not we process the web controls contents on document complete. As the user is generating their track, this event gets fired several times and we only want to process it when the user has hit the Go button.

The first thing we do is load up the location of the GPS Babel exe and the location of a temp folder (these are stored via the Settings tab which I will cover in a different post). We also set up the location of the map.txt file which is the input into GPS Babel, and gpx_data.gpx which is the output from the conversion process.

Next we save the contents of the web browser control to our input file (map.txt). Now we create a new Process object to kick off the GPS Babel exe. We give it the exe location and a set of command line arguments to control how GPS Babel executes and where to store the output. Once the conversion process is complete we read in the results from the gpx_data.gpx file into a string and pass it to another form to display the output.

My next post will cover the gpx viewer form and saving our file to Azure cloud storage for later retrieval.

Thursday, May 24, 2012

iGOR Design/Architecture Philosophies


The iVision Way


Actually, we don’t have a codified ‘way’, as far a project architecture goes, but we have guiding principles that allow us to deliver quality work in volume. I am going to steal an analogy from a co-worker (thanks Brian!).

Software projects are like trying to build a tower out of blocks. The higher the tower, the more features and business value is delivered. Some will start putting bricks one on top of the other and the tower gets high very quickly. This method involves little to no strategic planning or processes to support the development cycle. Thus the tower is unstable, and seemingly small changes can topple whole thing. These kinds of projects are rarely delivered on time or on budget. Others will build a wide and stable base and only start building upwards when they are sure there are no issues with the blocks already placed. These teams create reams of documentation and analysis of the business space and all interconnected systems. Analysis paralysis, it eats at deadlines and produces little of actual value to the business. These kinds of projects never deliver. Other projects are built with a solid base, just wide enough to support the pieces above. The tower goes up at a reasonable pace, with a stable support that allows for flexibility in case of change or the unexpected. This final method is far more likely to deliver on time and on budget and is what allows iVision to succeed where others fail.

I will assume you know how to download the Azure SDK and set up a new cloud project with the correct setting. I won't bore you with those details. I also won't subject you to testing plans and UI control minutia. Let’s get right to the fun.

iGOR Specifics

We have identified four separate projects to make up the solution; a web site, an API, an Azure worker and a desktop application. As we progress we will add more as the design dictates. Our initial solution looks like this:


iGOR is the Azure project and iGOR.Portal is our web site. The rest should be self exploratory. We are going to start with the desktop app (iGOR.App). This is because we need to be able to create and submit fake data tracks to iGOR for testing and demonstration (remember this is not a real production app). Also I find it to be an interesting problem to solve.

Here is a mock up of the main layout of the app we are going for:

As you can see we are looking at eight tabs, each with a distinct role in tracking remote employee locations, solution maintenance and settings. Next post will be a deep dive (including code) into generating fake device tracks using Google Maps.

Thursday, May 17, 2012

Introducing iGOR

The Why

My current employer, iVision does some fantastic work in the line of business application development field, and I am proud to be a part of it. We are currently preparing to do an internal project that will be used for technical demos, internal training and as a new technology proving platform. We have tentatively named it iGOR (iVision GPS Online Repository) and I will be writing about its design and development as we progress through the process.

The What

The concept is pretty straight forward, we have a fictional new client that has technicians in the field and would like to have the GPS location of each employee in real-time so they can optimize routes and update schedules. They have installed GPS receivers and cellular modems into each technicians laptop. They want the devices to transmit its current location every few seconds, and if it loses connectivity, to locally store the location data until the connection is re-established and then bulk send the data. They would also like to be able view each laptops track history for a given date range as well as see it in real-time.

The How

iGOR will be hosted on Microsoft’s Azure platform and be composed of four distinct applications; a desktop application, a worker role and two web roles. The site web role will handle the user interaction with a web interface, in this case a web site written in ASP.NET MVC 4. The API web role will handle the device interaction through an exposed API. The lone worker role will handle all long running or asynchronous tasks; such as file import/export, email communications and any regularly scheduled maintenance tasks. The desktop application will allow for users to interact with the underlying data stores. Users will be able to add/edit/delete devices, view GPS data, upload data files for import and other administrative tasks

Long term storage will be handled using Azure SQL for user and device information, Blob storage for files to be imported/exported and Table storage for the actual GPS data. Queues will be used for communication between roles and applications.

High Level Concept

The next post will be about setting up the development environment and some project architecture decisions.



Wednesday, May 16, 2012

Obligatory First Post Nonsense

Ok, so this is not actually my first post ever, just the first on this new engine and first blog with a more technical bent. I will be writing about any interesting issues that I run across in my various coding adventures.

One of the things I hope to write about is a technology demo application I am putting together for my day job. A mix of MVC 4, Windows application and Windows Azure. Will be a start-to-finish look at everything involved and should be a lot of fun.

Also will pontificate on the trials and tribulations of my start up company that is developing tools for small businesses.

Questions, comments and feedback all welcome. Now, be careful out there.