METAR/TAF: a Garmin Connect IQ Widget for D2™ Bravo

I built a widget.

The D2™ Bravo is Garmin’s second generation”pilot watch,” built on top of the fenix 3 hardware/platform with slightly less functionality of the fenix 3 but with the added bonus of some functionality for pilots (or aviation enthusiasts). The flagship function of the D2 Bravo is the Fly app, which records your flights as an “activity”, displays your route so far on a rudimentary map (but with no base map) and shows you distance and direction to the nearest airports as you fly along. The Start and Back buttons on the D2 Bravo are basically mapped to this functionality, giving you screens for “Direct To” an airport and nearest airports respectively. But you also get a great widget with the D2 Bravo: the METAR widget.

Unfortunately, the METAR widget has some drawbacks for anyone outside of the United States, such as in Canada where you will likely have your watch set up for metric units. You may not have an issue if this is a secondary watch that you use for flying only but if, like me, this is your main timepiece and you use metric day-to-day (for running, hiking and other activities the watch tracks) then using the built-in METAR widget from Garmin causes some grief.

A big problem with software for a global market is localization. In Canada we don’t tend to experience this much given that our software-producing giant neighbour to the south speaks the same main language that we do. So when a product only uses English it’s no big deal. And Garmin has done a great job with languages; my D2 Bravo supports 18 different languages via optionally installed language files. But for a watch with a GPS receiver, compass, barometric altimeter and a thermometer we also have the issue of units of measurement. And while the watch supports metric or imperial units, and allows for configuration of each sensor individually, the watch applies those settings to the aviation functionality of the watch. That seems great, except that with aviation it’s a mixed bag for how things are measured, further complicated by variations by country. In North America, temperature is in celsius, altitude is in feet, wind speed is in knots, barometric pressure is in inches of mercury, distances are in nautical miles and visibility is in statute miles. In Australia and most other metric countries outside of Canada the units for temperature,wind speed and altitude are the same but visibility is in meters and barometric pressure is in millibar. It might seem strange for a metric country such as Canada to still be using imperial units but it’s easier to be consistent with our USA neighbours.

So, back to the problem. The D2 Bravo is my primary watch in that I wear it every day, including for all activities such as running, biking or hiking. And as a Canadian, living in Canada I have my watch configured for metric units. Unfortunately, that means that the aviation functionality uses my metric units for everything. And while it might seem silly to be complaining, reporting the  visibility as ‘4 km‘ when you should be displaying ‘2½ SM‘ is completely foreign to me. And even if you were expecting a metric visibility, it should be displayed as 4000m not the equivalent in kilometres.

After reporting this issue to Garmin, the next release changed the wind speed displayed in the METAR widget from km/h to knots but left everything else the same. The ceiling today is at 1524 metres; ask any pilot if they have any idea what that is in feet, the units that cloud elevation is always reported in (except Russia and China) and you’ll get the same answer: “no idea”. And I don’t have any idea either.

fe90a0c9-a6d5-4f8b-924d-a09386f3eaf4It’s weird how the brain works but it just can’t think in metric when it’s learned aviation in everything but. As a result it was frustrating trying to use the built-in widget and it contributed to making the built-in widget unusable. Perhaps not for everyone, but for it was unusable for me. So I put my technology background to use and, as I said above, built my own widget (based heavily on Garmin’s built-in widget) and made it available for other users. I added in some features I wanted, such as displaying the four nearest aerodromes on the main page, and to maximize appeal for the changes I felt were needed, I added options for anything different from the built-in widget.

If you have a Garmin watch capable of running Connect IQ apps you can download the widget at the Connect IQ Store:

And if you’re interested in more details about the functionality of the widget including the changelog, you can read more on the page dedicated to METAR/TAF that I’ve created.

UTC Digital: a Garmin Connect IQ watch face

I built a watch face.

Following up on a previous post about my initial thoughts on Garmin’s Connect IQ, I dove in and started playing around with watch faces. Garmin’s Connect IQ SDK includes an example analog watch face and the Eclipse plug-in for Connect IQ will setup a simple, working digital watch face when you create a new watch face project.

Working with Connect IQ is remarkably easy. As advertised, the language Garmin created, Monkey C, is a procedural programming language that will be familiar to any C, C++ or Java programmer. It’s simply a matter of learning what classes/methods give you access to what functionality.

A watch face is the most simple of the project types you can build; watch faces have only a single view (typically), don’t interact with any keys or actions and don’t have access to any sensors.

A simple digital watch face might start out like this:

using Toybox.Application as App;
using Toybox.WatchUi as WatchUi;
using Toybox.Graphics as Graphics;

