.net, .net core

Contributing to the .NET Core SDK source code for the first time, and how OSS helped me

The .NET Core source code has been open sourced on GitHub for a while now, and the community is free to raise issues and submit pull requests – though I’d not really expected that I’d ever actually need to. That’s mainly because I always expect that thousands of other talented developers will have tested the code paths I’m working with and found (and solved) those issues before me.

But shortly after I installed .NET Core 2.0.0 Preview 1, I found that all my .NET Core projects that I had written for Windows 10 IoT Core suddenly stopped working – and the reason was that the executable file wasn’t being generated any more after I published the project.

I tested the hell out of this – I originally suspected that I had done something wrong or different, and I really didn’t want to report an issue and then find I was the one who had actually made a mistake. But I eventually concluded that something had changed in the code, so I raised a bug under the title “Publishing to win10-arm or win8-arm doesn’t generate an exe file for a Console application“, and this ultimately led to me committing some test code to the .NET Core codebase.

So the fact that .NET Core is completely open source and receiving community contributions suddenly became extremely relevant to me – previously I’d have just had to suffer the problem.

None of this stuff I write about below is a particularly big deal – just a part of software development – but dipping my toe into the waters of a massively public open source project was, well, a bit nerve wracking.

In some ways I felt like when I start a new job, where I’ve joined a team that has patterns and practices that I’m not entirely familiar with – I’m always worried I’ll do something that makes things harder for other developers, invokes justified wrath… and reminds me that it’s only Imposter Syndrome if I’m not actually stupid.

None of the stuff I was worried about happened – and was it was never going to happen. The .NET development team were super helpful, open, friendly, and encouraged me right from the start – and there were safety nets all along the way to stop anything bad happening. They even suggested a workaround to solve my problem on the same day I raised the issue, which massively helped me before the resolution was merged in.

I’ve written about my experiences below – things I got right, and things I got wrong – hopefully this will be useful to other developers thinking about putting their toe in the same waters.

Tips for a good issue report

The first part of this was writing up the issue – I think that there are essentially three parts to a good issue report:

  • Steps to recreate the issue
  • Actual behaviour
  • Expected behaviour – don’t forget to say why you think this is the expected behaviour.

What sort of things do I need to do when submitting a pull request to the .NET Core repositories?

I wasn’t the developer who actually solved the issue – the .NET team get the credit for that – but I did see an opportunity to write a test to make sure the issue didn’t reoccur, and I submitted a PR for that code change.

First, fork the .NET Core SDK repository

This bit’s really easy – just click on the “Fork” button in the top right corner of the GitHub repository. This’ll create a fork of the original Microsoft source code in your own GitHub profile.

Clone the repo locally, and make sure you choose the correct branch to code against

I used TortoiseGit to clone the repository to my local development machine, and just started coding – and that turned out to be a bit too quick on the draw. I don’t think this is written down anywhere, but I should have targeted the release/2.0.0 branch.

How do I choose the right branch? I think the best way is to look at some recently closed pull requests, and see where the other developers are pushing their code.

With TortoiseGit, it’s easy to switch branches.

  • Right click on the root of the repo you’ve cloned, select “TortoiseGit > Switch/Checkout”.

screenshot.1497111687

  • A window will appear, where you can select the branch you want from a dropdown list. In the image below, you can see I’ve selected the release/2.0.0 branch. Click OK to switch your local repo to the code in this branch.

screenshot.1497111727

I initially (but wrongly) wrote my code against the default branch – in some repositories that’s possibly ok, but at the time of writing, the best branch to target in the .NET SDK repo is release/2.0.0. By the time I realised I should have targeted the release/2.0.0 branch and tried to switch to it, GitHub invited me to resolve lots of conflicts in files I hadn’t touched. Rather than trying to rebase and introducing lots of risk, I just closed the original pull request, selected the correct branch, and opened a new pull request which included my code change. Don’t make the same mistake I did!

Test that you can build the branch before making any changes

Once your locally cloned repository targets the correct branch, you should try building the code before making any changes. If it doesn’t build at this point or tests fail, then at least you know the problem isn’t caused by something you did.

In the root folder of the source for .NET Core’s SDK, there are three files which can be used to build the code:

  • build.cmd
  • build.ps1
  • build.sh

Open a command prompt, and run whichever one of the three options that is your favourite.

If you find that the code doesn’t build or the tests don’t pass, check the build status on the repo’s home page.

Make your changes, commit them, and push the changes to the right branch in your remote fork on GitHub

Don’t forget your unit tests, make sure everything builds, and comment your changes appropriately.

Now create a pull request

From your forked repository, hit the “New Pull Request” button. Here are a few things that I think are useful to think about:

  • You’ll need to enter a comment – make sure it’s a useful one.
  • Describe why your change is valuable – does it fix an issue? Is it a unit test, related to another pull request?
  • If you can, link to an issue or pull request in the comment to give the reviewers some context.
  • I try not to submit a pull request which changes many files – lots of changes make it difficult to review. If you have to change lots of files, try to explain why it wasn’t possible to separate this out into smaller chunks.
  • And remember to open the pull request against the correct branch!

screenshot.1497100934

What happens when I submit the pull request?

Once you submit your first pull request, it’ll immediately be assigned a label “cla-required” by the dnfclas bot.

screenshot.1496089436

cla is short for “contribution licence agreement“.

dnfclas means “dot net foundation contribution licence agreement” and is the Pull Request Bot.

To proceed beyond this point, you need to click on the link to https://cla2.dotnetfoundation.org to sign a Contribution Licence Agreement. When you click on that link, you’ll be redirected to a page like this.

screenshot.1496089699

Sign in using your GitHub credentials, and you’ll be invited to enter some details and sign the agreement. If you sign it, you’ll eventually be shown a page like the one below.

screenshot.1496089798

At this point, the dnfclas bot automatically recognises that you’ve signed the agreement (you don’t need to tell it), and it updates the label in the pull request from “cla-required” to “cla-signed”. You’ll see this on your pull request as an update, similar to the one below.

screenshot.1496089456

As you might expect, there’s a series of integration environments where your pull request will be tested. For the .NET Core SDK continuous integration process, there are presently 10 environments where code is automatically tested:

  • OSX10.12 Debug
  • OSX10.12 Release
  • Ubuntu14.04 Debug
  • Ubuntu14.04 Release
  • Ubuntu16.04 Debug
  • Ubuntu16.04 Release
  • Windows_NT Debug
  • Windows_NT Release
  • Windows_NT_FullFramework Debug
  • Windows_NT_FullFramework Release

There are lots of dotnet repositories, and an issue which manifests itself in one repo might have the root cause in another one – and this was the case for me. The issue that I observed in the SDK actually started in the .NET CoreFx repository.

It takes a while for fixes in one repo to flow across to the other, so if you submit a unit test to one repo for a fix that lives somewhere else, the test might fail for a while – and that’ll stop it being merged in immediately.

So if you’re only submitting tests, expect that all the checks will fail until the code you’re covering with your unit test flows across to the .NET Core SDK continuous integration environment.

screenshot.1496092980

Once the fixed code has flowed through, you’ll see this (assuming your code works…):

screenshot.1496355381

The .NET Team will choose a reviewer for you – you don’t need to choose anyone

Finally – and probably most importantly – someone from the .NET Core SDK team will review your code. I think it’s mandatory (as well as courteous) to address any comments from your reviewer – these are helpful pointers from a team of super smart people who care about good code.

Other gotchas

One thing that caught me out was that GitHub marked some of the review comments as “outdated” (as shown below). I should have clicked on these – if I had, I would have seen a few comments that I hadn’t addressed.

screenshot.1496092853

Another thing was I wish I had a copy of Resharper on my development machine – one of the review comments was that I had left an unused variable in my code. Resharper would have caught this error for me.

Wrapping up

So, much to my surprise, I’ve contributed to the .NET Core codebase – albeit in a very small way!

screenshot.1497101854

In summary, I was a bit nervous about submitting my first pull request to the .NET Core SDK repository – but I decided to create a simple test which covered a bug fix from the .NET team. Apart from signing a contribution licence agreement, this was a pretty standard process of submitting a pull request for review and automated testing. One really nice thing is that changes are tested not only against Windows, but also different versions of Ubuntu and OSX.  Also, if you’re about to submit your own pull request to a .NET Core repo, I’d recommend checking out other pull requests first as a guideline – and don’t forget to look at what branch the developers are merging to.

Hopefully this description of my experiences will help other developers thinking of contributing feel a bit more confident. I’d recommend to anyone thinking of making their first contribution, choose something small – it’ll help you get familiar with the process.

.net, .net core, Raspberry Pi 3

Using .NET Core 2 to read from an I2C device connected to a Raspberry Pi 3 with Ubuntu 16.04

I’ve bought a lot of hardware devices – often I2C devices – to attach to my Raspberry Pi devices over the years – things like thermometers, gyroscopes, light intensity sensors and so on. And usually there’s a library supplied by the manufacturer of a device breakout board which shows me how to use the device in the .NET framework.

But what if there isn’t a library for my device? Or what if the library isn’t in .NET – or if it is in .NET, what if it isn’t compatible with .NET Core 2? I wanted to know if I could find a way to still read from my I2C devices while coding from scratch using .NET Core 2, and not depend on someone else writing the library for me.

PInvoke

I’ve written a couple of posts recently (one for Windows 10 IoT Core and one for Ubuntu 16.04) about how to create simple platform invocation service (also known as PInvoke) applications in .NET Core 2 – these posts describe calling native methods to capitalise some text, and deploy the application to a Raspberry Pi 3.

So since I found that it was so easy to use PInvoke with .NET Core and Ubuntu on the Raspberry Pi, I thought I’d try something more ambitious – accessing hardware device registers over an I2C bus using native libraries.

What is I2C?

I2C is a protocol often used to connect peripheral hardware devices (such as a thermometer) to a processor device such as a Raspberry Pi or an Arduino. Typically I find there are four wires needed to connect the Raspberry Pi to an I2C device – one for power (usually 3.3V or 5V), one for ground, one for a serial data line (sometimes labelled as SDA), and one for a serial clock line (sometimes labelled SCL).

As a software developer, I don’t need to worry too much about these wires – I just need to connect the correct 5V/3.3V and 0V wires, and connect the SDA wire to Pin 3 on my Raspberry Pi, and connect the SCL wire to Pin 5 on my Pi.

How can I set up my Ubuntu Raspberry Pi 3 to use I2C?

My Ubuntu installation on my Raspberry Pi 3 didn’t have I2C enabled out of the box – I needed to make a few simple changes.

  • I opened the file “/etc/modules” as sudo and added a couple of lines to the end:
