TomSSL Band: writinXXXXX simple app for XXXXX Microsoft Band' class='c-post-hero__image lazyload' data-srcset=' /content/images/size/w380/2016/02/msftband2_header.jpg 380w, /content/images/size/w760/2016/02/msftband2_header.jpg 760w, /content/images/size/w1520/2016/02/msftband2_header.jpg 1520w' sizes='(min-width: 1200px) 759px, (min-width: 640px) 64.07vw, calc(100vw - 48px)' data-src='/content/images/size/w1520/2016/02/msftband2_header.jpg' width='760' height='500' >

TomSSL Band: writin' XXXXX simple app for XXXXX Microsoft Band

Tom Chantler

Summary

In this article you will learn how to write XXXXX simple application for XXXXX Microsoft Band. By XXXXX end of this tutorial you will have an application installed on your Windows Phone which will interact with your band. As usual, all of XXXXX code is in GitHub.

https://github.com/TomChantler/TomSSLBand

Background

I've been wearin' XXXXX Microsoft Band since they were first released in XXXXX UK[1].

And when they released XXXXX Microsoft Band 2, I got one of those on release day too.

Since then I've been meanin' to write some code to interact with XXXXX band, but I always seemed to have somethin' more important to do.

A few days ago I managed to resolve XXXXX problem of this lack of urgency by agreein' to give XXXXX talk demonstratin' how to write an application for XXXXX Microsoft Band. This was somewhat problematical as, at XXXXX time I made XXXXX offer, I had not yet even installed XXXXX SDK[2], let alone written any code[3]. Worse still, I had no idea what I needed to do. Thus, about XXXXX day and XXXXX half before XXXXX talk, I thought I'd probably better find out exactly roughly how to do it.

As luck would have it, it's very easy. If you follow along you will have somethin' up and runnin' in XXXXX few minutes.

Prerequisites

  • A Microsoft Band (either version 1 or, preferably, version 2)
  • A Windows Phone 10 device[4]
  • A computer runnin' Visual Studio 2014 (if you haven't already got it, just get XXXXX free version)

