06 October 2016

A HoloLens airplane tracker 2–Setting up the project and getting airplane assets

Intro

All right my friends, it’s time to hit Unity again. In a previous blog post about the Cube Bouncer I have told you how to set up a project. That was quite a convoluted procedure. Luckily, things have improved considerably since, especially where it comes to the HoloToolkit. So this ‘setting up’ post will be a lot shorter and simpler.

Creating the project

Don’t start with creating a project – first find the HoloToolkit here on GitHub, and clone it at some place on your disk. Then follow carefully the first two steps of procedure as described here.

Then you create the Unity project.

image

Initializing the project

Proceed with following the third step of the getting started document: import the package. This will give you two folders in your Assets folder plus some stuff in the root – and an extra menu-item, called “HoloToolkit”

image

image

I usually delete everything under HoloToolkit-Examples. And then I hit File/Save Scene to save the current scene as “Main”. Now do the fourth step of the getting started document. I usually skip the step of adding ManualCameraControl.cs to the camera. Allow Unity to reload the project when it has to, and accept it’s offer to save the Main scene when it asks to. Now your project has been set up the way the HoloToolkit people think it’s a good default. Only I don’t quite agree with all settings, so we are going to change a few ;)

Tweaking the camera

There are two major things I want to do to the camera:

image

Every manual about the HoloLens I saw so far say you should put the camera at 0,0,0 and the near clipping plane at 0.85m. To make things clear – the clipping plane is the minimum virtual distance you can get to a Hologram before it winks out. I found it to be very cool to be able to get up close to the airplanes and the airport and see the amazing level of detail HoloLens is capable of. As to the camera location – this is essentially a 3D map, I am a GIS person – and a stubborn b*st*rd as well. So I put 0,0,0 at the center of my display data, a logical origin – the center of Schiphol airport according to Google Maps. The camera then is stationed a little South and above it. So when the app starts, you will see Schiphol float about 2 meters before you and 25 cm down from your horizontal line of sight. You will be looking due North - which gives you a nice and compelling overview of airplanes going out over the ocean and around Amsterdam, or coming into it.

After you have made the settings, double-click the camera in the hierarchy.

Directional light

Basically this can be whatever you like, but I opted to put it right over the airport.

image

The hat stand

Finally, add an empty game object “HologramCollection” to the main scene by right-clicking in the hierarchy, and select “Create Empty”. Make sure both position and rotation X, Y and Z are all 0 (zero) and Scale all 1:

image

This will be the hat stand – the place where all other Holograms will be placed in or moved within.

Getting the airplanes assets

There is of course the awesome Unity Asset store, but there is also a great site where you can find a lot of free (and paid) 3D models. It’s called an awesome site called CGTrader and claims to have 520000 3D models to choose from.

image

Models are available in a range of formats – we will need to have an airplane that is provided in OBJ or FBX format, because that is what Unity likes to have. You can just look for “aircraft free” and find a lot of airplanes Lo and behold, here’s a beautiful A320 and it’s free, too:

image

Before you use a model, make sure the license allows you to do so. When in doubt, contact the person who uploaded it – the site offers that capability. In my case, I contacted a person called Maxim Kraft and he (I assume he) graciously gave me permission to use it. He has a whole range of excellent models – check him out!

Anyway - hit “Free download” and select “3d-model.fbx.zip”. Unblock and unzip the file. Rename the file that comes out of it 3d-model.fbx – to A320.fbx. Then go to Unity, make a folder “A320” in the root and drag the A320.fbx from your explorer on top of it. Net result should be this:

image

And if you drag the A320 on top of your scene (don’t!) you will see this ginormous airplane (and this is zoomed out considerably!)

image

That clearly needs to be scaled down a little first. We will do that in the 4th blog post of this series.

A word about source control settings

I had quite some ‘fun’ getting this solution properly in source control. I am not absolutely sure this is necessary, but I think – at least for Git – it is. Hit Edit/Project Settings/Editor and select “Visible Meta Files”

image