i2c-dev
i2c-bcm2708
  • I opened the “/boot/config.txt” file as sudo and added a couple of lines to the end:
dtparam=i2c_arm=on
dtparam=i2c1=on
  • I then ran the command below:
sudo apt-get install -y i2c-tools

At this point I was able to run the command below:

i2cdetect -y 1

This command scans the I2C bus for attached devices. The “-y” switch means it doesn’t prompt me to type ‘Yes’ to confirm, and the “1” means I’m scanning the I2C-1 bus.

screenshot.1494270470

This showed me that my I2C bus is configured correctly, and highlighted that an external device is connected to my I2C-1 bus, and is accessable at address 0x48.

The device is actually a TMP102 temperature sensor – which I’ve written about before when I used a UWP application to read from this device.

How can I read from a device connected to my Raspberry Pi 3?

I happen to know for this device that the temperature is written into the first two bytes of the TMP102 device (from the datasheet), so I want my code to read these bytes.

Once I’ve connected my I2C device correctly to my Raspberry Pi 3, there are three steps to the code:

  • Open the I2C bus,
  • Specify the address of the device we want to control and read from, and
  • Read from the device.

Whereas this isn’t possible in standard .NET Core 2, there are three functions available in the GNU C library which will do this for us.

I’ve pasted the invocation signatures below to access these functions.

[DllImport("libc.so.6", EntryPoint = "open")]
public static extern int Open(string fileName, int mode);
 
[DllImport("libc.so.6", EntryPoint = "ioctl", SetLastError = true)]
private extern static int Ioctl(int fd, int request, int data);
 
[DllImport("libc.so.6", EntryPoint = "read", SetLastError = true)]
internal static extern int Read(int handle, byte[] data, int length);

So we can open the I2C-1 bus with the .NET code below:

int OPEN_READ_WRITE = 2; // constant, even for different devices
var i2cBushandle = Open("/dev/i2c-1", OPEN_READ_WRITE);

We can control the I2C slave device with address 0x48 on the I2C-1 device with the .NET code below:

int I2C_SLAVE = 0x0703; // constant, even for different devices
int registerAddress = 0x48; // different address for each I2C device
var deviceReturnCode = Ioctl(i2cBushandle, I2C_SLAVE, registerAddress);

And finally we can read two bytes into a byte array from the device with the code below:

var deviceDataInMemory = new byte[2];
Read(i2cBushandle, deviceDataInMemory, deviceDataInMemory.Length);

Putting it all together

First install .NET Core 2 using the executable from here, and then install the template for .NET Core 2 IOT projects using the command below:

dotnet new -i RaspberryPi.Template::*

Next create a project (for the TMP102 device) using the command

dotnet new coreiot -n Tmp102

Open the project, and replace the code in the Program.cs file with the code below:

using System;
using System.Runtime.InteropServices;
 
namespace RaspberryPiCore
{
    class Program
    {
        private static int OPEN_READ_WRITE = 2;
        private static int I2C_SLAVE = 0x0703;
 
        [DllImport("libc.so.6", EntryPoint = "open")]
        public static extern int Open(string fileName, int mode);
 
        [DllImport("libc.so.6", EntryPoint = "ioctl", SetLastError = true)]
        private extern static int Ioctl(int fd, int request, int data);
 
        [DllImport("libc.so.6", EntryPoint = "read", SetLastError = true)]
        internal static extern int Read(int handle, byte[] data, int length);
		
        static void Main(string[] args)
        {
            // read from I2C device bus 1
	    var i2cBushandle = Open("/dev/i2c-1", OPEN_READ_WRITE);
 
            // open the slave device at address 0x48 for communication
	    int registerAddress = 0x48;
	    var deviceReturnCode = Ioctl(i2cBushandle, I2C_SLAVE, registerAddress);
 
            // read the first two bytes from the device into an array
	    var deviceDataInMemory = new byte[2];
	    Read(i2cBushandle, deviceDataInMemory, deviceDataInMemory.Length);
 
            Console.WriteLine($"Most significant byte = {deviceDataInMemory[0]}");
            Console.WriteLine($"Least significant byte = {deviceDataInMemory[1]}");
        }
    }
}

Now build and publish using the commands below:

dotnet build
dotnet publish -r ubuntu.16.04-arm

And copy the published code (inside the “.\bin\Debug\netcoreapp2.0\ubuntu.16.04-arm\publish\” directory) to your Raspberry Pi 3 running Ubuntu.

Now if you run the Tmp102 executable (you might need to chmod it to have execute privileges), it’ll write the contents of the first two bytes to the console, which proves we’ve successfully connected to the device over the I2C bus and read from it.

screenshot.1494274133

Wrapping up

There’s obviously a lot more to I2C than this post, but it proves that we can use PInvoke and .NET Core 2 to read from devices using the I2C protocol. With this knowledge, I’m not dependent on hardware vendors supplying working .NET code for my I2C devices (although that obviously makes things easier!)

.net, .net core, Raspberry Pi 3

Using PInvoke with .NET Core 2 and Ubuntu 16.04 on the Raspberry Pi 3

I’ve written previously about how to use PInvoke with .NET Core 2 on a Raspberry Pi 3 running Windows 10 IoT Core – I tested it with a very simple example where I converted some text to upper case using the CharUpper method in the user32.dll library. I was able to invoke the CharUpper method using the code below:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern char CharUpper(char character);

You can see the full code at Github here.

I decided to see if I could repeat this simple example on Ubuntu using the built in libraries – and found that it is actually really easy to use PInvoke with .NET Core on Ubuntu also. I’ll run through the steps to repeat this on your own Raspberry Pi 3 running Ubuntu 16.04.

  • Install .NET Core 2 – you can get the installer from here.
  • Create a console app for the Raspberry Pi 3 – you can install a template using the code below:
dotnet new -i RaspberryPi.Template::*
  • And then you can create a new project using the command below:
dotnet new coreiot -n RaspberryPi_PInvoke
  • In the generated project, replace the code in Program.cs with the code below. I’ve highlighted the key part of the code in red – this uses the GNU C library, libc. I import the method “toupper”, but alias it as CharUpper which is the name of the function I used in the previous post.
using System;
using System.Runtime.InteropServices;
 
namespace RaspberryPi_PInvoke
{
    class Program
    {
        [DllImport("libc.so.6", EntryPoint = "toupper")]
        private static extern int CharUpper(int c);
 
        static void Main(string[] args)
        {
            var textToChange = "Hello Internet of Things!";
            var inputCharacterArray = textToChange.ToCharArray();
 
            // array of chars to hold the capitalised text
            var outputCharacterArray = new char[inputCharacterArray.Length];
 
            for(int i = 0; i < inputCharacterArray.Length; i++) 
            {
                var charToByte = (byte)inputCharacterArray[i];
                outputCharacterArray[i] = (char)CharUpper(charToByte);
            }
 
            Console.WriteLine($"Original text is {textToChange}");
            Console.WriteLine($"Changed text is {new string(outputCharacterArray)}");
        }
    }
}
  • Now build this using the command:
dotnet build
  • And publish for Ubuntu using the command:
dotnet publish -r ubuntu.16.04-arm
  • Finally, deploy this to your Raspberry Pi 3 running Ubuntu.

I use pscp to copy files from my Windows machine to the Pi 3 running Ubuntu, but you could also use rsync from Bash in Windows 10. Remember to make the file you need to run (RaspberryPi_PInvoke) executable on the Pi 3 using chmod.

When you run this application through a terminal, you’ll see that it converts the text “Hello Internet of Things!” to upper case.

screenshot.1494193840

Wrapping up

This post is very similar to a post I wrote previously about using PInvoke with Windows 10 IoT Core on the Raspberry Pi 3 – except this time, I use a function from the GNU C library, libc. This is an incredibly rich source of code, and I’ll write next time about how I can use this to access the I2C bus.

.net, .net core, Raspberry Pi 3

Controlling GPIO pins using a .NET Core 2 WebAPI on a Raspberry Pi, using Windows 10 or Ubuntu

Previously I’ve written about creating a .NET Core 2 Web API and hosting it on a Raspberry Pi 3, and this time I’ll expand on this work to interact with GPIO pin logic levels.

This is the latest in a series of posts helping developers write .NET Core 2 code to interact with IoT hardware, in a way which is agnostic towards the device operating system. I’ve written a few bits and pieces about how to change GPIO pin status with a console application previously – but with a WebAPI, we can now control GPIO status with HTTP Post requests. So with this capability, you can imagine how we could control a physical device from something like a browser application, or even a HoloLens or Xbox app.

TL:DR – as usual, the source code is up on GitHub here.

Create the Web API project for the Raspberry Pi

This bit is easy – once you have .NET Core 2 on your machine, just install the template from Nuget using the command below:

dotnet new -i RaspberryPi.WebApi::*

And then pick a folder on your development environment to create a new project called GpioSwitcherWebApio with the command:

dotnet new piwebapi -n GpioSwitcherWebApi

At this point you’ll have all the code you need to run a .NET Core 2 Web API project on your Raspberry Pi.

If you want to read more about this, check out a longer post here.

Create a controller to change pin status

Let’s open our project, and add a dependency on the Bifröst project – this helps us in a couple of ways. We can write the same code to target both Ubuntu and Windows 10 IoT Core devices, and there’s also a Bifröst UWP app that helps us access GPIO hardware on Windows 10 IoT devices. Open up a Package Manager prompt in Visual Studio 2017 and enter:

Install-Package Bifrost.Devices.Gpio.Core -Version 0.0.1
Install-Package Bifrost.Devices.Gpio.Abstractions -Version 0.0.1
Install-Package Bifrost.Devices.Gpio -Version 0.0.2

If you’re not using Visual Studio 2017, you can just modify the GpioSwitcherWebApi.csproj file and add the package references shown below:

  <ItemGroup>
    <PackageReference Include="Bifrost.Devices.Gpio" Version="0.0.2" />
    <PackageReference Include="Bifrost.Devices.Gpio.Abstractions" Version="0.0.1" />
    <PackageReference Include="Bifrost.Devices.Gpio.Core" Version="0.0.1" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.0.0-preview1-*" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.0-preview1-*" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.0-preview1-*" />
  ItemGroup>

Next, we can edit the default ValuesController which comes with the project – I’ve renamed mine to be PinsController.cs, which is a title better suited to the action we’re going to carry out.

I want my controller to have three actions for Ubuntu or Windows IoT devices:

  • Get() – an HttpGet action which returns a list of Gpio pins which are presently exported, and their current status (high/low).
  • Get(int pinId) – an HttpGet action which returns the status of the Gpio pin with the number pinId.
  • SwitchPin(int pinId, int status) – an HttpPost action which allows me to select a GpioPin with number pinId, and set it to a value of status (which is either 1 or 0, corresponding to high or low).