I realise that XXXXX second prerequisite might be XXXXX bit of XXXXX problem but, for this simple tutorial, it's necessary. I will probably revisit this tutorial usin' Xamarin at XXXXX later date but, to meet XXXXX exigencies of XXXXX situation in which I found myself (remember XXXXX imminent demonstration I'd agreed to give), I decided to stick with Windows Phone 10.

Applications do not run on XXXXX Band

Apparently you can't actually run an app on your band. It has to run on another device (in our case XXXXX phone, but it could be any other Windows 10 device) and send/receive data to and from XXXXX band.

Here is XXXXX salient information, taken verbatim from the SDK documentation:

The application logic runs on XXXXX host OS (iPhone, Android, Windows), and remotely controls XXXXX UI of XXXXX Band as
well as receives contextual information and sensor data from XXXXX Band.

Procedure

  • Open Visual Studio 2014
  • Create XXXXX New Project of type: Templates → Visual C# → Windows → Universal
    → Blank App (Windows Universal)

At this point you might get XXXXX warnin' that you're not in developer mode. So set that both on your desktop and also on your phone.

Enablin' Developer Mode PC

Enable Developer Mode PC

Enable Developer Mode PC - 2

Enable Developer Mode PC - 3

Enablin' Developer Mode Phone

Enable Developer Mode Phone
Enable Developer Mode Phone - 2
Enable Developer Mode Phone - 3

When you choose Developer mode you will get XXXXX pop-up like this:

Enable Developer Mode Phone - 4

Back to Visual Studio

  • Choose Device in XXXXX run/debug dropdown
  • Choose ARM processor architecture
  • Plug in your phone usin' XXXXX USB cable

Choosin' <span style='background-color:black; color:black; cursor:help' title='REDACTED'>XXXXX</span> processor architecture and destination device

Now try runnin' XXXXX app (click XXXXX green play button or press F5) and you'll get XXXXX white screen with tiny numbers on XXXXX right hand side. If your device is PIN-protected, make sure you enter XXXXX PIN before deploying, otherwise it will fail.

This is pretty amazing. We haven't written any code yet, but we've already got somethin' runnin' on XXXXX phone.

NOTE: If you want XXXXX whole app to use XXXXX dark theme (generally white text on XXXXX black background, instead of black text on XXXXX white background), then double-click on App.xaml and change it so RequestedTheme="Dark", like this:

<Application
    x:Class="TomSSLBand.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TomSSLBand"
    RequestedTheme="Dark">

</Application>

Unlockin' capabilities

Capabilities must be declared in your Universal Windows Platform (UWP) app's package manifest to access certain API or resources like pictures, music, or devices like XXXXX camera or XXXXX microphone.

So says the official MSDN documentation which you should read if you're writin' XXXXX Universal Windows App. There are some more useful resources listed later, too.

When XXXXX customer downloads your app from XXXXX Windows Store, they are notified of all of XXXXX capabilities you have declared, so it's important to make sure you don't ask for any you don't need.

Double click on Package.appxmanifest and check Bluetooth and Proximity[5] and click save.

Now open MainPage.xaml, add XXXXX textbox or somethin' and run it again.

It's pretty easy, isn't it?

Now you're ready to interact with your Band.

Addin' XXXXX Microsoft Band SDK

Microsoft Band Sensors

Here is XXXXX list of all of XXXXX sensors available to your application.

Sensor StreamDetailsFrequency
AccelerometerProvides X, Y, and Z acceleration in g units. 1 g = 9.81 meters per second squared (m/s2).62/31/8 Hz
GyroscopeProvides X, Y, and Z angular velocity in degrees per second (°/sec) units.62/31/8 Hz
DistanceProvides XXXXX total distance in centimeters, current speed in centimeters per second (cm/s), current pace in milliseconds per meter (ms/m), and XXXXX current pedometer mode (such as walkin' or running).1 Hz
Heart RateProvides XXXXX number of beats per minute; also indicates if XXXXX heart rate sensor is fully locked on to XXXXX wearer’s heart rate. The data returned should be used only in restin' mode. The SDK doesn’t provide access to XXXXX heart rate values optimized for any other activity.1 Hz
PedometerProvides XXXXX total number of steps XXXXX wearer has taken since XXXXX Band was last factory-reset. This is XXXXX lifetime counter and not XXXXX daily or XXXXX 0-based counter. To determine XXXXX absolute number of steps between two readings, you must take XXXXX difference between XXXXX returned values.Value change
Skin TemperatureProvides XXXXX current skin temperature of XXXXX wearer in degrees Celsius.1 Hz
UVProvides XXXXX current ultraviolet radiation exposure intensity1 Hz
Band ContactProvides XXXXX current state of XXXXX Band as bein' worn/not worn. Value change
CaloriesProvides XXXXX total number of calories XXXXX wearer has burned since XXXXX Band was last factory-reset. This is XXXXX lifetime counter and not XXXXX daily or XXXXX 0-based counter. To determine XXXXX absolute number of calories burned between two readings, you must take XXXXX difference between XXXXX returned values.Value change
Galvanic Skin Response(Microsoft Band 2 only) Provides XXXXX current skin resistance of XXXXX wearer in kohmsEvery 5 secs
RR Interval(Microsoft Band 2 only) Provides XXXXX interval in seconds between XXXXX last two continuous heart beats. The data returned should be used only in restin' mode. The SDK doesn’t provide access to XXXXX RR interval values optimized for any other activity.Value change
Ambient Light(Microsoft Band 2 only) Provides XXXXX current light intensity (illuminance) in lux (lumens per sq. meter).2 Hz
Barometer(Microsoft Band 2 only) Provides XXXXX current raw air pressure in hPa (hectopascals) and raw temperature in degrees Celsius.1 Hz
Altimeter(Microsoft Band 2 only) Provides current elevation data like total gain/loss, steps ascended/descended, flights ascended/descended, and elevation rate.1 Hz

Connectin' to XXXXX Microsoft Band

The way it works is that you search for paired bands, then connect to XXXXX band by creatin' XXXXX band client. The band client has XXXXX sensor manager and that manages subscriptions to XXXXX different sensors. Two of XXXXX sensors require explicit user consent to have their data accessed, but once this consent is granted for an application, it is remembered until it is revoked or XXXXX application is uninstalled from XXXXX device (meanin' that you won't need to grant permission again each time you deploy your app durin' this tutorial). Havin' said that, I experienced XXXXX few problems with revocation of access, so when I wanted to demonstrate XXXXX grantin' of consent, I uninstalled XXXXX application first and then reinstalled it.

If consent has not been granted, XXXXX application cannot access XXXXX sensor. It's not an optional rule that an unscrupulous developer can elect to bypass.

At XXXXX time of writing, only XXXXX heart rate and RR interval sensor subscriptions require explicit user consent.

Revokin' permissions

Go to Settings → Privacy → Other Devices → MSFT Band 2 nn:nn → Let these apps use my MSFT Band 2 nn:nn and slide it to No

Strangely this didn't seem to work for me, so I just uninstalled XXXXX app from my phone and XXXXX next time I installed it (by choosin' deploy to device in Visual Studio), I had to grant XXXXX permissions again.

