Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Brewing Beer With a Raspberry Pi: Moving to ITemperatureClient Interface

DZone's Guide to

Brewing Beer With a Raspberry Pi: Moving to ITemperatureClient Interface

Using Windows 10 IoT and a Raspberry Pi to emulate temperatures and situations that are not easily reproducible.

· IoT Zone
Free Resource

Learn how Bluetooth mesh helps you create industrial-grade networks. Download the mesh overview.

My previous blog post Brewing Beer With a Raspberry Pi: Measuring Temperature introduced you to my simple solution for measuring temperatures. In this blog post, we go a step further and make some modifications to the solution architecture so we don’t have to keep sensors connected all the time and, as a result, we can also emulate temperatures and situations that are not easy to produce in the home or office.

In short, we'll do the following:

  1. We define interface for client classes that measure temperatures.
  2. We define model class for measurements (value, time, device id),
  3. We create one client to read sensors and one client to return fake values,
  4. We modify start-up class so it uses one of the client classes.

What we actually do is simple code organization task that results in better and more flexible arcitecture.

ITemperatureClient interface

To have more than one way to read temperatures I defined interface ITempratureClient.

internal interface ITemperatureClient : IDisposable
{
    IEnumerable<Measurement<double>> Read();
}

It has just one method to read temperatures from sensors. To avoid using Tuples and other unearthly code constructs I defined generic class Measurement<T>.

internal class Measurement<T>
{
    public string DeviceId { get; set; }
    public DateTime Time { get; set; }
    public T Value { get; set; }
}

With measurement we provide also device ID so we can match measured value with device where it came from.

Client for DS18B20

First we write client class to get temperatures from real sensors.

internal class TemperatureClient : ITemperatureClient
{
    private OneWireDeviceHandler _handler;
    private IEnumerable<DS18B20> _devices;

    public IEnumerable<Measurement<double>> Read()
    {
        var temperatures = new List<Measurement<double>>();

        if (_handler == null)
        {
            _handler = new OneWireDeviceHandler(false, false);
            _devices = _handler.OneWireDevices.GetDevices<DS18B20>();
        }

        var stamp = DateTime.Now;

        foreach (var device in _devices)
        {
            var result = device.GetTemperature();

            var temp = new Measurement<double>();
            temp.DeviceId = device.OneWireAddressString;
            temp.Time = stamp;
            temp.Value = result;

            temperatures.Add(temp);
        }

        return temperatures;
    }

    public void Dispose()
    {
        if (_handler != null)
        {
            _handler.Dispose();
            _handler = null;
            _devices = null;
        }
    }
}

This code is just taken from StartupTask class we created in blog post Measuring temperature with Windows 10 IoT Core and Raspberry Pi.

Fake Client

Now let’s create fake client we can use when thermal solution is not connected to RaspberryPi or when thermal solution is not working for some reason.

internal class TemperatureClientEmulator : ITemperatureClient
{
    public IEnumerable<Measurement<double>> Read()
    {
        var temperatures = new List<Measurement<double>>();
        var now = DateTime.Now;

        temperatures.Add(new Measurement<double> { 
                         DeviceId = "1", Time = now, Value = 12 });
        temperatures.Add(new Measurement<double> { 
                         DeviceId = "2", Time = now, Value = 20 });

        return temperatures;
    }

    public void Dispose()
    {
    }
}



This class just returns some numbers and this is minimum we need to make our code think that temperatures are coming in from somewhere.

Some scenarios for fake client:

  • Emulate some previously measured set of temperatures.

  • Emulate extreme temperatures you cannot produce in your home or office.

  • Emulate faulty sensors.

  • Emulate unexpected situations.

Startup Task

As a last thing let’s make start-up task work with new client classes.

public sealed class StartupTask : IBackgroundTask
{
    private Timer _timer;
    private ITemperatureClient _tempClient;
    private bool _isClosing = false;

    public void Run(IBackgroundTaskInstance taskInstance)
    {
        taskInstance.Canceled += TaskInstance_Canceled;

        _tempClient = new TemperatureClient();
        _timer = new Timer(TemperatureCallback, null, 0, 5000);

        while (!_isClosing)
        {
            Task.Delay(2000).Wait();
        }
    }

    private void TemperatureCallback(object state)
    {
        foreach (var temp in _tempClient.Read())
        {
            Debug.WriteLine(temp.Time + " " + temp.DeviceId + ": " + temp.Value);
        }
    }

    private void TaskInstance_Canceled(IBackgroundTaskInstance sender, 
                                       BackgroundTaskCancellationReason reason)
    {
        _isClosing = true;

        if (_timer != null)
        {
            _timer.Dispose();
            _timer = null;
        }

        if (_tempClient != null)
        {
            _tempClient.Dispose();
            _tempClient = null;
        }

        sender.GetDeferral().Complete();
    }
}


Now we can choose what implementation we want to use for thermal solution.

Wrapping up

Now we have way better architecture for our background application that runs on Windows 10 IoT Core. We can use real device if needed and when we don’t have it we can use fake client to emulate reading of sensors. Our fake class is extremely primitive but we can modify it so it also meets our more complex needs.

Brewing Beer With a Raspberry Pi: Table of Contents

  1. Brewing Beer With a Raspberry Pi: Measuring Temperature
  2. Brewing Beer With a Raspberry Pi: Moving to ITemperatureClient Interface
  3. Brewing Beer With a Raspberry Pi: Measuring Cooling Rate
  4. Brewing Beer With a Raspberry Pi: Making Cooling Rate Calculations Testable  
  5. Brewing Beer With a Raspberry Pi: Reporting Measurements to Azure IoT Hub
  6. Brewing Beer With Raspberry Pi: Stream Analytics
  7. Brewing Beer With Raspberry Pi: Visualizing Sensor Data  
  8. Brewing Beer With Raspberry Pi: Building a Universal Windows Application

For a deeper look into Bluetooth mesh, check out this technical insight for developers.

Topics:
windows 10 ,iot ,raspberry pi

Published at DZone with permission of Gunnar Peipman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}