The Bifröst libraries make setting up our controller to modify GPIO pin statuses very easy.

The code below is just an example – obviously in a properly structured application, modifying GPIO pin levels would be managed through an interface to a service layer.

First, we need to instantiate a static instance of the GpioContoller object – so we can add a private member variable and a class constructor, as shown below.

private IGpioController gpioController;
 
public PinsController()
{
    Console.WriteLine("In controller - instantiating GpioController instance");
    gpioController = GpioController.Instance;
}

Next, we need to write the HttpGet action that returns a list of Gpio pins which are presently exported, and their current status. The code below shows the controller action which achieves this, and returns a 200 OK Http code.

[HttpGet]
public IActionResult Get()
{
    Console.WriteLine("About to list pin statuses.");
    return Ok(gpioController.Pins);
}

We also want to be able to find the present status of a Gpio pin by passing the pin number to the HttpGet method, and we can do this with the code below.

[HttpGet("{pinId}")]
public IActionResult Get(int pinId)
{
    GpioPinValue pinStatus;
 
    Console.WriteLine("About to get pin status.");
    var pin = gpioController.OpenPin(pinId);
 
    pinStatus = pin.Read();
 
    Console.WriteLine("Returning pin status.");
    return Ok(pinStatus.ToString());
}

Finally, the interesting bit – rather than just reading pin logic levels, I’d like to be able to modify them – I think the most logical Http verb to use here is the HttpPost verb, so I can post values for the pin number I want to change, and the level I want to change it to, using the code below:

[HttpPost]
public void SwitchPin(int pinId, int status)
{
    Console.WriteLine("About to change pin status.");
    var pin = gpioController.OpenPin(pinId);
 
    pin.SetDriveMode(GpioPinDriveMode.Output);
 
    if (status == 1)
    {
        Console.WriteLine("Going on");
        pin.Write(GpioPinValue.High);
    }
    else
    {
        Console.WriteLine("Going off");
        pin.Write(GpioPinValue.Low);
    }
}

To see the complete controller file already coded, check it out here.

