Windows 10 on Raspberry Pi 2

Windows 10 IoT Core on Raspberry Pi 2I was one of those who ordered the Raspberry Pi 2, when it was announced back in February 2015, off the back of the claims that it would run Windows 10. Not the full desktop version of Windows 10 of course, but a version for simpler devices. Still, it impressed me that here was a $36 computer that could run the latest version of Microsoft Windows.

Unfortunately, while the Pi 2 became available back then, the required version of Windows was not. It’s only been in the last month that Microsoft launched Windows 10 IoT Core, so I’ve finally had a chance to try it out.

For those that also are interested in this option, I thought I’d note down my experiences on installing it, connecting to it and running software on it.

Installing Windows 10 IoT Core

There are some official instructions provided by Microsoft on how to do this. However, they require that you are running Windows 10 on a PC, and none of my computers have Windows 10 yet. I also didn’t want to use up the hard disk space that would be needed if I had set up a Windows 10 virtual machine. I was more interested in unofficial options.

What didn’t work:

  • Using the Python ffu2img tool to convert the official Windows 10 IoT SD card image to something that could be loaded onto the SD card with something like Win32 Disk Imager. The ffu2img developer admits that they are pretty sure that there’s something wrong.
  • Downloading the official Windows 10 Home edition ISO and using the version of DISM in the sources directory there to load the SD card image.

What did work:

  • I got the official Windows 10 IoT Core for Raspberry Pi 2 ISO from Microsoft, opened it, ran the installer, and it put the flash.ffu file in C:\Program Files (x86)\Microsoft IoT\FFU\RaspberryPi2\
  • Next, I got the Windows ADK for Windows 10 installer from Microsoft, and it loaded a suitable version of DISM into C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\x86\DISM\
  • Then I formatted my SD card using SD Formatter
  • I copied the flash.ffu file into the DISM directory and used it (following the instructions on the Raspberry Pi forums) in an Administrator Command Prompt to copy it onto my SD card
  • I safely ejected the SD card, and popped into the Pi and it booted up fine.

Connecting to Windows 10 IoT Core

Once the Pi got going, I needed to tell it what language to use. I had plugged a decent quality USB keyboard in, but it was extremely finnicky: key presses were seemingly ignored. In the end, I plugged a USB mouse in and it was much more responsive to mouse clicks.

Windows 10 IoT is really designed to run a single GUI application. It boots into one that shows the hostname and IP address for the Pi, as well as displaying some simple tutorial instructions. It’s designed to connect to Visual Studio 2015, and allow a developer to push their application straight to the Pi. However, I don’t work with my Pi that way – I connect into it and configure/run it via a remote shell.

It’s possible to SSH straight into the Pi (as user Administrator, initially, until you set up some other users). You basically get a DOS prompt. Cool! What was less straightforward was getting files onto it.

What didn’t work:

  • SCP – I kept getting an “exec request failed on channel 0” error
  • Trying to get the Pi to download files using an Invoke-WebRequest via PowerShell running on the Pi. The version of PowerShell seems to be missing some modules.

What did work:

  • The Pi appears on the LAN as a Windows network share. You can use a Windows PC and put in \\192.168.1.10\c$ (or whatever your IP address is) and then login as minwinpc\Administrator with your password. Voila!
  • Similarly, on a mac, you can access it via the Finder using Go > Connect to Server smb://192.168.1.14/c$ (or whatever your IP address is). The Pi will also then appear under /Volumes/c$/
  • Once the share has been opened, it’s straightforward to copy files to and from the Pi.

Running Software on Windows IoT Core

As mentioned above, the standard way to get software running on Windows IoT is for Visual Studio to load it onto the Pi over the network. However, I’m more interested in running standard server apps that don’t rely on the Microsoft ecosystem, so I focussed my efforts on getting Node.js to run on the Pi.

Microsoft is doing some very cool stuff around supporting platforms like Node.js and even Python on Windows IoT. It’s still very much in its early days, but shows promise.

Here’s what I did:

  • I downloaded and installed the Node.js Tools for Windows IoT (v1.1) from GitHub. These were installed into C:\Program Files (x86)\Node.js (chakra)\
  • I copied the whole Node.js (chakra)\ installation directory over to the Pi into C:\Node.js\
  • I downloaded the ARM version of node.exe from the same GitHub page as above, which I copied over the top of the previous (Intel version of) node.exe in C:\Node.js\
  • Set up the APPDATA environment variable to be somewhere useful (it wasn’t set for me): set APPDATA=C:\Users\Public
  • Set up other useful environment variables for Node by running: C:\Node.js\nodevars.bat
  • Now commands like “npm install -s express” and “node test.js” work.

While I could run simple Hello World style programs with Node that wrote text out to the screen, I was unable to get working a slightly more advanced Node program that ran a basic webserver.

Conclusions

It was fun to see Windows 10 boot up on the Raspberry Pi. However, I was a little disappointed how limited it was, given how powerful a Pi is with the default Linux-based OS.

