How to win your first hackathon (and get a free Xbox from Microsoft)

czacha2-021

So, a while ago (10-11 Dec 2016) we assembled a team for Hackathon of Things (HoT), organized by .NET Groups in Poland. The main goal was simple: to combine these three technologies:

  • Microsoft Azure
  • Xamarin
  • Internet of Things

A hacker is someone who looks at a puzzle and finds an unexpected way to solve it without following the accepted methodology.

Ian Armstrong, UX Lead at EMC’s Experience Studio

Oh man, did we “find an unexpected way to solve it without following the accepted methology”… but let’s start from the beginning!

The Division

Yes, that name sucks – hey, what else could we do? A random name had to be picked, so we just went with the first idea because we had no better one. The team consisted of 4 members:

  • Paweł Chochura
  • Arkadiusz Rozmus (me)
  • Kamil Dąbrowski
  • Stefan Dyjak

The Plan

So, our first idea was “hey, why don’t we just write a game in Xamarin and call it a day?”. On day -1 we met at the campus and created a new Hello World project in Visual Studio. It even compiled and ran in the emulator. Great! Satisfied with our first results, we called it a winner. “Okay guys, we’ll figure out the rest later on”.

The Journey

7 am, I woke up. Following the path of success, I even managed to eat breakfast before rushing for the train (departing at 8:45). Everyone ready, let’s go. 3 hours later, we’re in Lublin. Hanged around the city for a while, stopped at a local bar “św. Michał” (click). Great beer (we picked chocolate-flavoured), here’s a photo of the breath-taking inside:

Source: SZLEZAK - Krzysztof Szlęzak
Source: SZLEZAK – Krzysztof Szlęzak

Where the hell are we?

Hour by hour, finally it was finally about time to go for the actual event. The hackathon started at 4 pm, so we headed for Maria Curie-Skłodowska University, Faculty of Mathematics, Physics and Computer Science. Took a while, about half an hour on foot, but we were in on time. Actually, it was 25 minutes before time. Seems like nobody’s at home. The place is all dark, some closed doors, hey… where’s the hackathon? We asked the porter for directions. “Oh sure, just head for the second floor”. Still, it’s dark everywhere. We found a guy in one of the rooms, fixing a computer by the looks of it.

“Good evening, we’re looking for the hackathon, can’t find the place”

Oh, you’re already there? Great. We’ll… it’s here, just wait a little, you came in first.

Also, when we finally found the place, we realized we could just come from the other side and go upstairs instead of walking all around the building. Oopsie.

Sorry for the blur (potato quality phone camera)

Oh, they also have a nice sort of glass panel on one of the corridors. No idea what it could be for (my first thought was it’s an elevator, but it’s not. It’s just a wall). Whatever, it looks cool, I guess.

The glass panels of pure badassery
The glass panels of pure badassery

Getting started

It turned out everything was fine. That’s good. Some introduction ceremonies, sponsors, all these kinda things. Let’s get to coding. First of all: design. It’s a good idea to know what you’re doing. So we sketched out the game mechanics, the objectives, some technical ideas (to solve problems we already see coming), and some “would be nice to add if we have enough time” thingies. All good.

Whiteboards are cool, make sure to get one for your team!
Whiteboards are cool, make sure you get one for your team!

The jury comes in to look at our progress, asks some questions.

“Hey guys, it looks cool, but it’s a hackathon of things. You’re supposed to be making some intelligent devices which interact with your phone, that kinda stuff”

Oh, snap. Okay, let’s rethink our plan. Why don’t we just keep going like nothing happened? Probably a bad idea… well, let’s get some devices and try the whole IoT thing.

One trip to fetch some cool things and we’re back with a Raspberry Pi 3, with a memory card for it, couple of Arduinos, and a nice little kit called GrovePi. Basically it’s like shields for Arduino. This one gives us connectivity with ready to use sensors, and some really simple software to get it running. Sort of.

First attempt, sticked the card in. Crap, we don’t even have a HDMI monitor to see what’s going on. “Hey, how about that projector over there?”, I ask. Booting it up, seems like it’s working. Some initial config, managed to connect it to our WiFi network, enabled SSH so we could develop comfortably from our computers.

Here’s some minimal Python “blink a LED” code, from the documentation included with GrovePi:

import time
from grovepi import *

# Connect the Grove LED to digital port D4
led = 4

pinMode(led,"OUTPUT")
time.sleep(1)

while True:
    try:
        digitalWrite(led,1)     # Send HIGH to switch on LED
        time.sleep(1)

        digitalWrite(led,0)     # Send LOW to switch off LED
        time.sleep(1)

    except KeyboardInterrupt:   # Turn LED off before stopping
        digitalWrite(led,0)
        break
    except IOError:             # Print "Error" if communication error encountered
        print "Error"