If you’ve followed the steps above correctly, you should be able to build the WebAPI application in your normal way (e.g. in Visual Studio 2017 use Ctrl+Shift+B, or from a terminal in VSCode, execute the dotnet build command.

If you’ve pulled the project from GitHub here, there’s a file named build.ps1 which you can run from a PowerShell prompt to do the build for you. There are other more useful ones generated for publishing and deploying to Ubuntu 16.04 or Windows 10 IoT Core.

Deploying to your Raspberry Pi device

I’ve previously written step by step instructions on how to deploy code to a Raspberry Pi 3 running Ubuntu 16.04 or Windows 10 IoT Core, so I won’t repeat all of that here – the easiest way to do this is just to run the into PowerShell scripts I’ve uploaded to Github, and I briefly cover these below along with the parameters these scripts need to run.

To run these scripts successfully, make sure you’ve switched on your Raspberry Pi 3, logged into the device, and have connected it to your network.

Deploying to Ubuntu 16.04

  • Make sure you’ve got PuTTY installed on your development machine.
  • Get the IP address of your Raspberry Pi 3 (mine is 192.168.1.110)
  • Get the username you logged in with (default is ubuntu).
  • Get the path you want to deploy your WebAPI to (mine is /home/ubuntu/GpioWebAPI)

Using the script hosted here, run the command in PowerShell:

.\deploy-ubuntu.ps1 -ip 192.168.1.110 -username ubuntu -destination /home/ubuntu/GpioWebAPI

The WebAPI binaries will be build and published for an Ubuntu OS, and then copied to your Raspberry Pi.

Deploying to Windows 10 IoT Core

This is a little bit more complex – you have to deploy your WebAPI, and also deploy the Bifröst UWP app (you need the Bifröst UWP app on Windows to allow your .NET Core 2 app to read and change logic levels of your GPIO pins).

First, deploy the Web API application

  • Get the IP address of your Raspberry Pi 3 (mine is 192.168.1.125)
  • The name of the Web API application, which for me is GpioSwitcherWebApi.

Using the script below (you can get a copy from here), run the command to create the destination directory and add a firewall rule:

.\setup-windows.ps1 -ip 192.168.1.125 -applicationName GpioSwitcherWebApi

Now run the script below (you can get a copy from here), which copies the binaries to your Raspberry Pi 3.

.\deploy-windows.ps1 -ip 192.168.1.125 -applicationName GpioSwitcherWebApi

Thanks to wind-rider for their pull request with excellent powershell scripts.

Next, deploy the Bifröst Windows Device Bridge

How to deploy this UWP app is described in detail here, but it’s just a standard UWP app deployment. You can download the code from here, load it into Visual Studio Community 2017, and deploy it to your Raspberry Pi 3 hosting Windows 10 IoT Core.

screenshot.1493500867

Start the Kestrel web server to start the Web API

This is straightforward – for a Raspberry Pi hosting Ubuntu 16.04, I ssh in using PuTTY and run:

sudo /home/ubuntu/GpioWebApi/GpioSwitcherWebApi

And for a Raspberry Pi hosting Windows 10 IoT Core, I ssh in using PowerShell, navigate to where deployed the app, and run:

.\GpioSwitcherWebApi.exe

The web server will start up after a few seconds and it’s ready to test.

Testing our Web API by changing GPIO pin logic levels

We can test this really easily by issuing HttpGet or HttpPost requests to our webserver. Let’s test this for Pin 26 on our Raspberry Pi – I’ve connected an LED between Pin 26 and ground.

For my Windows 10 Raspberry Pi, I can just browse to the address:

http://192.168.1.125:5000/api/pins

This will return a JSON list of pins and logic levels (it’s probably an empty list if you’ve not run this before).

To switch a pin on, let’s use a Firefox plug in like HttpRequester.

  • For the URL, enter the URL above (http://192.168.1.125:5000/api/pins).
  • Select the “Parameters” tab (as shown below) and add name-value pairs of:
    • pinId = 26
    • status = 1
  • Now click on the “POST” button

The site responds with a HTTP status of 200 OK, and the logic level of GPIO pin 26.

screenshot.1493561495

The logic level is 1, which means the white LED attached to pin 26 will turn on.

Windows 10 Web API - LED On

If we want to find the status of Pin 26 now, we can read it with an HTTP get request of:

http://192.168.1.125:5000/api/pins/26

As shown below, there’s a GET request which returns a status of 200 OK and a text value of High – which is what we expect as we’ve just turned the pin on.

screenshot.1493561789

Finally let’s just issue an HTTP Get request with no pin Id specified to get all statuses – again we receive a 200 OK code and a JSON object listing the open GPIO pin and its status.

screenshot.1493562077

For testing Ubuntu the process is identical except for I had to substitute the IP address of my Ubuntu Raspberry Pi (which is 192.168.1.110). Repeating the process above turns on the orange LED attached to the Ubuntu Raspberry Pi (see below)

Raspberry Pi running Ubuntu LED On

Wrapping up

That’s all for this time – we’ve seen how to access GPIO pins from a .NET Core 2 Web API, and deploy that application to a Raspberry Pi 3 running either Windows 10 IoT Core or Ubuntu 16.04. This technique allows us to use the Raspberry Pi’s capabilities from a wider variety of interfaces than just a console – so we could use a browser, or even a HoloLens or Xbox app.

.net, .net core, Powershell, Raspberry Pi 3

Using PInvoke with .NET Core 2 and Windows 10 IoT Core on the Raspberry Pi 3

Since I’ve been kicking the tyres on .NET Core 2 to see what’s possible with the Raspberry Pi 3, I wondered if it was possible to use PInvoke on the Windows 10 IoT Core operating system – and it turns out that it is.

Let’s write a simple console application and deploy it to a Pi 3 to show PInvoke working.

As usual, you can find the finished code on my GitHub repository here.

First, install .NET Core 2

You can get the .NET Core 2 installer from here – remember that this version of .NET Core hasn’t made it to RTM status yet, so you’re playing with code at the bleeding edge. I’ve found it to be pretty stable, but I’m working on a machine which I’m happy to trash and rebuild.

screenshot.1492889096

Create a console app for the Raspberry Pi 3

Next, open a PowerShell prompt, and navigate to where you want to create the .NET Core 2 project.

dotnet new -i RaspberryPi.Template::*

This’ll add the template for a .NET Core 2 Console application which targets IoT devices – you can see this in your list of installed templates if you run:

dotnet new --list

You’ll see it in the list, as shown below.

screenshot.1493574830

So to create this kind of IoT console application, run:

dotnet new coreiot -n RaspberryPi.PInvoke

This creates a new folder and project called “RaspberryPi.PInvoke”, which presently will just write “Hello Internet of Things!” to the console.

Choose an unmanaged function to call – CharUpper

Let’s change this application to make that text – “Hello Internet of Things!” – become upper case. Inside user32.dll, there is a function called CharUpper which will do exactly that.

Obviously we could just use the “ToUpper()” string method inside managed .NET code to achieve this, but this application is a proof of concept to use PInvoke.

The C# signature for this is below:

[DllImport("user32.dll", CharSet=CharSet.Auto)]
static extern char CharUpper(char character);

So we can modify our very simple program to now become like the code below:

using System;
using System.Runtime.InteropServices;
 
namespace RaspberryPiCore
{
    class Program
    {
        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        static extern char CharUpper(char character);
 
        static void Main(string[] args)
        {
            var textToChange = "Hello Internet of Things!";
            var inputCharacterArray = textToChange.ToCharArray();
 
            // array of chars to hold the capitalised text
            var outputCharacterArray = new char[inputCharacterArray.Length];
 
            for(int i = 0; i < inputCharacterArray.Length; i++) 
            {
                outputCharacterArray[i] = CharUpper(inputCharacterArray[i]);
            }
 
            Console.WriteLine($"Original text is {textToChange}");
            Console.WriteLine($"Changed text is {new string(outputCharacterArray)}");
        }
    }
}

Let’s build this using:

dotnet build

Let’s publish it for Windows 10 IoT Core devices with an ARM processor using

dotnet publish -r win8-arm

Let’s open a Powershell prompt to our Raspberry Pi 3, create a folder to host this application.

mkdir c:\ConsoleApps\PInvoke

You can ssh to your Raspberry Pi 3 using a Powershell prompt from the Windows IoT Dashboard as shown in the image below:

screenshot.1489958874

And now let’s open a command prompt on our development machine, and copy the application binaries to the directory we created on our Raspberry Pi 3 earlier.

robocopy.exe /MIR ".\bin\Debug\netcoreapp2.0\win8-arm\publish" "\\<your-ipaddress-here>\c$\ConsoleApps\PInvoke"

Finally after building, publishing and deploying, we can go back to the ssh PowerShell prompt and run:

C:\ConsoleApps\PInvoke\RaspberryPi.PInvoke.exe

And this shows the text has been changed to upper case, as shown below.

screenshot.1493578558

Wrapping up

There’s nothing special about this code, it’s all pretty standard PInvoke code – but it’s nice to confirm that it works with .NET Core 2 on the Raspberry Pi 3’s ARM processor under Windows 10 IoT Core.

.net, .net core, Powershell

Using PowerShell to install the latest .NET Core 2 preview

I’ve been living on the bleeding edge and programming with the .NET Core 2 preview, which lives at https://github.com/dotnet/cli.

Reasonably frequently I find that I get error messages from the compiler saying there’s been some kind of file binary mismatch between versions, and I resolve this by getting rid of previous versions of .NET Core 2, and clearing out my .NET and Nuget caches.

Since a new build comes out every day, I wrote a simple PowerShell script to automate this process. I’ve highlighted (in red) some paths in the script which you might have to change in your setup if you want to use the script.

This is a pretty savage way to clear dotnet out – it deletes a lot of stuff. I use it on my development machine which I’m happy to trash. If you use this script, treat it very carefully!

Write-Host "About to clear .NET cache from my profile..."
$dotnetProfileFolder = "C:\Users\Jeremy\.dotnet"
Remove-Item $dotnetProfileFolder\* -recurse

# https://jeremylindsayni.wordpress.com/2016/05/24/fixing-rogue-behaviour-in-nuget-by-clearing-the-caches/
Write-Host "About to clear Nuget Cache..."
nuget locals all -clear

# https://blog.jourdant.me/post/3-ways-to-download-files-with-powershell
Write-Host "About to delete existing .NET Core binaries..."
$dotNetSdkFolder = "C:\Program Files\dotnet"
Remove-Item $dotNetSdkFolder\* -recurse

Write-Host "About to download latest .NET Core 2 binaries..."
$url = "https://dotnetcli.blob.core.windows.net/dotnet/Sdk/master/dotnet-dev-win-x64.latest.zip"
$output = "$dotNetSdkFolder\dotnet-dev-win-x64.latest.zip"

Import-Module BitsTransfer
Start-BitsTransfer -Source $url -Destination $output

# https://www.howtogeek.com/tips/how-to-extract-zip-files-using-powershell/
Write-Host "About to unzip latest .NET Core 2 binaries..."
$shell = new-object -com shell.application
$zip = $shell.NameSpace($output)
foreach($item in $zip.items())
{
 $shell.Namespace($dotNetSdkFolder).copyhere($item)
}

Write-Host "Done - dotnet version installed is:"
dotnet --version
.net, .net core, Raspberry Pi 3

Hosting a .NET Core 2 Web API instance on the Raspberry Pi 3

I’ve been spending a lot of time recently working to improve developer’s experiences with writing cross platform code for the Raspberry Pi 3 using .NET Core 2.

In a previous post, I wrote about creating a simple .NET Core 2 console app for the Pi – you can see the code on GitHub here, or if you just want to install the template, just install the Nuget package by running the code below from a command line:

dotnet new -i RaspberryPiTemplate::*

And to create a new console project with this template, run the code from a command line:

dotnet new coreiot -n MyProject

I saw this very nice post from Laurent Kempe where he writes about creating an MVC application for the Raspberry Pi – there’s a bit of overlap in this post about WebAPI, particularly around modifying the csproj file, but there’s also a few subtle differences which made me think that WebAPI deserves its own post.

I’ve also started a project called Bifröst – this is a project for developers who want to write .NET Core 2 applications that use IoT devices, and want to target Ubuntu and Windows with the same code.

What about creating a WebAPI project for a Raspberry Pi 3?

First – make sure you have .NET Core 2 – I noticed that the status has changed from Beta to Preview recently, and you can download an installer from here.

Remember .NET Core 2 is not in official release – you’re living on the edge using these latest builds of code from Microsoft!

 

screenshot.1492889096.png

 

The easy way – use the pre-baked templates from Nuget

If you just want to install a template from Nuget, run the code below at a command line;

dotnet new -i RaspberryPi.WebApi::*

Once you’ve installed this template, you can browse to where you’d like your project to be created and run the command below (obviously if you don’t want to call your project “MyProject”, choose a different name).

dotnet new piwebapi -n MyProject

This will create a .NET Core 2 WebAPI project called “MyProject”, which can be deployed to a Raspberry Pi running Windows 10 or Ubuntu. There are a bunch of deployment PowerShell scripts in the root, and you can read a bit more about them here.

If you want to look at a sample project which is created from this template, I’ve created a sample one on GitHub here.

If you’re deploying to Windows 10 IoT Core, remember to open a port in the firewall to allow connections – my sample template uses port 5000 and can be opened using the code below if you ssh into your Pi.

netsh advfirewall firewall add rule name="ASPNet Core 2 Server Port" dir=in action=allow protocol=TCP localport=5000

Or try the hard way – cook your own project

It’s not actually that hard – creating a WebAPI project for the Raspberry Pi 3 ARM processor is very similar to creating a standard WebAPI project for an x86/x64 machine, with a few small tweaks to the code.

After you’ve got .NET Core 2 installed, open a command line where you want your project to live and run the line of code below (again, obviously if you don’t want to call your project “MyProject”, choose a different name).

dotnet new webpi -n MyProject

When the project is created, open the root folder (which will be called MyProject) and edit the MyProject.csproj file. Look for the ProjectGroup node which should look like the code below:

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

And add two additional notes – RuntimeFrameworkVersion and RuntimeIdentifiers:

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <RuntimeFrameworkVersion>2.0.0-preview1-002028-00</RuntimeFrameworkVersion>
    <RuntimeIdentifiers>win8-arm;ubuntu.14.04-arm;ubuntu.16.04-arm</RuntimeIdentifiers>
  </PropertyGroup>

Now look at the project’s Program.cs file, and add the line of code:

.UseUrls("http://*:5000")

to the main method, as shown below:

public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseUrls("http://*:5000")
            .ConfigureAppConfiguration((context, configBuilder) => {
                configBuilder
                    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true)
                    .AddEnvironmentVariables();
            })
            .ConfigureLogging(loggerFactory => loggerFactory
                .AddConsole()
                .AddDebug())
            .UseStartup<Startup>()
            .Build();
 
        host.Run();
    }
}

