25 February 2015

Displaying Microsoft Band heart rate via Raspberry PI2 using Mono, C#, OWIN and a Windows Phone

Intro – what? WHY?

As regular readers of my blog might have seen, I got myself a Raspberri PI 2 and a Sunfounders sensor kit, and was happily dabbling a little with it. And then suddenly, out of the blue, Microsoft dropped a development kit for the Microsoft Band – and Gerard Verbrugge (Microsoft DX Netherlands) challenged me to make something with it. So I thought to combine a number of gadgets: my Microsoft Band, my Windows Phone and  the Raspberry PI plus some of the stuff from the sensor kit.

I created an application that shows your heart rate with a blinking led connected to the Raspberry PI, with a connected buzzer making sound as well. The LED blinks at the heart rate as reported by the Band, and using the  buzzer, the PI also emits and audible tick-sound as the LED blinks. At low heart rate the LED blinks blue, at medium rate green, and at high rate red:

Raspberry PI2 controlled by Microsoft band at heart rate < 80
Raspberry PI2 controlled by Microsoft band at heart rate > 80

If you crank up the sound, you can hear the ticking of the buzzer at the heartbeat. I think this is one of the coolest stuff I ever made. So, Gerard, challenge accepted. And, IMHO, achievement unlocked ;)

Hardware used

  • 1 Microsoft Band
  • 1 Windows Phone running Windows Phone 8.1
  • 1 Raspberry PI 2
  • 1 4-pins RGB LED from the SunFounders kit
  • 1 3-pins Active buzzer from the Sunfounders kit
  • Breadboard, GPIO cable (connecting PI to breadboard), miscellaneous connecting wires

Don’t give up reading if you don’t have a Band – that part can be simulated and the technique to control hardware peripherals from a WebAPI endpoint is useful on it’s own.

Global setup

How this thing works is, in essence, pretty simple:

  • On the Raspberry PI2 runs a OWIN server hosting
    • a little WebAPI endpoint that accepts heart rate data
    • an endless running task making the LED blink in the right color and cadence, again using Daniel Riches’ wrapper around Gordon Henderson’s wiringPI C library. Once again, with some adaptions.
  • A Windows Phone 8.1 application listening to the paired Microsoft Band’s heartrRate sensor’s events, and posting those to the RaspBerry PI2’s OWIN server upon receiving those.

The demo solution contains 5 projects:

  • A Universal app (with only the Windows Phone project actually used)
  • An project holding the OWIN server
  • A PCL holding two simple classes: an object to post data with to the OWIN server, and a Settings object with some hard coded settings shared over several projects
  • A test project posting a single simulated hearth rate update to the server
  • The WiringPi project – the wrapper around the C library that I used before.

A little PCL

I started a with a little PCL library WebLinker.Pcl that contains only two classes: a simple payload class that I can post from my Windows Phone to my OWIN server:

namespace WebBlinker
{
  public class Pulse
  {
    public int HeartRate { get; set; }
  }
}

and a little class to host some settings

namespace WebBlinker
{
  public static class Settings
  {
    public const string ServiceUrl = "http://192.168.0.188:5001/api/singleblink";
    public const string BaseListenUrl = "http://*:5001/";
  }
}

Rather primitive, indeed. But I want the class that I post as JSON and deserialize from JSON to be shared over client and server, and I don't like magic strings (especially not repeated magic strings) so I tend to gather those in settings classes.

The OWIN server

OWIN is a self hosted web server inside a console app – more or less Microsoft’s answer to nodejs and the like. It’s pretty simple to get started: make a console app, then add the Microsoft.AspNet.WebApi.OwinSelfHost nuget package and that brings everything you need – it’s even simpler than I described in this post. Oh, and add a reference to the PCL while you are at it.

The server contains four parts:

  • A “Program” class with a static void Main – like every console app – kicking and keeping the OWIN server alive
  • A “Startup” class containing the configuration of the OWIN server
  • A “BlinkController” WebAPI controller hosting two methods (one for test, one for the real thing)
  • A “Blinker” class that hosts a thread that does the actual blinking.

The Program class is, well, not very complicated:

using System;
using System.Threading;
using Microsoft.Owin.Hosting;

namespace WebBlinker
{
  class Program
  {
    static void Main(string[] args)
    {
      // Start OWIN host and keep it running
      using (WebApp.Start<Startup>(url: Settings.BaseListenUrl))
      {
        while (true)
        {
          Console.WriteLine("Server still alive...");
          Thread.Sleep(60000);
        }
      }
    }
  }
}