class SimpleDigitalApp extends App.AppBase {
    function initialize() {

    function getInitialView() {
        return [ new SimpleDigitalView() ];
class SimpleDigitalView extends WatchUi.WatchFace {
    function initialize() {

    function onUpdate(dc) {
        var timeInfo =, Time.FORMAT_SHORT);
        var timeStr = timeInfo.hour + ":" + timeInfo.min.format("%02d");
        dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
        dc.drawText(dc.getWidth()/2, dc.getHeight()/2-dc.getFontHeight(Graphics.FONT_NUMBER_MEDIUM)/2, Graphics.FONT_NUMBER_MEDIUM, timeStr, Graphics.TEXT_JUSTIFY_CENTER);

But because a watch face is running all the time the underlying watch OS only calls the onUpdate() method once per minute so as to ensure that battery life is maximized. However, when the watch senses the motion of a user lifting up the watch to look at it, the watch enters “high power” mode, whereby the onUpdate() method is called once per second for a maximum of 8 seconds or whenever the user looks away from the watch, whichever happens first. This then allows you do display the seconds or display other secondary information.

There are a large number of third-party watch faces available on the Connect IQ store; it depends on the watch model but for the D2 Bravo there are 692 of them. Most are okay in that they function but don’t add much value beyond the fancy background (team sport or whatever). Some of the watch faces are fantastic, offering up a neat, at-a-quick-glance view of all the other information available, such as daily steps, distance, calories expended, etc. But with that added functionality comes more complex code, which typically results in slower response when switching to or from the watch face. And sadly, it seems as most of the available watch faces are built with looks in mind and little consideration for code efficiency.

So while watch faces are simple to create, the best ones are the ones that manage to find a nice balance between information displayed and responsiveness. Or, the watch face fills a niche. And it’s the niche category that my watch face fits into.

64b24906-9032-455a-858b-34000b433ea2The D2 Bravo has analog and digital watch faces built-in and both allow for some customization of the background and extra information displayed. One of the extra fields is UTC (commonly referred to as GMT or Zulu time). However, UTC is always rendered in a small font and when I’m in pilot-mode all times are referenced in UTC. I don’t depart at 10:24am local Calgary time, I depart at 1724 UTC (or 1624 UTC when in Daylight Saving Time). So from the time I start planning my flight(s) and filing my flight plans through departure and until some point shortly after arrival all I’m really interested in seeing on my watch in terms of time is UTC.

And that primary interest in UTC is what my watch face “UTC Digital” provides. The large, easy to read at a casual glance font is displayed UTC time, with the UTC date (which could be tomorrow’s date) right above it. And in case a passenger is asking about it, local time is presented in the smaller font right below UTC. For me, it’s the perfect “pilot doing pilot things” watch face.

If you have a Garmin watch capable of running Connect IQ apps you can download the watch face at the Connect IQ Store:

And if you’re interested in more details about the functionality of the watch face, including the changelog, you can read more on the page dedicated to UTC Digital that I’ve created.

Overview of Garmin’s Connect IQ

One of the attractive features of Garmin’s D2 Bravo pilot watch (a derivative of their fēnix 3 model) is the ability to customize the watch via for apps, widgets, watch faces and data fields available on the Connect IQ Store.

Connect IQ is touted by Garmin as “the first-ever open platform for third-party developers to create apps for our [Garmin’s] products” and it allows anyone with some programming savvy to create add-ons for their products, filling gaps (or in some cases, gaping holes) in built-in, default functionality or adding on highly specialized features that may not appeal to the general masses.

I’ve had my D2 Bravo for nine months now and I finally got around to looking into developing with Connect IQ, though I had been thinking about it for the past couple months but had been completely unmotivated to do so because the last thing anyone wants to do is dive into documentation provided by a big company (Garmin has a market cap of about $7.7B as of this writing) – I had visions of the nightmare that was working with PayPal’s API back before Stripe showed up on the payment processing scene. Plus I recalled reading that Garmin had created a new language to go with their Connect IQ API and I detest learning new languages, especially when the language is specific to one particular platform.

As it turns out Garmin did create a new, object-oriented language, called Monkey C, for use with Connect IQ. But the claimed goal of doing so was to make for easier app development on wearable devices by “…letting developers focus more on the customer and less on resource constraints“.

Okay, I was warming up to the notion of learning a new language. And that was made easier by the modern look and wording style in which the developer site for Connect IQ was written. The documentation is casual, fun and easy to read and understand. Perfect. And just when you think you can’t have anymore fun, you come across one of their  funny footnotes.

Functions are the meat[2] of your program.

2. Tofu for the vegetarians, BBQ for Kansans…

But footnotes aside, the programmer’s guide is a software developer’s dream, full of clear descriptions and lots of sample snippets of code. Not at all what I was expecting, and that serves me right for projecting past experiences with big companies and terrible documentation onto Garmin. In any case, what a breath of fresh air; it was like working with the Stripe API again! I’m not sure if this developer honeymoon will last through the first trial project but it’s looking good so far.

Density Altitude in Canadian METAR

Everything is about perspective; there’s that saying “One person’s garbage is another person’s treasure.” And so it is about air. That’s not to say that air is a treasure. Or garbage for that matter. The point is that to most people air is just air. The air might feel cold or warm, dry or wet but for the most part it doesn’t affect them, other than how they might dress for the day and that they need to continue to breath it. But to a pilot, the characteristics of the air have a significant impact on the performance of the aircraft we are flying.

When pilots think of the air, density altitude is (or should be) one of, if not the first, things that comes to mind. Density altitude is the atmospheric reality within which we operate our aircraft. I like to describe it as “the altitude at which the aircraft ‘thinks’ it is operating at.” You could easily argue that there isn’t more critical phases of a flight with respect to density altitude than takeoff and landing when the aircraft is low (to the ground) and slow (relative to cruise speed). And at takeoff the aircraft is also the heaviest it will be.

This is why density altitude is an important factor at airports. Critical aircraft performance metrics are all affected by density altitude, such as the distance required for takeoff and, for aircraft with normally aspirated engines, whether or not the aircraft can climb at a rate required to clear any obstacles. This is why calculating density altitude is a part of proper flight planning; as pilots we need to ensure that the runway is long enough to enable the aircraft to get off the ground and that the runway at our destination is both long enough for us land and then, if necessary, to take off from.

NAV CANADA started including density altitude in METAR for Canadian airports in late 2009, making things that much easier when flight planning. The density altitude is automatically calculated and included in the remarks section of the METAR whenever the density altitude is 200 ft or higher than the aerodrome elevation as noted in NAV CANADA’s Aviation Weather Services Guide [PDF]. For example, here’s a METAR from CYYC today (22-Jun-2016 1900 UTC):

METAR CYYC 221900Z 13006KT 040V220 40SM SCT068 SCT220 BKN300 22/05 A2999 RMK CU3CI1CI1 SLP154 DENSITY ALT 5100FT

The elevation of Calgary International Airport (CYYC) is 3606 feet MSL (height above mean sea level) and calculated density altitude for CYYC is 5100 feet MSL. It may not seem like a big difference but it’s enough of a difference that the takeoff rolls of heavy aircraft will be longer and the climb out will be slower, which is great for any avgeeks as planespotting will be easier since aircraft will be lower for longer.

But back to calculating density altitude. The reported density altitude for Calgary is 5100 feet. Or is it? The answer is a complicated ‘yes’ and ‘no’, leaning much more towards no than yes. Calculating the true density altitude requires four variables: altitude, pressure, temperature and humidity.

The NAV CANADA calculated density altitude that is included in the METAR above is using the dry calculation; that is, a density altitude that does not factor in the humidity. And, in fact, the calculated density altitude in the METAR remarks is also rounded. The actual dry density altitude, based on the above METAR, is 5154 feet MSL. But when we include humidity (using the dew point from the METAR) in the calculation, we get the true density altitude of 5294 feet MSL. This true density altitude, the altitude at which the aircraft will “think it is at,” is almost 200 feet higher than is reported in the METAR, a difference of almost 4%. Although this difference will likely not affect an airliner, where the margin for error is much more forgiving, that 4% difference might be catastrophic for a small [general aviation] aircraft that is close to (or at) gross weight trying to takeoff from a short runway.

If you’re interested in reading more about calculating density altitude, check out the Wikipedia article or the article “Hot, High and Heavy — The Deadly Cocktail of Density Altitude” [PDF] in the July 2012 issue of NOAA/NWS’s The Front.

UPDATE (2016-06-23): NAV CANADA responded that they use the dry calculation so as to share commonality with the United States, which also uses the dry method to determine density altitude. However, NAV CANADA said that there have been internal discussions to “review the calculations to include the dew point” so we may see that change in the future.

Blog Reboot

unnamedIf you’re coming from my previous, out-dated and stale blog then consider this a reboot. Of course, that blog was so stale (the last post was in 2010) that it’s doubtful anyone was still following and anyone that was reading posts likely arrived there directly from Google.

Those old blog posts are all still there, at least for now, but you’ll have to find them via search. There is some interesting stuff there, but the majority is seriously outdated (configuring some old release of Linux) or me babbling on (or worse, complaining) about something without much in the way of solutions.

With this reboot I am loftily aiming to make things better. That is, if I point out a problem, I plan to propose fixes or potential solutions. Where a positive spin can be placed on something, I plan to do so. There is enough negativity to go around already and that negativity and the egregious diatribe is only increasing with tools like Twitter, Facebook or any other easily setup platforms for expressing views and opinions. So you won’t get that negativity from me, or if you do, I plan for that to be the rare exception rather than the rule. Misery may love company but hopefully my positive energy (and lack of negative waves) will make for better reading and maybe even a better world, if only a happier, more positive one. Like I said, potentially lofty goals.