Skip to main content

Cloud

IoT Development with Windows 10 and Raspberry Pi: Public Display

IMG_20160111_163542This 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.

Now we need to plug in FlickReader to the application UI. Let’s add the following to MainPage.xaml.cs:
    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

IMG_20160111_163644IMG_20160111_163721IMG_20160111_163756

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Stan Tarnovskiy

Solutions Architect at Perficient

More from this Author

Follow Us
TwitterLinkedinFacebookYoutubeInstagram