As to the rest – I am not a Git guru. I have included two .gitignore files, one for the FlightDataService in my previous post, and one for the Unity project. I have learned the hard way that for checking in Unity projects in Git, you make sure that everything in Assets and ProjectSettings gets checked in. As far as these directories are concerned, there is no such thing as an ignored file. So make sure everything under that is added to your repo. This includes dlls.

Code so far can be found here. That’s a short post, eh? I did say the procedure for setting up a project was dramatically simpler now, and it is indeed!

The code, as always, can be found online – here on github

05 October 2016

A HoloLens airplane tracker 1–an Azure dataservice for aircraft data

Introduction

Recently I posted my first HoloLens app “AMS HoloATC” to the public store, Now it has been showed to the important customers, I have no longer to keep it under wraps, and I can start doing what I always planned to do – bring this app in the open, and blogging in detail how I built it. So here we are, a little earlier than I anticipated. For those who have not seen it, a little video of the app, recorded the Wortell offices, which are housed in an converted Roman Catholic church (hence some unusual details).

 

A little rant

So why am I ‘giving this all away’? If there is one thing around the HoloLens that really annoys me it’s the secrecy. Not secrecy from Microsoft – I am talking about the videos that show beautiful apps, and tell zilch about how things are made, nothing about best practices or experiences. It’s a far cry from what I was used to in the Windows Phone and am used to in the UWP world. I get it: HoloLenses are expensive, investments need to be protected, commercial interest are at stake, your fellow community member is maybe a competitor too – but approaching how-to knowledge as a trade secret is taking it a bit too far IMHO. This is, after all, the age of Open Source. So I am going to show you (almost) every little detail, show you the places where I stumbled, and include all the code – like you are used from me from way back before I was MVP. I hope it will be useful for you. And I sincerely hope some more people will participate in being more open about their experiences in this new and exiting field. End of rant.

Planned series

As far as I can see, this is going to be an 8 part series.

  1. A data service for aircraft data (this article)
  2. Setting up the project and getting airplane assets
  3. Creating an annotated airplane
  4. Reading data and positioning airplanes
  5. Smooth movement with iTween and adding a trail 
  6. Adding an airport (and a tower)
  7. Activating an aircraft by air tapping
  8. Adding the church and the billboard

As you can see, in the first part we are not even touching on a HoloLens yet. So let’s get started with

A demo data service

For what I hope are obvious reasons I cannot give you access to my live data feed, but what I can do is provide a sample. It serves up a 10 hour loop of recorded live data data, using data files. And this actually the feed the app in the store uses. We start with creating an App Service called “FlightDataService”.

image

I put this in a subdirectory HoloATC_Demo as this will be the home for both projects – the data service and the Unity projects/the UWP app. On the next screen I suggest you select ‘Host in the cloud’ on Azure indeed and take it from there. Provided of course you have an Azure subscription. If you don’t, take a free trial.

image

I will skip the details of hosting the service in the cloud for now, you can also do that later. First, we do a big cleaning out. We empty the Controllers, DataObjects and Models directory of the project. Then open App_Start/Startup.MobileApp.cs and remove the class MobileServiceInitializer at the bottom of the file, as well as line 25 and 26 of the Startup class:

// Use Entity Framework Code First to create database tables based on your DbContext
Database.SetInitializer(new MobileServiceInitializer());

Also, use all unused namespaces in that file, in particular FlightDataService.DataObjects and FlightDataService.Models as they no longer exist.

Adding data objects

The service employs two data objects and one enumeration. The last one is the most simple:

namespace FlightDataService.DataObjects
{
  public enum TrackType
  {
    Up = 1,
    Down = 2
  }
}
A plane is either going up or down. At least - for now. Then we need a coordinate, and this looks a bit peculiar
namespace FlightDataService.DataObjects
{
  public class Coordinate
  {
    public double Lon { get; set; }
    public double Lat { get; set; }
    public double? Alt { get; set; }
    public double X { get; set; }
    public double Y { get; set; }
    public double Z { get; set; }
  }
}