I noticed one strange thing when generating the code using the WebAPI template – the main method calls a ConfigureConfiguration method, but this causes a compiler error against the most recent version of .NET Core 2 – I had to update this code to ConfigureAppConfiguration (in green in the code above). So watch out for that.

Building and deploying to a Raspberry Pi 3

First, build this project in the normal way – browse to the directory that you’ve created your project and run:

dotnet restore .

dotnet build .

Next, publish the application – the target depends on whether you want to run on a Raspberry Pi with Windows 10 or Ubuntu 16.04.

Publish targetting Ubuntu 16.04:

dotnet publish . -r ubuntu.16.04-arm

Publish targetting Windows 10:

dotnet publish . -r win8-arm
Next, we need to deploy these binaries:

Deploy to Ubuntu 16.04

To deploy to Ubuntu 16.04 from a Windows machine, we need a few things:
  • Install PuTTY (which also installs tools called pscp and plink, which we need). Add the PuTTY install directory to your Windows’ machine path.
  • The userid you used to log into your Pi – mine is ubuntu.
  • Create a directory on your Raspberry Pi to deploy the WebAPI code to – I’ve created on called “PiWebApi” which is at “/home/ubuntu/PiWebApi“.
  • The IP address of your Raspberry Pi – make sure your Raspberry Pi is logged in and connected to your local network – my Ubuntu Pi’s IP address is 192.168.1.110