The startup class does the actual configuration and is simple but noteworthy:

using System.Web.Http;
using Owin;

namespace WebBlinker
{
  public class Startup
  {
    public void Configuration(IAppBuilder appBuilder)
    {
      var config = new HttpConfiguration();

      //Use attribute routes!
      config.MapHttpAttributeRoutes();
      appBuilder.UseWebApi(config);
      Blinker.GetBlinker().Start();
    }
  }
}

Although in general I am a fan of Microsoft technology, there are some tiny parts I hate with a vengeance. One of those things is ASP.NET MVC / WebAPI default routing. So whenever I get the chance, I go for attribute based routing. I’d rather like to have the minor chore of having to define all my routes explicitly and know they will be there, in stead of having to deal with inferred routes that might just disappear because someone else adds a route that ‘steals’ or invalidates mine. Just a pet peeve. So I did not include the default routing – I just added a call to MapHttpAttributeRoutes. Now I can control my routes pretty easily in my BlinkController by adding attributes:

using System;
using System.Web.Http;

namespace WebBlinker
{
  public class BlinkController : ApiController
  {
    [HttpPost]
    [Route("api/singleblink")]
    public void PostBlink([FromBody] Pulse pulse)
    {
      Console.WriteLine( "Got update: {0}", pulse.HeartRate);
      Blinker.GetBlinker().HeartRate = pulse.HeartRate;
    }

    [HttpGet]
    [Route("api/helloworld")]
    public string HelloWorld()
    {
      Console.WriteLine("Hello world called");
      return "Hello world!";
    }
  }
}

So now I have an explicitly defined route “api/singleblink” where I can post a Pulse object containing a heart rate to, as well as a simple “api/helloworld” method whose URL I can enter in a browser to see if the WebAPI is up and running at all.

In the “PostBlink” method our Blinker’s HeartRate property is updated. And we come to the heart of the matter – pun intended – as far as the server is concerned. What is important to understand is that the Microsoft Band does not post an update per heartbeat. It posts at a quite regular interval what your current heartbeat is. So in order to let the LED blink at the rate of a heartbeat, we actually have to calculate how often the LED needs to flash. As a matter of fact – the LED does not show your actual heartbeat. It just blinks at the same rate. More or less.

The basic setup of the Blinker is:

using System;
using System.Threading;
using System.Threading.Tasks;
using WiringPi;

namespace WebBlinker
{
  public class Blinker
  {
    private DateTime lastReceivedUpdate = DateTime.MinValue;
    private int heartRate;
    private Task task;

    private Blinker()
    {
      if (Init.WiringPiSetup() != -1)
      {
        GPIO.pinMode(BluePin, (int)GPIO.GPIOpinmode.Output);
        GPIO.pinMode(GreenPin, (int)GPIO.GPIOpinmode.Output);
        GPIO.pinMode(RedPin, (int)GPIO.GPIOpinmode.Output);
        GPIO.pinMode(SoundPin, (int)GPIO.GPIOpinmode.Output);
      }
    }

    public void Start()
    {
      if (task == null)
      {
        cancellationTokenSource = new CancellationTokenSource();
        task = new Task(() => ShowHeartRateBlinking(cancellationTokenSource.Token), 
           cancellationTokenSource.Token);
        task.Start();
      }
    }

    public void Stop()
    {
      if (cancellationTokenSource != null)
      {
        cancellationTokenSource.Cancel();
        task = null;
      }
    }

    private CancellationTokenSource cancellationTokenSource = null;


    private static Blinker blinker;
    public static Blinker GetBlinker()
    {
      return blinker ?? (blinker = new Blinker());
    }

    public const int RedPin = 27;
    public const int GreenPin = 28;
    public const int BluePin = 29;
    public const int SoundPin = 0;
  }
}

On creation, it initializes the pins we are going to use for output (these are GPIO16, GPIO20 and GPIO21 for RGB, and GPIO17 for sound). See picture for connection details. To make things easier for myself, I actually selected a blue wire for the blue pin, a red for the red ping, and green for the green pin ;):WP_20150225_21_02_33_Pro__highres

I am using a different API than before, for this one is – amongst other reasons reasons - a lot simpler to use and does not hinge on C threading. With a caveat I will come to a little later. Important to see is that’s a singleton – there’s only a private constructor and a static method GetBlinker() to create it. Normally you would not get away with this in a web environment, but as OWIN is not hosted in IIS, we actually can use statics here. Scalable? No. But who cares on a mini device like this. Usable? Yes!