There’s not only Latitude, Longitude and Altitude, but also X, Y and Z. This is is the already converted Lat/Lon/Alt coordinate into Unity X/Y/Z space as used by HoloLens. How this is done, you can read in the precursor to this series. You won’t see this conversion in the solution as this is already converted data. But the important point it this – for every every airplane, it’s coordinate and that of it’s track (see later) needs to be converted by a set of complex mathematical calculations. Every 10 seconds the HoloLens app will pull in new aircraft data, this may means every 10 seconds up to 500 points need to be converted. it’s much more logical to run that conversion where the available computing power is next to unlimited – in Azure – in stead of a HoloLens, whose resources are limited to what Microsoft could cram into it.

The final data class is the Flight:

using System.Collections.Generic;

namespace FlightDataService.DataObjects
{
  public class Flight
  {
    public Flight()
    {
      Track = new List<Coordinate>();
    }

    public string Id { get; set; }

    public string FlightNr { get; set; }

    public string Aircraft { get; set; }

    public Coordinate Location { get; set; }

    public double? Speed { get; set; }

    public double? Heading { get; set; }

    public List<Coordinate> Track { get; set; }

    public TrackType TypeTrack { get; set; }

    public bool IsActive { get; set; }

    public override string ToString()
    {
      return string.Format("{0} {1} {2} {3} {4} {5}", FlightNr, Aircraft,  
        Location.Alt, Speed, Heading, TypeTrack).Trim();
    }
  }
}

My aircraft data feed does not always give speed or heading, especially when airplanes just have taken off, so both are nullable types. Notice also the track – the list of points where the aircraft has already been observed. IsActive is a special case – we won’t use that until much much later.

Adding a controller

We add a simple Azure Mobile App Custom Controller “FlightDataController”

image

And put the following code in it:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Http;
using FlightDataService.DataObjects;
using Microsoft.Azure.Mobile.Server.Config;
using Newtonsoft.Json;

namespace FlightDataService.Controllers
{
  [MobileAppController]
  public class FlightDataController : ApiController
  {
    // GET api/FlightData
    [HttpGet]
    public List Get()
    {
      var dataDirectory = new DirectoryInfo(
        System.Web.HttpContext.Current.Server.MapPath(@"~/App_Data"));

      var time = DateTimeOffset.UtcNow;
      var maxPattern = $"{time.Hour % 10 + 8:00}_{time.Minute:00}_{time.Second:00}.json";
      var datafile =
          dataDirectory.EnumerateFiles()
              .Where(p => string.Compare(p.Name, maxPattern, StringComparison.Ordinal) >= 0)
              .OrderBy(p => p.Name)
              .First();
      using (var stream = datafile.OpenText())
      {
        var flights = JsonConvert.DeserializeObject>(stream.ReadLine());
        return flights;
      }
    }
  }
}

So what does this do? Well, basically look for a json file with a HH_mm_ss.json name. I have recorded a 10 hour loop from 8am to 6pm and this algorithm makes sure the data files are served up in the right order. It takes the first file whose name is ‘larger or equal’ (i.e. represents the same or a later time) than the actual time.

And that’s it for this very humble start. Publish it to Azure somewhere, and note the URL. You cannot test it directly in your browser because it’s an Azure App Service. If you run the service and  hit http://localhost:59541/api/flightdata in your browser you get {"message":"No API version was specified in the request, this request needs to specify a ZUMO-API-VERSION of '2.0.0'. For more information and supported clients see: http://go.microsoft.com/fwlink/?LinkId=690568#2.0.0"}

You can test it using Fiddler though by using the composer:

image

The important thing is adding ZUMO-API-HEADER:2.0.0 to the headers, then hit execute. In the session list to the left you will see then

image

And on the right hand side below the composer a lot of JSON:

image

That is, if you select TextView. Right. Our service is now working. We can now move on to make a real HoloLens application that read this stuff and transforms it into airplanes moving through your room.

Code, as always, can be viewed on and downloaded from GitHub.

28 September 2016

Converting lat/lon coordinates to local coordinates for HoloLens apps