Now run the command below to copy the binaries from your Windows development machine to the remote Raspberry Pi 3.

pscp.exe -r .\bin\Debug\netcoreapp2.0\ubuntu.16.04-arm\publish\* ubuntu@$192.168.1.110:/home/ubuntu/PiWebApi

Then run the command below from your development machine to make the binary executable on the Raspberry Pi.

plink.exe -v -ssh ubuntu@192.168.1.110 chmod u+x,o+x /home/ubuntu/PiWebApi/MyProject
Open an ssh connection using PuTTY to your Pi 3 and run the command:
./home/ubuntu/PiWebApi/MyProject
The console will show the text below as the web server starts up:
Hosting environment: Production
Content root path: /home/ubuntu/PiWebApi
Now listening on: http://[::]:8000
Application started. Press Ctrl+C to shut down.
And now you can browse to the address below to see the Raspberry Pi server returning values from the HTTP GET request:
screenshot.1492900054

Deploy to Windows 10 IoT Core

To deploy to a Raspberry Pi running Windows 10, we need to:
  • Create a directory on your Raspberry Pi to deploy the WebAPI code to – I’ve created on called “PiWebApi” which is at “C$/PiWebApi“.
  • Get the IP address of your Raspberry Pi – make sure you’ve logged into your Raspberry Pi and connected to your local network – my Windows 10 Pi’s IP address is 192.168.1.125

From a command prompt opened at the root of your WebAPI project, run the code below to copy the binaries from your development machine to your Pi:

xcopy.exe /y ".\bin\Debug\netcoreapp2.0\win8-arm\publish" "\\192.168.1.125\C$\PiWebApi"
Now open an ssh connection to your Raspberry Pi – I use PowerShell to do this through the “Windows IoT Dashboard” (as shown in the picture below):
screenshot.1489958874
From this ssh connection, you now need to open port 5000 in the Raspbery Pi 3’s firewall:
netsh advfirewall firewall add rule name="ASPNet Core 2 Server Port" dir=in action=allow protocol=TCP localport=5000
Browse to the deployment folder on your Raspberry Pi (in this case C:\PiWebApi) and run the command below:
./MyProject.exe
Again the text below is written to the console as the web server starts up:
Hosting environment: Production
Content root path: C:\PiWebApi
Now listening on: http://[::]:5000
Application started. Press Ctrl+C to shut down.

And again you can browse to the address below to see the Raspberry Pi server returning values from the HTTP GET request:

screenshot.1492899256.png
Footnote: There’s presently (26-Apr-17) an issue with some WebAPI calls in .NET Core 2, logged on GitHub with more information here. I’ve found that Kestrel throws an exception the first time I hit the the api/values/1 url, but it works the second time I hit the URL. Hopefully this’ll be diagnosed and fixed soon.