So the Startup class initializes and starts the Blinker. That fires of a cancellable task. The Blinker actually has some more code, amongst other the implementation of said task:

private async Task ShowHeartRateBlinking(CancellationToken cancellationToken)
{
  while (!cancellationToken.IsCancellationRequested)
  {
    if (DateTime.Now - lastReceivedUpdate < TimeSpan.FromSeconds(5))
    {
      DoBlink();
      await Task.Delay(60000/HeartRate, cancellationToken);
    }
    else
    {
      await Task.Delay(10000, cancellationToken);
    }
  }
}

public int HeartRate
{
  get { return heartRate; }
  set
  {
    if (value >= 0 && value <= 200)
    {
      lastReceivedUpdate = DateTime.Now;
      Console.WriteLine("Got updated: {0}", value);
      heartRate = value;
    }
  }
}

private async Task DoBlink()
{
  var pin = GetPin();
  GPIO.digitalWrite(pin, 1);
  GPIO.digitalWrite(SoundPin, 1);
  await Task.Delay(50);
  GPIO.digitalWrite(pin, 0);
  GPIO.digitalWrite(SoundPin, 0);
}

private int GetPin()
{
  if( HeartRate < 80) return BluePin;
  return HeartRate < 130 ? GreenPin : RedPin;
}

The ShowHeartRateBlinking actually is an endless loop, that runs while no cancellation is given (or until the OWIN server is simply killed). If the last update was less than 5 seconds ago, it will blink the LED and give a sound pulse, wait for 60000ms divided by the beats per minute – and goes into the next blink. If it does not get updates after 5 seconds, it goes into a 10-seconds polling mode.

The HeartRate property is set by the BlinkController when new data from the Band is posted to the OWIN server’s endpoint, and it’s setter also keeps track of the last update time. The DoBlink method actually does the blinking and the activating of the buzzer (at pin 0). The GetPin method, by means of extra fun, determines what color the LED will flash based upon the posted heart rate: blue for below 80, green for below 130, and red for 130 and up.

In the demo solution there is actually a test project with a test method that posts a single update to the OWIN server. That should at least get you a “Got updated” line on the screen when you run the server. If you run the method multiple times, the LED should start to blink at 75bmp and the buzzer gives a ticking sound.

Adapting the WiringPi wrapper

I already warned about a caveat concerning the API I am using now. Unfortunately, if you compile and run the OWIN server in this stage on the Raspberry PI2, you will get an error. Apparently the WiringPi wrapper is a bit outdated or things have changed for the Raspberry PI2. In the WrapperClass.cs file there’s a class GPIO with on top the following part:

public class GPIO
{
  [DllImport("libwiringPi.so", EntryPoint = "pinModeGpio")] 
  public static extern void pinMode(int pin, int mode);

  [DllImport("libwiringPi.so", EntryPoint = "digitalWriteGpio")]
  public static extern void digitalWrite(int pin, int value);

Studying the original C code, I found that the entry points should be just “pinMode” and “digitalWrite”, not “pinModeGpio” and “digitalWriteGpio”. That was easily fixed:

public class GPIO
{
  [DllImport("libwiringPi.so", EntryPoint = "pinMode")] 
  public static extern void pinMode(int pin, int mode);