Cool, it blinks. Now, how the heck are we going to add the Xamarin and Azure part? First, let’s switch to Windows 10 IoT Core, will probably be easier to code in C# than Python (yes, I don’t know a single thing about Python). Since I’m a Fast Ring Windows Insider, I have access to beta stuff – turns out there’s a beta version of IoT Core for Raspberry Pi 3. Took a while to download, okay it starts installing. Failed. What? Wait, do that again. Success. Weird, but shoved it into the Pi and it works. Well, if it works, it works, I guess?

Connected to it no problem, there’s even a nice remote display app. Cool. Now I just need to compile the driver library, add a NuGet package, set up remote machine IP in Visual Studio and we’re in business.

But… what are we doing, again?

So, with everything set up we just straight up copied “HelloWorldBlinky” from the included example and went from there. The code is fairly easy to grasp, here are some highlights:

// Tons of usings here, we got rid of Linq and Net.Http
// Way overkill for our needs so far

// GrovePi Libraries Needed
using GrovePi;
using GrovePi.Sensors;
using Windows.System.Threading;

namespace HelloWorldBlinky {
    public sealed class StartupTask : IBackgroundTask {
        // Initiate the LED on Digital Pin 2
        ILed led = DeviceFactory.Build.Led(Pin.DigitalPin2);
        public async void Run(IBackgroundTaskInstance taskInstance) {
            while (true) {
                Task.Delay(1000).Wait(); // Delay 1 second
                try {
                    // If the LED is on, turn it off.  If the LED is off, turn it on.  
                    led.ChangeState((led.CurrentState == SensorStatus.Off) ? SensorStatus.On : SensorStatus.Off);
                }
                catch (Exception ex) { // catch me if you can!
                }
            }
        }
    }
}

Then, once that was running no problem, we started playing around with other sensors. Luckily, they’re all the same for us – I love the GrovePi library. Ultrasonic sensor? No problem. Just do:

IUltrasonicRangerSensor sensor = DeviceFactory.Build.UltraSonicSensor(Pin.DigitalPin3);

… and whenever you need to read from it,

sensor.MeasureInCentimeters();

gives you a nice, ready to use integer. Cool!

 

Now, how about adding a buzzer and making it beep whenever you’re close? No problem:

while (true) {

    // hey, first piece of dirty code!
    // turn the buzzer off just in case

    buzzer.ChangeState(SensorStatus.Off);

    if (sensor.MeasureInCentimeters() < 30) {

        // then turn it back on if it should be on
        buzzer.ChangeState(SensorStatus.On);

    }

}

Idea strikes…

Wait, how about we put it on a chair just next to a door and make it a “smart anti-theft alarm”?

Just add a Xamarin app for changing the “settings” (distance, should it beep or not) and notifications… Hey, that could actually work! Change the settings in the app, push it to Azure, then make the board load it back. Genius!

Writing an API – the dirty way

So we need to put something on Azure to store our settings. At that point, it’s about 2 am and we’re slowly losing sanity. Logged in on Azure, started a 14-day trial, will be more than enough. Turns out on a trial account you don’t get a SQL database. Snap

Since I’m still pretty new to object-oriented programming and all the “write clean code” thing, I’m going to make this work, whatever it takes. New PHP app, how about if you won’t give me a database, I’ll just keep stuff in a plain old text file, status.txt

Warning: following code might be considered offensive by Java and/or C# developers. If you feel nausea from reading this, please skip to the next paragraph.

Great, onto the API. My set.php is a crude script that saves stuff it gets in the URL into status.txt. Let’s have a look:

<?php
// some warning popped up, shut it off before anyone notices
error_reporting(~E_NOTICE);

// open the file for writing
$settings = file('status.txt');
$file = fopen("status.txt", "w");

// load current settings so we can keep them
$s_beep = $settings[0];
$s_led = $settings[1];
$s_dist = $settings[2];

if (isset($_GET["s_beep"])) {
 // we're changing beep!
 $s_beep = $_GET["s_beep"];   // load from URL
 fwrite($file, $s_beep."\n"); // write to file, add a new line
} else {
 // we're not changing beep!
 fwrite($file, $s_beep);      // write whatever was there
}
if (isset($_GET["s_led"])) {
 // same for LED
 $s_led = $_GET["s_led"];
 fwrite($file, $s_led."\n");
} else {
 fwrite($file, $s_led);
}
if (isset($_GET["s_dist"])) {
 // same for distance
 $s_dist = $_GET["s_dist"];
 fwrite($file, $s_dist."\n");
} else {
 fwrite($file, $s_dist);
}
fclose($file); // close the file
echo "OK";     // all good!
?>

So, after loading set.php?s_beep=1&s_led=0&s_dist=25, we get a status.txt which looks like this:

1
0
25

Perfect. This should be compact enough not to kill the performance, at least I hope so.

Xamarin – let’s make an app!

Meanwhile, I sent Paweł the API “documentation so he could start working on the Android app.

 

(to be continued…)

Leave a Reply

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