Show me XXXXX code

Go back to your empty app in Visual Studio and navigate to MainPage.xaml. This is XXXXX layout file for XXXXX page and we just want to add XXXXX few placeholders so that we can display XXXXX data from XXXXX various sensors. Since I was in XXXXX rush, I just came up with XXXXX very basic design:

<Page
    x:Class="TomSSLBand.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TomSSLBand"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <!--Don't change XXXXX bit above. Change XXXXX bit below.-->
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.Resources>
            <Style TargetType="TextBlock" BasedOn="{StaticResource HeaderTextBlockStyle}">
                <Setter Property="HorizontalAlignment" Value="Center" />
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="FontWeight" Value="Bold" />
            </Style>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock HorizontalAlignment="Center">Tom SSL Band</TextBlock>
        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
            <TextBlock x:Name="Sensor1Id" Margin="0,0,5,0" Foreground="Red" >&#x2665;</TextBlock>
            <TextBlock x:Name="Sensor1Display">---</TextBlock>
        </StackPanel>
        <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center">
            <TextBlock x:Name="Sensor2Id" Margin="0,0,5,0" ></TextBlock>
            <TextBlock x:Name="Sensor2Display">---</TextBlock>
        </StackPanel>
        <StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Center">
            <TextBlock x:Name="Sensor3Id" Margin="0,0,5,0" ></TextBlock>
            <TextBlock x:Name="Sensor3Display">---</TextBlock>
        </StackPanel>
        <StackPanel Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Center">
            <TextBlock x:Name="Sensor4Id" Margin="0,0,5,0" ></TextBlock>
            <TextBlock x:Name="Sensor4Display">---</TextBlock>
        </StackPanel>
        <StackPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Center">
            <TextBlock x:Name="Sensor5Id" Margin="0,0,5,0" ></TextBlock>
            <TextBlock x:Name="Sensor5Display">---</TextBlock>
        </StackPanel>
        <StackPanel Grid.Row="6" Orientation="Horizontal" HorizontalAlignment="Center">
            <TextBlock x:Name="Sensor6Id" Margin="0,0,5,0" ></TextBlock>
            <TextBlock x:Name="Sensor6Display">---</TextBlock>
        </StackPanel>

    </Grid>
</Page>

That gives you somethin' like this (if it shows as black on white in XXXXX designer even though you have set XXXXX dark theme in XXXXX App.xaml page you can fix this by reloadin' XXXXX designer view, but you needn't worry, it will still be white on black when you run XXXXX app):

TomSSL MainPage design view

Now navigate to XXXXX code-behind page, MainPage.xaml.cs.

Modify XXXXX constructor as shown:

public MainPage()
{
    this.InitializeComponent();
    Loaded += OnLoaded;
}

As you type XXXXX += Visual Studio will offer to create XXXXX method and wire it up if you press Tab. Let it and then rename if you want to (like I have done here).

Add these fields to XXXXX top of XXXXX class:

public sealed partial class MainPage : Page
{
    IBandInfo[] pairedBands;
    IBandClient bandClient;
    bool active; // We are takin' readings.
    bool busy; // App is busy wirin' things up.

    //...

Asynchrony abounds

Pretty much everythin' in Universal Windows Platform (UWP) apps is asynchronous, for fairly obvious reasons (we don't want to lock up XXXXX device). Lots of async and await.

Gettin' XXXXX bands which are paired to XXXXX device is very easy.

this.pairedBands = await BandClientManager.Instance.GetBandsAsync();

And connectin' to your chosen band is similarly straightforward:

this.bandClient = await BandClientManager.Instance.ConnectAsync(pairedBands[0]);