This is going to be a bit of a theoretical story, but I feel it’s a necessary as a precursor to my promise to explain in detail how I made the AMS HoloATC app. So bear with me.

One of the challenges when it comes to showing geo-positioned data in a HoloLens is that is most of this type of data comes in Lat/Lon (and optional Alt – for altitude) format. The UWP Map component knows how to handle it, but if you want to use this kind of data in a HoloLens you will need some way to convert to the X-Y-Z system Unity uses.

Now there are two approaches. The first one is to go for the full 3D experience and you project the coordinates relative to a globe. Although is awesome for demoes, it also has the drawback that it may not be easy to see relative heights over larger distances in what is in essence a curved plane. In my app I take the Netherlands – an area of 300 by 200 km, the largest part more or less North-South, and condense that by a factor of 15000 to about 20 x 13 meters. The curvature of the Earth would cause the airplanes to rise from the edges of the view, and then come down again as they head for approach and landing.

The second approach is to pretend the Earth is flat in the Netherlands (which is kind of true, but and in a different way-people who have ever visited us will understand why) and use a tangential plane that hits the Earth on a certain spot. This is the approach I took. For the spot where the plane hits the Earth I took what according to Google Maps is the center of Amsterdam airport (aka Schiphol) -  52.307687, 4.767424, 0 (lat/lon/alt)*. A very useful site for finding lat/lon coordinates of places on Earth is this one. Click on the map or enter a name and presto.

Projecting an airplane to a globe or this tangential plane requires more math than I know. Although I worked in GIS for over 20 years I was never formally trained for it that and I was never a math wizard anyway. Fortunately, some guy called Govert van Drimmelen – I presumed him to be Dutch as well based on his name, but he is actually from South Africa – has posted a GitHub gist that does exactly what you need. It actually supports both approaches (projection to a globe and to a tangential plane). I made a fork of it that only gets rid of the missing Util.DegreesToRadians, the tests and other stuff that is not used, but is essentially the same.

But there are still two caveats, and they both have to do with altitude. I put the center of Schiphol on the 0,0,0 position in Unity’s coordinate system, and then wrote this test code:

double x, y, z;
GpsUtils.GeodeticToEnu(52.307687, 4.767424, 0, 52.307687, 4.767424, 0, out x, out y, out z);
Assert.IsTrue(x == 0 && y == 0 && z == 0);

The first coordinate is the coordinate I want to project, the second one is the place where the tangential plane is hitting the ground. If I put both at the same place, the method should return 0,0,0. And indeed it does. Hurray.

Now let’s head over to the city of Leeuwarden, some 121 km North-East from Schiphol (this is a useful simple website for measuring distances) at lat, lon = 53.201233, 5.799913. As I have no idea what to expect, let’s first print out the results before testing

GpsUtils.GeodeticToEnu(53.201233, 5.799913, 0, 52.307687, 4.767424, 0, out x, out y, out z);
Debug.WriteLine($"{x},{y},{z}");

Result: 68991.988451593,99923.1412132109,-1155.45361490022. The output is apparently in meters. Nice. So… 100km to the North and 69km to the West. If you do Pythagoras on those first two values, you get indeed about 121000. Awesome. So that seems to work as well. But… 1155 down? Still the curvature of the Earth, I guess. Apparently when you go 121 km to the North-East, you end up 1155 below the horizon of someone standing on the original place. I think. So when I project my plane I use X for X, Y for Y, and the original altitude for Z. But this leads to another problem.

First of all, one unit is a meter in a HoloLens (or appears to be – let’s not get metaphysical). If I were to use X/Y/Alt directly, an airplane approaching from the direction of Leeuwarden at 3km would be some 121km from my point of view – and at 3km height. Even if I used 1:1 models it would be invisible. That does not help giving an Air Traffic Controller (ATC) a nice 3D view of the area around his or her airport of condern. So I divide X and Y by 15000. Result for an airplane about Leeuwarden is this: 4.59946589677287,6.6615427475474