  [DllImport("libwiringPi.so", EntryPoint = "digitalWrite")]
  public static extern void digitalWrite(int pin, int value);

If you compile the OWIN server now, and copy the .EXE and all DLLs in the bin/debug directory to your Raspberry PI2, you should now be able to run the server (sudo mono WebBlinker.exe – since settings.BaseListenerUrl is set to “http://*:5001/” it listens to port 5001 on all hostnames assigned to your Raspberry PI, and this means you have to start the webserver as root). It should print “Server still alive…” every 60 seconds on the command line, as well as any heart beat postings coming by.

The Windows Phone app

I hope my Windows Phone friends will forgive me for skimping a little on this, because I really made quite a horrible and above all ugly app. I first installed the Microsoft ASP.NET WebAPI 2.2 Client libraries in it. Then I created this model to actually listen to the Band’s heart rate events and post them to the OWIN server:

using System;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using Microsoft.Band;
using Microsoft.Band.Sensors;
using WebBlinker;

namespace BlinkerPhone
{
  public class BlinkerModel
  {
    public async void SendSimulatedPulse(int value)
    {
      var pulse = new Pulse { HeartRate = value };
      using (var client = new HttpClient())
      {
        await client.PostAsJsonAsync(new Uri(Settings.ServiceUrl), pulse);
      }
    }

    private IBandClient bandClient;

    public async void StartListening()
    {
      var pairedBands = await BandClientManager.Instance.GetBandsAsync();
      if (pairedBands.Any())
      {
        var band = pairedBands.First();
        bandClient = await BandClientManager.Instance.ConnectAsync(band);
        var sensor = bandClient.SensorManager.HeartRate;
        sensor.ReadingChanged += SensorReadingChanged;
        await sensor.StartReadingsAsync();
      }
    }

    public async void StopListening()
    {
      var sensor = bandClient.SensorManager.HeartRate;
      sensor.ReadingChanged -= SensorReadingChanged;
      await sensor.StopReadingsAsync();
      bandClient.Dispose();
    }

    async void SensorReadingChanged(object sender, 
      BandSensorReadingEventArgs<IBandHeartRateReading> e)
    {
      try
      {
        if (e.SensorReading != null)
        {
          var pulse = new Pulse { HeartRate = e.SensorReading.HeartRate };
          using (var client = new HttpClient())
          {
            await client.PostAsJsonAsync(new Uri(Settings.ServiceUrl), pulse);
            Debug.WriteLine("Sending update, pulserate = {0}", pulse.HeartRate);
          }
        }
      }
      catch (Exception ex)
      {
        Debug.WriteLine("Error reading/sending data: {0}", ex);
      }
    }
  }
}

wp_ss_20150225_0001This is not exactly rocket science, and it’s mostly 1:1 nicked from the heart rate sensor sample in the Windows Phone Band SDK samples anyway. If there’s a heart rate event coming in, a new Pulse object is created and posted to the Raspberry PI2’s OWIN Web API endpoint and the LED starts blinking in the right rate.

To give the user the ability to start, stop and send test data I created this awesome UI with buttons to start and stop the phone sending band data to the OWIN server, as well as a button to send a simulated heart rate as typed in the textbox. Quite the pinnacle of minimalistic design I’d say, don’t you think? ;)

Conclusion

With a little imagination, out-of-the-box thinking and of course some kick *ss hardware and awesome SDKs it’s not that hard these days to let three devices dance together and make a single system – all C#, mostly Microsoft technology and mostly standard knowledge. The hardest part is now writing the C# code that runs on Mono, as it’s impossible to debug a running instance from Visual Studio. We are so spoiled by Visual Studio and the awesome tools it offers, it’s sometimes very hard to have to do without. Let’s hope Windows 10 for devices makes life as good for device developers as for all other Windows Platform developers.

For those who missed the link in between – a complete solution can be downloaded here.

20 February 2015

Controlling a LED with a Raspberry PI 2 using Mono and C#

My fellow MVP Peter Nowak from Germany pointed me to this awesome kit on Amazon.de that has this vast array of sensors in it.

It comes with 37 sensors and peripherals that can be controlled with a Raspberry PI2. It’s originally made for the PI B+, but as this is pin compatible with the PI 2 this works fine. It comes with a mini CD with sample code, but unfortunately this is all C - you need to compile it using GCC. Not having programmed in C since the late 90’s, it’s not code I feel very comfortable messing around with. On the other hand, I am also to impatient to let this gather dust until Windows 10 for devices becomes available.

Now the code samples in C that go with this kit all use a library called wiringPI, that is created by one Gordon Henderson. I basically used this library as a foundation for getting the stuff to work with C#. You first have to install the library. Gordon has a simple step-by-step manual on how to go about on this. Simply open a console, go to the directory where you want to download the library’s sources to, and follow his instructions.”Installing” in Linux apparently means installing git, clone the repository, and start a build file that apparently compiles the whole shebang and puts it ‘somewhere’. The net result is that you can compile the sample C programs that comes with the kit using Gordon’s library to control the sensors.

Then there is this guy, Daniel Riches, who has created a simple wrapper library for C#. How this works is mind-bogglingly simple – he simple uses DllImport to wrap calls to the C library and making those accessible to C#. I haven’t seen this technique used in anger since 1999, in a Visual Basic 6 project. But apparently this still works – and what’s more important – it apparently works under Mono too, even if the imported code does not come from a DLL at all, but a ‘so’ file.

He kind of describes what you need to do – after installing Gordon’s library, you go (still on the command line of course) to the subfolder “wiringPi” of the folder where you have started the build, and then start three commands to create ‘shared libraries’:

cc -shared wiringPi.o -o libwiringPi.so
cc -shared wiringPiI2C.o -o libwiringPiI2C.so
cc -shared wiringPiSPI.o -o libwiringPiSPI.so

And apparently you can then just delete the folder where you have downloaded wiringPi’s sources in. The library is installed and can be used.

Now Daniel’s sample shows the way, unfortunately it’s missing one key feature for my goal – for controlling a LED you will need access to the “softPwm” routines of wiringPi. Browsing the C sources I found the softPwm.c file with the routines I needed to access. So I created my own wrapper class:

using System.Runtime.InteropServices;

namespace WiringPi
{
  public class SoftPwm
  {
    [DllImport("libwiringPi.so", EntryPoint = "softPwmCreate")]
    public static extern void Create(int pin, int initialValue, int pwmRange);

