This is my fifth blog post covering Windows 10 IoT Core.
Previous posts:
Part 1: https://blogs.perficient.com/microsoft/2016/01/windows-10-iot-editions-explained/
Part 2: https://blogs.perficient.com/microsoft/2016/01/iot-development-with-windows-10-and-raspberry-pi-what-you-need/
Part 3: https://blogs.perficient.com/microsoft/2016/01/iot-development-with-windows-10-and-raspberry-pi-setting-up/
Part 4: https://blogs.perficient.com/microsoft/2016/01/iot-development-with-windows-10-and-raspberry-pi-hello-world/
In my previous post we being creating our first application for Raspberry Pi 2 running Windows 10 IoT Core. That was a simple “hello world” application. Now let’s build something more practical.
I think Raspberry Pi can make a convenient and inexpensive (less than $50!) computer powering an outdoor display (large display located somewhere outside, usually displaying ads) or indoor public display located in the conference hall, office, etc. These displays usually simply display a slideshow, but could also display something like Twitter feed, charts, etc. In our example we’ll be just doing a slideshow, but having a fully powered Windows Universal App we can make it display anything we want.
Let’s start from creating a new Universal Windows application in Visual Studio (like we did in part 4: https://blogs.perficient.com/microsoft/2016/01/iot-development-with-windows-10-and-raspberry-pi-hello-world/). Then don’t forget to set target platform to ARM, target device to Remote Machine and specify your Raspberry Pi name as remote machine name.
Then, open to MainPage.xaml and add an Image control inside application grid. This image control will be displaying our content on the screen:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Image Name="splashImage" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stretch="Uniform"/> </Grid>
To keep things simple, we going to source our images from Flikr. Flikr has a public RSS image feed which can return images by specific tags: https://api.flickr.com/services/feeds/photos_public.gne?tags=. In our application, I’ll be displaying images by tag “unicorn” (because everybody loves unicorns!).
Here is super simplistic class for reading and parsing Flikr image feed:
public sealed class FlickrReader { private const string FeedBaseUrl = "https://api.flickr.com/services/feeds/photos_public.gne"; private List<string> _images = null; private int _currentIndex = 0; private bool _loading = false; private readonly string _tags; public FlickrReader(string tags) { _tags = tags; } public async Task<string> GetImage() { if(_loading) { return null; } if(_images == null) { // prevent from loading images multiple times _loading = true; // build request to flickr image feed var url = FeedBaseUrl + "?tags=" + _tags; // load image feed var feed = await XmlDocument.LoadFromUriAsync(new Uri(url)); // parse out images from ATOM 1.0 feed _images = feed .DocumentElement .ChildNodes .Where(n => n.NodeName == "entry") .SelectMany(n => n.ChildNodes) .Where(n => n.NodeName == "link") .Where(l => l.Attributes.Any(a => a.NodeName == "rel" && (string)a.NodeValue == "enclosure")) .SelectMany(e => e.Attributes.Where(a => a.NodeName == "href") .Select(a => (string)a.NodeValue)) .ToList(); _loading = false; } if(_currentIndex >= _images.Count) { _currentIndex = 0; } return _currentIndex < _images.Count ? _images[_currentIndex++] : null; } }
FlckrReader will load images from feed at the first use of it, and then it would cycle through the list of images proving a sequence for the slide show.
public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); // create Flickr feed reader for unicorn images var reader = new FlickrReader("unicorn"); TimeSpan period = TimeSpan.FromSeconds(5); // display neew images every five seconds ThreadPoolTimer PeriodicTimer = ThreadPoolTimer.CreatePeriodicTimer( async (source) => { // get next image var image = await reader.GetImage(); if (image != null) { // we have to update UI in UI thread only await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // create and load bitmap BitmapImage bitmap = new BitmapImage(); bitmap.UriSource = new Uri(image, UriKind.Absolute); // display image splashImage.Source = bitmap; } ); } }, period); } }
In our example we creating a periodic time which would be loading and changing image on the screen every 5 seconds. Note that we can’t just update application UI from the timer thread (because that would cause an exception). We have to use CoreWindow.Displatcher to update UI.
This is it! Now you can deploy your application to your Raspberry Pi and enjoy a stream of unicorns on your TV.
Full source code of this application is available in my GitHub repository: https://github.com/starnovsky/IoTDisplay