So an airplane that is in real life about 121km from me appears about 7 meters from me, forward and quite a bit to the right. As airplanes on approach for an airport (at least around Schiphol) are moving within 20km around the airport this makes the busiest part of air traffic happen in an apparent space of about 2.5x2.5 meters. That looks good to me. But if I would use the same scale factor on the height, and airplane flying 3km would be 20cm from the ground. At final approach, say at about 500m, it would be a mere 3cm from the ground. At 10km – cruise altitude, and not particularly interesting to and ATC - it would still be a little short of 70cm. Our poor ATC would have to look very carefully to see height differences between aircraft on final approach ;). So I opted to scale down the height considerably less – by dividing that by only 2000. That puts an aircraft on 500m at 25cm, on 3km it is at 1.5m, and 10km is at 5m – still well within visual range, but literally flying way over your head, which is exactly what you want, as it is not of immediate concern for an ATC handling the arrivals and departures on an airport. The only drawback is that aircraft seem to climb at impossible steep trajectories when taking off, but I think that’s ok.

So this is how I convert and transform aircraft flight data into what I think a format and space that makes it usable for an ATC wearing a HoloLens. The fun part of it is that when I hook up the app to live data and put Schiphol to the side of the room, the city where I live is more or less where the living table is. It’s pretty awesome to see airplanes coming from Schiphol and moving over that table – because in certain conditions, and when I open a window, I can actually hear the rumble of engines of the actual airplane outside when it passes over my house at 3km height ;)

As I wrote earlier, a very theoretical and perhaps even dry piece of text. I hope it’s useful for other people thinking about using geo-positioned data in HoloLens. I am still a GIS nut at heart, although I don’t work in GIS anymore. I wonder if other people maybe have better approaches.

*Technically that is not correct - Schiphol is about 4.5 meters below sea level. Do not be alarmed. We have excellent dunes, dams, and other things to keep the wet bit where it belongs, i.e. not where we live. That is, for the time being ;)

24 September 2016

Sharing download links to (hidden) HoloLens apps

The Windows store has a very neat feature. You can send out direct http links to people that, when entered, show and app directly in the web version of the store, with a neat button next to it to initiate install. For instance, if you hit this URL: https://www.microsoft.com/store/apps/9NBLGGH08D4P

It will take you directly to my app Map Mania.image

Even more handy is that this also works with hidden apps, so you can submit early versions of your app to the Store as hidden - and only hand out the link to a limited number of people. The store has more advanced methods for distributing betas these days, but as a low friction and easy way to send your POCs to customers this direct link feature is still very useful.

Unfortunately, this little trick does not work for HoloLens. For instance, my very first HoloLens app in the Store - “AMS HoloATC” - is accessible via URL: https://www.microsoft.com/store/apps/9NBLGGH52SZP

It will actually show you the app, but it will also say “This app does not work on your device”. Even on a HoloLens.

image

The solution for this is pretty simple – don’t use the http link, but use a store protocol link. Thus, you enter in Edge: ms-windows-store://pdp/?ProductId=9NBLGGH52SZP

And this will open the Windows Store App at the right place. And a button to install the app:

image

So you simply paste the product id behind “ms-windows-store://pdp/?ProductId=” and you can once again share links to selected audiences.

Credits go to my fellow MVP Tom Verhoeff who suggested trying this in an online conversation this afternoon, when I wanted him to try and download my app to see if it was available already. Incidentally, feedback on the app is also appreciated. In it’s current form it’s a one man spare time project. A video will appear shortly, and I will also document in detail how it’s built. Stay tuned.

09 September 2016

How shipping an UWP app update can make your app unavailable

First of all – don’t do this. You might regret it dearly.  

One might consider the fact that this is possible at all to be a bug in the Store. For the moment I am just operating on the assumption that I, a Windows Development MVP, actually managed to mess up my best paying app’s availability by being distracted and not reading the wording in the submission carefully. The sole purpose of this little blog post is to prevent you falling into the same trap.

I happily created a new version of my app now supporting the Anniversary Update, so it would be available on all clients (most notably the XBox One!) In the package page, for some reason I misread the line next to the top checkbox:

image

It says, now in gray print because the submission is already done:

“Let Microsoft decide whether to make this app available to any future device families”

The key error I made here was missing the word future. I had played a little with the check boxes above the platforms and then I noticed the text above, got distracted for some reason, misread it, and unchecked all the boxes thinking “better let Microsoft handle this choice”.

Wrong. Very wrong. Microsoft handles future device families, not current device families. Set the checkboxes like this – and what you end up with is a submission that is not eligible for any of the mentioned devices. And it says so if you read the legend below the package. What struck me in hindsight as odd is that the app was certified and published without a hitch with what might be considered as a completely senseless set op options. Anyway, the net result was - when you tried to search in from the store, it never showed up, and if I used the direct link ($0.99, free trial included, thank you for supporting your faithful developer) it said, in the browser:

"This app does not work on your device"

On every device.

Fortunately the good people of the Windows Store were nice enough to point out my error, so I resubmitted (just the same package, just all checkboxes checked now!). So this is how a submission is supposed to look, and it will look that way if you don’t mess with those checkboxes to begin with:

image

Then the Store Team still had to do something to boot my previous submission out of the queue. When that was done, the app became available again. After five days of absence.

So I guess I stumbled upon an edge for which case the people of the Windows Store could not even imagine some stupid enough to actually stumble upon. ;) Quite a sobering experience for me, both as a user and a developer – even when your users are intelligent people. somehow, some way they will find a way to click on the wrong button and mess up. Usually I am on the other side of the fence. I will never say again “how can anyone be so stupid to do XYZ” because th8ings like this happen.

This is not the proudest article of my blog, but I figured that if I could fall into this trap, there is a remote possibility other people would do so as well. Bottom line: be careful with these checkboxes, read carefully what they mean, and don’t get distracted during a submission ;)

10 August 2016

Why servicing UWP IoT apps via the store is such a Big Deal

In the past I have been dealing with IoT equipment made by a manufacturer that shall remain nameless here, but their solution was - like a lot of IoT solutions are today - based on Linux. Now granted, they had a quite nifty data exchange option via LoRa meshing. But updating both firmware and apps was a nightmare. You were constrained to your own network, so pushing out updates was your own responsibility, you had to do that per (sub) network, one by one, app by app.

Now this was (semi) professional sensing equipment, not intented for use by Joe and Jane Sixpack. The stuff that actually can be purchased by Joe and Jane is even in more dire straits. See for instance this horror story about smart locks. Or actually, dumb locks, as it turns out

Now first of all, a lot of these manufacturers are at fault for delivering essentially insufficient safe equipment. What's even worse is that they refuse to fix it. But in the long run, they are actually right about updating the lock software. It has very little sense, as most of the users won't update the lock (or whatever smart device they may have purchased anyway), either because they don't know how to do it, or because they rather watch the Olympics or some other sports event du jour in stead of reading obscure websites about security to keep up to date on the status of their smart lock, light bulb or whatever other gadget they bought (or got from a well intending friend or relative).

The only solution to this, of course, is that both the lock software itself and the firmware could be serviced remotely, without requiring the user to do something. This would of course require some kind of secure communication protocol, centrally guarded... kind of like how a computer or a phone and it's apps are updated. And wouldn't you know it, that is exactly what Microsoft are doing. Rather too quietly in my humble opinion. Maybe because it’s still in preview. But this is a big deal, and I think it deserves a lot more fanfare.

Windows 10 IoT Core can already update itself, so whenever Microsoft adds new features or improves overall security and stability, the base software can be updated without affecting what is running on top of it. Now by making the apps running on it servicable as well, Microsoft are providing the ultimate solution for making IoT devices servicable remotely and securely, without the user having to do anything.

Drawbacks? What if your lock is just about rebooting when you want to go out (or in)? And then there's the age old "quis custodiet ipsos custodes" - who guards the guards? You (and manufacturers) will have to decide whether or not they want to trust Microsoft - a company that has decades of security expertise, a enormous cloud infrastructure, and basically runs on selling trust - or just hope some random hardware dude does a better job and do it right the first time, because they cannot update their stuff once they have sold it.