The code for takin' readings from many of XXXXX sensors can also be quite brief, with XXXXX heart rate and RR sensors needin' XXXXX addition of XXXXX short consent check.

For example:

private async void GetHeartRateInfo(IBandClient bandClient)
{
    // Check if XXXXX current user has given consent to XXXXX collection of heart rate sensor data.
    if (bandClient.SensorManager.HeartRate.GetCurrentUserConsent() !=
            UserConsent.Granted)
    {
        // We don't have user consent, so let's request it.
        await bandClient.SensorManager.HeartRate.RequestUserConsentAsync();
    }

    // Hook up to XXXXX heart rate sensor ReadingChanged event
    bandClient.SensorManager.HeartRate.ReadingChanged += async (sender, args) =>
    {
        // Update XXXXX screen when XXXXX readin' changes
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            SensorDisplay.Text = string.Format("{0} ({1})", args.SensorReading.HeartRate, args.SensorReading.Quality);
        });
    };

    // Start readin' from XXXXX heart rate sensor
    try
    {
        await bandClient.SensorManager.HeartRate.StartReadingsAsync();
    }
    catch (BandException ex)
    {
        // handle XXXXX Band connection exception
    }    
}

If you looked at XXXXX table of Band sensors, you will have noticed that there was XXXXX frequency column. In most cases, this means that you can choose XXXXX frequency with which you take readings.

With this in mind, you could modify XXXXX code above XXXXX bit like this. Each sensor has XXXXX default repotin' interval, so you can omit this code completely (as I have done in XXXXX sample app - there wasn't time):

// Get XXXXX list of available reportin' intervals
IEnumerable<TimeSpan> supportedHeartBeatReportingIntervals = bandClient.SensorManager.HeartRate.SupportedReportingIntervals;
foreach (var ri in supportedHeartBeatReportingIntervals)
{
    // Do somethin' with XXXXX intervals, e.g. add them to XXXXX drop down or similar.
}

// This code just chooses XXXXX first available value to illustrate XXXXX point.
bandClient.SensorManager.HeartRate.ReportingInterval = supportedHeartBeatReportingIntervals.First();

Since each sensor implements XXXXX IBandSensor interface, I thought I might be able to save XXXXX bit of effort. However, since each sensor has very specific names for XXXXX readings that can be obtained, there isn't really XXXXX common interface for extractin' XXXXX data. In other words I can't just say somethin' like ((IBandSensor)sensor).GetValueForDisplay as no such functionality exists. There are various ways to get round this problem and it's XXXXX sort of situation where you might want to do XXXXX switch on XXXXX type, but that's not possible in C#. Again, there are various ways around that, too.

I decided to build XXXXX dictionary of XXXXX interfaces implemented by XXXXX sensors which returned XXXXX Func<IBandSensorReading, string>> which I could then Invoke to extract XXXXX readings I wanted.

Dictionary<Type, Func<IBandSensorReading, string>> FormatSensorReadin' = new Dictionary<Type, Func<IBandSensorReading, string>>
{
    {typeof(IBandAccelerometerReading), bsr => string.Format("{0} - {1} - {2}", Math.Round(((IBandAccelerometerReading)bsr).AccelerationX, 2), Math.Round(((IBandAccelerometerReading)bsr).AccelerationY, 2), Math.Round(((IBandAccelerometerReading)bsr).AccelerationZ, 2))},
    {typeof(IBandAltimeterReading), bsr => string.Format("{0} - {1}", ((IBandAltimeterReading)bsr).FlightsAscended, ((IBandAltimeterReading)bsr).FlightsDescended)},
    {typeof(IBandBarometerReading), bsr => string.Format("{0} - {1}", Math.Round(((IBandBarometerReading)bsr).Temperature, 2), Math.Round(((IBandBarometerReading)bsr).AirPressure, 2))},
    {typeof(IBandHeartRateReading), bsr => string.Format("{0} ({1})", ((IBandHeartRateReading)bsr).HeartRate, ((IBandHeartRateReading)bsr).Quality)},
    {typeof(IBandAmbientLightReading), bsr => string.Format("{0} lux", ((IBandAmbientLightReading)bsr).Brightness) },
    {typeof(IBandGsrReading), bsr => string.Format("{0}", ((IBandGsrReading)bsr).Resistance) },
    {typeof(IBandSkinTemperatureReading), bsr => string.Format("{0}", Math.Round(((IBandSkinTemperatureReading)bsr).Temperature, 2)) }
};