Microsoft’s approach to developing for the Raspberry Pi brings something new to the space, and may make the platform more accessible to developers who are already adept with Microsoft tools. Still, it would’ve been nice to see the basic image come with something immediately useful, if only the new Edge web browser (this would’ve make super-cheap Internet Explorer based kiosks really simple to create).

There’s the old saying that you should always wait for the third version of a Microsoft OS. I don’t know if we’ll need to wait that long for a compelling Microsoft OS on Raspberry Pi, but I am excited to see what Microsoft does with this in future.

Facebook Node SDK example

I’ve been writing some Node.js software to interact with Facebook recently. To do this, I just picked the first SDK listed in the Facebook developer’s page for Node.js. However, I couldn’t find a good example listing of how to use this SDK to iterate over multiple pages of results. So, this is a quick post that will hopefully serve as such an example.

The complete Node.js application can be downloaded from Github at https://github.com/aesidau/sbs-headlines, but I’ll walk through it step by step here. The application will list the first 1,000 news headlines from the SBS News page on Facebook. However, before any of this will work, you will need to get the fb and async modules, so start with something like:

npm install fb
npm install async

Also, I assume that you’ve set up a Facebook application over at https://developers.facebook.com/ and have its app id and app secret to hand. In fact, for this Node.js example, I am assuming that these values are stored in the environment variables FB_APP_ID and FB_APP_SECRET, respectively.

The first step in any Facebook API application is to use these app credentials to get an access token that can be used in later Facebook API calls. In this example, I’m going to get a basic access token that isn’t associated with a Facebook user, so will be able to obtain only public information. That’s all we need here, anyway.

// Acquire a new access token and callback to f when done (passing any error)
function acquireFacebookToken(f) {
  FB.napi('oauth/access_token', {
    client_id: process.env.FB_APP_ID,
    client_secret: process.env.FB_APP_SECRET,
    grant_type: 'client_credentials'
  }, function (err, result) {
    if (!err) {
      // Store the access token for later queries to use
      FB.setAccessToken(result.access_token);
    }
    if (f) f(err);
  }); // FB.napi('oauth/access_token'
}

This has been written as a function so we can call it later. Note that it uses a callback to indicate to the caller when the process has been completed, passing back any errors that came up.

So far, so obvious. Now that the access token is sorted, let’s look at what is required to iterate over a Facebook feed using the API.

I’m going to use the doUntil function in the async module. This enables iteration of functions that return results in callbacks. The other thing to note is that each call to the Facebook API will return a “paging” object that will contain a “next” attribute but only if there is another page of results to retrieve. This attribute can be parsed to construct the next Facebook API query to obtain the next page of results.

I have also included a test for if the access token has expired. This shouldn’t happen in a simple app where the access token was only just acquired. However, in many apps, the access token may have been acquired hours before. So, if this code is to be reused, it’s a good idea to deal with this case.

// Process the Facebook feed and callback to f when done (passing any error)
function processFacebookFeed(feed, f) {
  var params, totalResults, done;

  totalResults = []; // progressively store results here
  params = { // initial set of params to use in querying Facebook
    fields: 'message,name',
    limit: 100
  };
  done = false; // will be set to true to terminate loop
  async.doUntil(function(callback) {
    // body of the loop
    FB.napi(feed, params, function(err, result) {
      if (err) return callback(err);
      totalResults = totalResults.concat(result.data);
      if (!result.paging.next || totalResults.length >= 1000) {
        done = true;
      } else {
        params = URL.parse(result.paging.next, true).query;
      }
      callback();
    }); // FB.napi
  }, function() {
    // test for loop termination
    return done;
  }, function (err) {
    // completed looping
    if (err && err.type == 'OAuthException') {
      // the access token has expired since we acquired it, so get it again
      console.error('Need to reauthenticate with Facebook: %s', err.message);
      acquireFacebookToken(function (err) {
        if (!err) {
          // Now try again (n.b. setImmediate requires Node v10)
          setImmediate(function() {
            processFacebookFeed(f);
          }); // setImmediate
        } else if (f) {
          f(err);
        }
      }); // acquireFacebookToken
    } else if (f) {
      f(err, totalResults);
    }
  }); // async.doUntil
}

Lastly, we just need to wire these two functions together so that we get the access token, retrieve the results (i.e. the headlines from SBS World News Australia), and then print them out.

acquireFacebookToken(function (err) {
  if (err) {
    console.error('Failed authorisation to Facebook: %s', err.message);
  } else {
    console.log('Acquired Facebook access token');
    // Now let's do something interesting with Facebook
    processFacebookFeed('SBSWorldNewsAustralia/feed', function (err, results) {
      if (err) {
        console.error('Failed to retrieve Facebook feed: %s', err.message);
      } else {
        // Print out the results
        results.forEach(function (i) {
          var headline = i.message || i.name;
          // If it's an embedded video, possible there's no headline
          if (headline) {
            console.log(headline);
          }
        }); // results.forEach
      }
    }); // processFacebookFeed
  }
}); // acquireFacebookToken

And that’s it. I hope this has been useful for others. Grab the complete application from GitHub to try it out, but make sure you set up your environment variables for the App ID and App Secret first.