    [DllImport("libwiringPi.so", EntryPoint = "softPwmWrite")]
    public static extern void Write(int pin, int value);

    [DllImport("libwiringPi.so", EntryPoint = "softPwmStop")]
    public static extern void Stop(int pin);
  }
}

As you see, this is all pretty ugly – everything is public static, it follows the layout of the original code very closely and is in its current for totally not object oriented. But whatever, it’s still early days and it’s a temporary measure until Windows 10 pops up anyway. What this does is make a few C routines accessible to C# – for instance, the C routine “softPwmWrite”, that puts a value on a GPIO pin, becomes available al SoftPwm.Write.

And then I can write the following simple program that lets the multi color LED that comes with the SunFounder kit it all kinds of colors:

using System;
using System.Threading;
using WiringPi;

namespace SunfounderTest
{
  class Program
  {
    const int LedPinRed = 0;
    const int LedPinGreen = 1;
    const int LedPinBlue = 2;

    static void Main(string[] args)
    {
      if (Init.WiringPiSetup() != -1)
      {
        SoftPwm.Create(LedPinRed, 0, 100);
        SoftPwm.Create(LedPinGreen, 0, 100);
        SoftPwm.Create(LedPinBlue, 0, 100);
        Console.WriteLine("Init succeeded");

        for (var i = 1; i < 3; i++)
        {
          ShowColor(255, 0, 0, "Red");
          ShowColor(0, 255, 0, "Green");
          ShowColor(0, 0, 255, "Blue");
          ShowColor(255, 255, 0, "Yellow");
          ShowColor(255, 0, 255, "Pink");
          ShowColor(0, 255, 255, "Cyan");
          ShowColor(195, 0, 255, "Purple");
          ShowColor(255, 255, 255, "White");
        }

        SoftPwm.Stop(LedPinRed);
        SoftPwm.Stop(LedPinGreen);
        SoftPwm.Stop(LedPinBlue);
      }
      else
      {
        Console.WriteLine("Init failed");
      }
    }

    private static void ShowColor(int r, int g, int b, string label)
    {
      SetLedColor(r, g, b);
      Console.WriteLine(label);
      Thread.Sleep(1000);
    }