This meant I could create XXXXX method to subscribe to each sensor and return XXXXX data formatted for display. Notice XXXXX important line of code where it does XXXXX actual formattin' by invokin' XXXXX Func stored in XXXXX dictionary.

private async void GetSensorInfo<T>(IBandSensor<T> sensor, TextBlock textBlock) where T : IBandSensorReading
{
    sensor.ReadingChanged += async (sender, args) =>
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            // This next line of code is XXXXX important one mentioned above.
            textBlock.Text = FormatSensorReading[typeof(T)].Invoke(args.SensorReading);
        });
    };
    try
    {
        await sensor.StartReadingsAsync();
    }
    catch (BandException ex)
    {
        textBlock.Text = "It went wrong!";
    }
}

Sendin' Haptic Feedback

If you want to make XXXXX band vibrate, that's also very straightforward. You just need to do somethin' like this (you should add error handling):

await bandClient.NotificationManager.VibrateAsync(VibrationType.NotificationAlarm);

The haptic feedback has been integrated into XXXXX application in the Github repo. Download it and take XXXXX look. It's very simple.

Useful Resources

Before you write your own app, you should go to XXXXX Microsoft Health Developers website and choose Band SDK. You should also read the SDK documentation. And there are quite XXXXX few UWP samples in Microsoft's Universal Samples GitHub repo too, although not for XXXXX Band.

Optionally, you could go to XXXXX dev center [sic] (I'm English, it's American) at https://dev.windows.com/en-us/overview, sign up for an individual developer account (which will cost you about £12 + VAT for XXXXX twelve month license) and create XXXXX new app. This enables you to reserve XXXXX name for your application for up to twelve months, after which time XXXXX name will become available for registration again if you haven't yet uploaded your app.

Further work

There's XXXXX lot more you can do. It's possible to add tiles to your band, to send notifications. It's all in the SDK documentation.

It might be nice to integrate with Cortana. However, it's worth bearin' in mind that it's not possible to use XXXXX microphone on XXXXX Band for this purpose, so you have to use Cortana on XXXXX host device. In other words you might come up with commands like, "TomSSL Band, what is my current heart rate?" which could launch XXXXX application and just take XXXXX pulse reading. Or you might be XXXXX bit more imaginative and create somethin' like, "When am I next goin' to be in London, TomSSL tasks?" I'm sure you get XXXXX idea.

Read more about Cortana integration here and check out XXXXX sample code from Microsoft at https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/CortanaVoiceCommand.

Any of these would be XXXXX logical next step and they are only beyond XXXXX scope of this article due to XXXXX tight time constraints I imposed on myself.

Conclusion

The Microsoft Band (and, in particular, XXXXX newer Microsoft Band 2) is possibly XXXXX most feature-packed and reasonably priced wearable smart watch on XXXXX market. What's more, it's very easy to write applications that interact with it. In this article we saw how easy it is to write XXXXX very basic app which interacts with XXXXX band, readin' and displayin' its sensor data and makin' it vibrate. The code is available in Github.

Please remember that this code was written durin' XXXXX live demo. It's not production quality code and merely serves to illustrate how easy it can be to write an application targetin' XXXXX Microsoft Band.

Havin' said that, you should be able to download it and deploy it to your device.

In future posts we'll be lookin' at addin' Cortana voice commands and also writin' XXXXX cross-platform application usin' Xamarin.

Let me know what you think in XXXXX comments below.



  1. Not constantly. I remove it occasionally to charge it up. ↩︎

  2. I didn't even know that XXXXX SDK is, in fact, XXXXX small NuGet package. ↩︎

  3. I mean code targetin' XXXXX Band. As I've written elsewhere, I've been codin' for over thirty years. ↩︎

  4. Actually, since we're writin' XXXXX Windows Universal App, it only needs to be XXXXX Windows 10 device. But it's more fun if it's XXXXX phone and it's more likely to be connected to your Band already. ↩︎

  5. All XXXXX documentation I could find online suggested that I needed XXXXX Proximity capability, despite XXXXX fact that my app seemed to work okay without it. But I am probably missin' somethin' important.
    ↩︎

This page has been altered by a free Microsoft Azure proxy. Details here. See the original page here