I think the time is ripe for Smart IoT, and I applaud Microsoft for making this move. I once dreamed about it in a closed conversation with some Microsofties, and now it's coming true. Not doubt my dreaming has nothing to do with it, but the fact that it does come true indeed, is not the less awesome

The second blog post in a row without any code attached to it. My apologies, I will return to code next time ;)

03 August 2016

Why you should update your apps to UWP

Woe is us

No code this time, but a kind of a rant. Or some advice. Whatever you want to call it.

So we all saw the stories. Several pundits all over the world claim Windows Phone is going down, the Windows Store is going nowhere, it’s all going bust, blah blah blah doom and gloom, woe is us. I must admit I’ve been lazy converting my apps from Windows 8.x / Windows Phone 8.x to UWP too. Not out of defaitism, but, well, I got distracted. And for good reason too – there’s now so much fun stuff to play with. First there was IoT Core and some great IoT Azure features, then came HoloLens and UWP on XBox One - it’s hard to set priorities. Especially if you suffer from the shiny new toy syndrome like me ;).

A little confession

So far I have updated only one app to UWP, and submitted it to the store – good old Map Mania. It was my first serious Windows Phone application, dating back to the Windows Phone 7 days; it made it’s transition to 8, 8.1 and was languishing in the store. You can buy it for €0.99, although buying apps is an outdated model in these freemium days, right? And it was not even my most downloaded app – a little over 8000 downloads does not even come close to my more-or-less hit 2 Phone Pong. So why did I chose to update this app specifically? Well, mainly because I use it myself. It’s ability to show Open Street Maps is a great boon when making hikes in more rural places of Europe where the wife and me tend to go on holiday (although it was also great in finding spots around Rome). In addition, I think its ability to show WMS maps is also fun, a throwback to my years as a GIS programmer. And there’s sentimental reasons as well. Anyway, May 11th 2016 Map Mania Universal passed certification. Mission accomplished. I announced its existence with one tweet and forgot about it – because a HoloLens was on it’s way. That is why I am an engineer, not an entrepreneur– I know nothing of marketing, nor am I particularly interested in it.

Money talks. Numbers too

Now three months in, I browsed around some new Dev Insiders Pages on the Dev Center, and found these rather unexpected numbers in the payout pages:

image

Apparently, for every copy of Map Mania for Windows Phone 8.x, I am selling a little over 1.4 UWP copies. But well, ho hum, that’s nice. It’s not exactly breaking the bank.

I am going to share another number with you. Not one that I am very proud of, but what the heck:

image

The point is, look at the latest payout date. June 2015. In fourteen months I have sold for like €10 Map Mania 8.x. copies. But in three months I have sold UWP copies for an amount of  €14.69 . Ergo: I net about 71 cents per month on 8.x, and €4,90 per month on the UWP app. That’s almost seven times as much. It’s still quite not time to call the boss and give my month’s notice, but still - seven times as much. And these are new users - because if you upgraded from an older version, you keep owning it.

What the [redacted]?

How is possible in the light of all the doom and gloom stories? If I check the new download reports I see quite a few Windows 10 mobile acquisitions, a little less tablet acquisitions – but both of those are outnumbered by a bucket load of PC acquisitions. Whatever “PC” may be these days – since Surface saw the light of day, the borders between a laptop and a tablet have become quite hazy.

I’ve been discussing this on Slack with a few people, and with my fellow MVP Ginny Caughey, and we think there are apparently three things at work

  • Relative small store = relative high visibility
  • The huge number of Windows 10 on PC installs is apparently kicking in
  • Those new users are apparently willing to put down money.

Long story short

Update your apps! There is life (and money) in the UWP market. Learn new skills, earn a few bucks, and who knows, maybe you will sell an app to a HoloLens user. But an ‘ordinary’ PC user’s euros, dollars or whatever are currency too, right? There quite a lot more of those.

…and they are willing to pay, apparently.