    private static void SetLedColor(int r, int g, int b)
    {
      SoftPwm.Write(LedPinRed, r);
      SoftPwm.Write(LedPinGreen, g);
      SoftPwm.Write(LedPinBlue, b);
    }
  }
}

I will not even begin with pretending that I actually fully understand what I am doing – and I even understand less of the why - but you first have to call the Init.WiringPiSetup method – that was already wrapped by Daniel – and then you need to call ‘Create’ on the three pins - only then you can actual set value to the pins using SoftPwm.Write. I wrapped the calls to that in SetLedColor that accepts red, green and blue values (apparenly 0-255), which is in turn wrapped in a routine that writes progress info and waits a little before progressing. And at the end, you will need to call Stop on all three pins to make the LED go off again, or else it will happily stay on.

Net effect: if you connect LED Pin R to GPIO17, Pin G to 18, Pin B to 27 and the ground pin to on of the GND, the led will flash trough a whole range of colors.

LED controlled by C# on Raspberry PI2 using C#

It will only work if you run the app using sudo, so

sudo mono SunfounderTest.exe

The annoying part is that in the samples provide with this kit these pins 17, 18 and 27 are referred to as 0, 1 and 2. This apparently has historical reasons. On this page at element14 I have found a pin schema with translation from one naming to the other. Notice Pin number 11 is called both GPIO17 as well as GPIO_GEN0. This correspond to Pin 0 in the code. I assume there is some logic somewhere, but I yet have to discover that :)

As is my custom, you can find a demo solution here. Mind you – not all of the code is mine, part of it is from Daniel Riches

11 February 2015

Starting an OWIN ASP.NET server on Raspberry PI 2 automatically at boot up

Inspired by the buzz that engulfed the Microsoft community when it was announced the new Raspberry PI 2 was going to support Windows 10 I actually got myself one too, with the aid of community member Maurice Spronkers (thank bro!)

image

Windows 10 for devices is not yet out for release, so here I was, being a bit impatient to apply my .NET skills, looking at a device that, at the time of this writing, only can be powered by Linux. I have extensive UNIX experience, but after the GIS world largely moved to Windows NT in 1997(!) my command line skills had gotten a little rusty. Fortunately, there are this great tutorial by this awesome Belgian guy named Jan Tielens, who describes setting up the device for .NET developers and running an ASP.NET OWIN server on it.

The only thing I could not get to work, is to get the darn OWIN server to start at boot time. I found out, eventually. The problem did not so much in the configuration, as well in the default OWIN stand alone server code. Now Linux fans all over the world will probably ridicule me for this total lack of understanding of their system, let alone at how I arrived at the solution, but what the heck. Only a few learn without falling on their face first.

So after a lot of looking around of various sites, muttering on Twitter, and getting some help from various people, I arrived at this page that tells you to need edit a file named /etc/rc.local. Think of it as ye olde autoexec.bat. That, of course, you can only do as root. So you have to start that from the command line [insert muttering here]. The purists may use Nano or even VI (I still know some keystrokes if I go on automatic) but I found out that you can get a nice notepad like editor by typing
sudo leafpad /etc/rc.local

And then you add a line
su - pi -c "mono /home/pi/Desktop/OwinDemo/OwinTest.exe " &

and that should work (yeah I put my demo on the desktop. I like a GUI. Sue me). Trouble is, after rebooting, it does not. Remembering ye olde days of shell script development, I changed the line to:
su - pi -c "mono /home/pi/Desktop/OwinDemo/OwinTest.exe 2>/home/pi/Desktop/error.txt >/home/pi/Desktop/log.txt" &

Mind you, this should all be on one line! It should dump all the output of the process itself in log.txt, and possible errors in error.txt. I booted up the PI2 – nothing. But lo and behold, two files popped onto the desktop, error.txt and log.txt. So at least something did run. The first one was empty (yay, no errors!) and the second one contained just the expected text: “Press Enter to quit.” So why did I get “This page cannot be displayed”

It turns out, my friends, that what works when you start it as a user, apparently does not work when you run it it the background. Apparently, although the Console.ReadLine should stop it – it doesn’t do that.

The only thing I had to change was the .NET code.

In stead of this piece of code, that everyone writes in the OWIN examples,

static void Main(string[] args)
{
  const string baseUrl = "http://*:5000";
  using (WebApp.Start<Startup>(baseUrl))
  {
    Console.WriteLine("Press Enter to quit.");
    Console.ReadKey();
  }
}

I wrote this very naïve piece of code

static void Main(string[] args)
{
  const string baseUrl = "http://*:5000";
  using (WebApp.Start(baseUrl))
  {
    while(true)
    {
      Console.WriteLine("Waiting...");
      Thread.Sleep(2000);
    }
  }
}

And verily, verily, now every two seconds my file “log.txt” got a new line and I actually could access the web site running on my PI.

image

I assume I am a very big dumbass for not understanding this and my logging method is very primitive, but I could not find a decent resource telling me why I was stupid and how to solve this, so I thought I’d share this with you.

AS Jan in his original article shares most of the code I forego my trademark sample solution this time, as I expect my readers at least to be capable to delete two lines of code and replace them by four.

Final thought: if you deploy this, you might want to delete the logging redirects (as you won’t like having a very big file on you desktop just saying “Waiting…” umpteen times), and you might want to set the Thread.Sleep to a higher value so save (a minute bit of) CPU cycles.

Disclaimers: no PI2’s were harmed for this article, or being forced to reboot by the flash where it’s picture was taken with ;)

08 February 2015

