Skip to content

Instantly share code, notes, and snippets.

@yaakov-h
Created December 6, 2015 09:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yaakov-h/0caad10add0b2935a85d to your computer and use it in GitHub Desktop.
Save yaakov-h/0caad10add0b2935a85d to your computer and use it in GitHub Desktop.
Win10 IoT code for Pi Menorah
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.Devices.Gpio;
using Windows.System.Threading;
namespace PiMenorah
{
public sealed class StartupTask : IBackgroundTask
{
// Board GPIO pin numbers that are connected to the LEDs.
static int[] ChannukiaPinNumbers => new[] {
21, // GPIO pin that controls the shamash AND the 1st light.
20, // GPIO pin that controls the 2nd light.
16, // GPIO pin that controls the 3rd light.
12, // GPIO pin that controls the 4th light.
25, // GPIO pin that controls the 5th light.
24, // GPIO pin that controls the 6th light.
18, // GPIO pin that controls the 7th light.
23 // GPIO pin that controls the 8th light.
};
static TimeSpan HttpCheckTimeInterval => TimeSpan.FromMinutes(1);
// URL to check. Should return a plain text string indicating what number of LEDs to light
// (plus the shamash)
const string NightCountUri = "https://some.url.here";
BackgroundTaskDeferral deferral;
GpioPin[] pins;
ThreadPoolTimer timer;
CancellationTokenSource cancellationTokenSource;
public async void Run(IBackgroundTaskInstance taskInstance)
{
// I have no idea if this is a valid pattern for a background task, but YOLO.
cancellationTokenSource = new CancellationTokenSource();
taskInstance.Canceled += (sender, reason) =>
{
cancellationTokenSource.Cancel();
cancellationTokenSource.Dispose();
cancellationTokenSource = null;
};
// Let us keep running in the background indefinitely, or until our task is canceled.
deferral = taskInstance.GetDeferral();
cancellationTokenSource.Token.Register(deferral.Complete);
var gpio = await GpioController.GetDefaultAsync();
Debug.Assert(gpio != null);
pins = OpenPins(gpio, ChannukiaPinNumbers);
cancellationTokenSource.Token.Register(DisposePins);
await RunTestPatternAsync();
SetNights(pins, 8);
// Note that this timer first runs after {HttpTimeCheckInterval}, so the startup procedure is:
// 1. Test pattern, 5 times.
// 2. 8 LEDs
// 3. {HttpCheckTimeInterval} later, the amount of LEDs as determined by our command and control server.
// 4. Every {HttpCheckTimeInterval} after that, the amount of LEDs as determined by our command and control server.
// (pretty much just control, no commanding going on).
timer = ThreadPoolTimer.CreatePeriodicTimer(GetCurrentNightCount, HttpCheckTimeInterval);
cancellationTokenSource.Token.Register(timer.Cancel);
}
async void GetCurrentNightCount(ThreadPoolTimer timer)
{
using (var http = new HttpClient())
{
try
{
var response = await http.GetStringAsync(NightCountUri);
var value = int.Parse(response?.Trim());
SetNights(pins, value);
}
catch(Exception ex)
{
Debug.WriteLine(FormattableString.Invariant($"{ex.GetType().FullName}: {ex.Message}"));
SetNights(pins, 8);
}
}
}
static void SetNights(GpioPin[] pins, int nights)
{
Debug.Assert(pins != null);
nights = Math.Min(nights, pins.Length);
// Turns LEDs 0 - {nights} on.
var i = 0;
for (; i < nights; i++)
{
pins[i].Write(GpioPinValue.Low);
}
// Turn LEDs {nights} - {max} off;
// i = nights at this point.
for(; i < pins.Length; i++)
{
pins[i].Write(GpioPinValue.High);
}
}
static GpioPin[] OpenPins(GpioController controller, int[] pinNumbers)
{
var pins = new GpioPin[pinNumbers.Length];
for (int i = 0; i < pinNumbers.Length; i++)
{
var pinNumber = pinNumbers[i];
var pin = controller.OpenPin(pinNumber, GpioSharingMode.Exclusive);
Debug.Assert(pin != null);
pin.SetDriveMode(GpioPinDriveMode.Output);
pins[i] = pin;
}
return pins;
}
async Task RunTestPatternAsync()
{
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < pins.Length; j++)
{
pins[j].Write(GpioPinValue.Low);
await Task.Delay(100);
}
for (int j = 0; j < pins.Length; j++)
{
pins[j].Write(GpioPinValue.High);
await Task.Delay(100);
}
}
}
void DisposePins()
{
if (pins != null)
{
for (int i = 0; i < pins.Length; i++)
{
pins[i]?.Dispose();
}
}
pins = null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment