Building ASP.NET Core “Hello, blinky” IoT application

After installing ASP.NET Core 3.0 on Windows 10 IoT Core and getting my ASP.NET Core 3.0 LED controlling application work I wanted to finish this journey with some classics – Hello, blinky application.

Source code for ASP.NET Core “Hello, blinky” is available in my Github repository gpeipman/AspNetCoreHelloBlinky. Feel free to explore the code and make it work on your board.

Controlling LED with ASP.NET Core 3.0

Turning LED on and off was actually simple thing to do. I took the code from LED blink example of .NET Core IoT libraries and made it work with ASP.NET Core 3.0.

Wiring is shown here. It’s same as for .NET Core IoT libraries samples and credits for diagram go to their guys.

Wiring for ASP.NET Core "Hello, Blinky"

Here’s my LED controlling client.

public class LedClient : IDisposable
{
    private const int LedPin = 17;

    private GpioController _controller = new GpioController();
    private bool disposedValue = false;
    private object _locker = new object();

    public LedClient()
    {
        _controller.OpenPin(LedPin, PinMode.Output);
        _controller.Write(LedPin, PinValue.Low);

        IsLedOn = false;
    }

    public bool IsLedOn { get; private set; }

    public void LedOn()
    {
        lock (_locker)
        {
            _controller.Write(LedPin, PinValue.High);

            IsLedOn = true;
        }
    }

    public void LedOff()
    {
        lock (_locker)
        {
            _controller.Write(LedPin, PinValue.Low);

            IsLedOn = false;
        }
    }      
       
    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                _controller.Dispose();
            }

            disposedValue = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }
}

It’s small class thas injected to ASP.NET Core controllers as singleton. It holds internal instance of GpioController. LedOn() and LedOff() methods switch LED on or off.

Getting ASP.NET Core “Hello, blinky” alive

Blinking LED was a little bit more challenging task because I needed to wind up some code that blinks LED automatically while control goes back to ASP.NET Core web application.

I decided to write client class for “Hello, blinky” and use Task to keep LED blinking.

public class LedBlinkClient : IDisposable
{
    private const int LedPin = 17;
    private const int LightTimeInMilliseconds = 1000;
    private const int DimTimeInMilliseconds = 200;

    private bool disposedValue = false;
    private object _locker = new object();
    private bool _isBlinking = false;

    private Task _blinkTask;
    private CancellationTokenSource _tokenSource;
    private CancellationToken _token;

    public void StartBlinking()
    {
        if(_blinkTask != null)
        {
            return;
        }

        lock (_locker)
        {
            if(_blinkTask != null)
            {
                return;
            }

            _tokenSource = new CancellationTokenSource();
            _token = _tokenSource.Token;

            _blinkTask = new Task(() =>
            {
                using (var controller = new GpioController())
                {
                    controller.OpenPin(LedPin, PinMode.Output);

                    _isBlinking = true;

                    while (true)
                    {
                        if (_token.IsCancellationRequested)
                        {
                            break;
                        }

                        controller.Write(LedPin, PinValue.High);
                        Thread.Sleep(LightTimeInMilliseconds);
                        controller.Write(LedPin, PinValue.Low);
                        Thread.Sleep(DimTimeInMilliseconds);
                    }

                    _isBlinking = false;
                }
            });
            _blinkTask.Start();               
        }
    }

    public void StopBlinking()
    {
        if(_blinkTask == null)
        {
            return;
        }

        lock (_locker)
        {
            if(_blinkTask == null)
            {
                return;
            }

            _tokenSource.Cancel();
            _blinkTask.Wait();
            _isBlinking = false;

            _tokenSource.Dispose();
            _blinkTask.Dispose();

            _tokenSource = null;
            _blinkTask = null;
        }
    }

    public bool IsBlinking
    {
        get { return _isBlinking; }
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                StopBlinking();                   
            }

            disposedValue = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }
}

Before we can try out “Hello, blinky” we have to make some changes to web application.

In ConfigureServices() of Startup class we have to register LedBlinkClient as singleton.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddSingleton<LedBlinkClient>();
}

We need to inject LedBlinkClient to HomeController and create actions to start and stop blinking.

public class HomeController : Controller
{
    private readonly LedBlinkClient _blinkClient;

    public HomeController(LedBlinkClient blinkClient)
    {
        _blinkClient = blinkClient;
    }

    public IActionResult Index()
    {
        ViewBag.BlinkState = _blinkClient.IsBlinking ? "Blinking" : "Not blinking";

        return View();
    }

    public IActionResult StartBlinking()
    {
        _blinkClient.StartBlinking();

        return RedirectToAction(nameof(Index));
    }

    public IActionResult StopBlinking()
    {
        _blinkClient.StopBlinking();

        return RedirectToAction(nameof(Index));
    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error()
    {
        return View(new ErrorViewModel
        {
            RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier
        });
    }
}

Index view of HomeController will display blinking state of LED and links to start and stop blinking.

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Hello, blinky!</h1>
    <p>Learn about
        <a href="https://gunnarpeipman.com/aspnet/aspnet-core-hello-blinky">
            how to blink LED with ASP.NET Core
        </a>.
    </p>
    <p>Led is <strong>@ViewBag.BlinkState</strong></p>
    <p>
        <a asp-action="StartBlinking">Start blinking</a> | <a asp-action="StopBlinking">Stop blinking</a>
    </p>
</div>

With this our work is done. Open PowerShell, log in to your RaspberryPi and run web application.

Wrapping up

Using ASP.NET Core 3.0 and .NET Core IoT libraries on RaspberryPi enables us to write a code that communicates with sensors and other devices connected to board. ASP.NET Core 3.0 is maybe not an ideal host for this task but if we need browser based UI to control something then it’s way to go in my opionion. Getting “Hello, blinky” work wasn’t complex task and “Hello, blinky” has been stable this far on my board.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    Leave a Reply

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