Using a full-size none-stretched background image in a Xamarin.Forms app

Intro

I always like to use a kind of a translucent background image to my app’s screens, that makes it look a bit more professional than just a plain single-colored screen – a trick I learned from my fellow MVP Mark Monster in the very early days of Windows Phone development. Now that I am trying to learn some Xamarin development, I want to do the same thing – but it turns out that works a bit different from what I am used to.

Setting up the basic application

I created a Xamarin Forms portable app “BackGroundImageDemo”, but when you create a new Xamarin Forms application using the newest templates in Xamarin 3.9, you get an application that uses forms, but no XAML. Having lived and dreamed XAML for the last 5 years I don’t quite like that, so start out with making the following changes:

1. Update all NuGet packages - this will get you (at the time of this writing) the 1.3.2 forms packages

2. Add StartPage.Xaml to BackGroundImageDemo (Portable)

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="BackGroundImageDemo.StartPage">
	<Label Text="Hello world from XAML" VerticalOptions="Center" 
         HorizontalOptions="Center" FontSize="30" />
</ContentPage>

3. Make some changes to the App.cs in BackGroundImageDemo (Portable) to make it use the XAML page:

namespace BackGroundImageDemo
{
  public class App : Application
  {
    public App()
    {
      // The root page of your application
      MainPage = new StartPage();
    }
    
    // stuff omitted
  }
}

And when you run that, for instance on Windows Phone, it looks like this:

image

JupiterAdding a background picture

Now suppose I want to make an app related to astronomy – then I might use this beautiful picture of Jupiter, that I nicked off Wikipedia, as a background image:

It has a nice transparent background, so that will do. And guess what, the ContentPage class has a nice BackgroundImage attribute, so we are nearly done, right?

As per instructions found on the Xamarin developer pages, images will need to be:

  • For Windows Phone, in the root
  • For Android, in the Resources/drawable folder
  • For iOS, in Resources folder

In addition, you must set the right build properties for this image:imageimage

  • For Windows Phone, set “Build Action” to “Content” (this is default) and “Copy to Output Directory” to “Copy if newer”
  • For Android, this is “AndroidResource” and “Do not copy”
  • For iOS, this is “BundleResource” and “Do not copy”

So I copy Jupiter.png three times in all folders (yeah I know, there are smarter ways to do that, that’s not the point here) add BackgroundImage=’'Jupiter.png” to the ContentPage tag and… the result, as we can see on the to the right, is not quite what we hoped for. On Android, Jupiter is looking like a giant Easter egg. Windows Phone gives the same display. On the Cupertino side, we get a different but equally undesirable effect.

RelativeLayout to the rescue

Using RelativeLayout and constraint expressions, we can more or less achieve the same result as Windows XAML’s “Uniform”.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="BackGroundImageDemo.StartPage" >
  <RelativeLayout>
    <Image Source="Jupiter.png" Opacity="0.3"
                RelativeLayout.WidthConstraint=
                  "{ConstraintExpression Type=RelativeToParent, Property=Width}"
                RelativeLayout.HeightConstraint=
                  "{ConstraintExpression Type=RelativeToParent, Property=Height}"/>
    <Grid RelativeLayout.WidthConstraint=
              "{ConstraintExpression Type=RelativeToParent, Property=Width}"
            RelativeLayout.HeightConstraint=
              "{ConstraintExpression Type=RelativeToParent, Property=Height}">

      <Label Text="Hello world from XAML" VerticalOptions="Center"
         HorizontalOptions="Center" FontSize="30"/>
    </Grid>
  </RelativeLayout>
</ContentPage>

All elements within a RelativeLayout will essentially be drawn on top of each other, unless you specify a BoundsConstraint. I don’t do that here, so essentially every object will drawn from 0,0. By setting width and height of the RelativeLayout’s children to essentially the width and height of the RelativeLayout itself, is will automatically stretch to fill the screen. And thus the image ends up in the middle, as does the Grid with the actual UI in it. Just make sure you put the image Image first and the Grid second, or else the image will appear over your text.

I also added Opacity = “0.3” to make the image translucent and not so bright that it actually wipes out your UI. The exactly value of the opacity is a matter of taste and you will need to determine how it affects the readability of the actual UI on a real device. Also, you might consider editing the image in Paint.Net or the like and set its to 0.3 opacity hard coded in the image, I guess that would save the device some work.

Anyway, net result:

imageimageimage

Demo solution, as always, can be downloaded here.