Monday, 25 April 2016

PucciThe.Dog – Python/Flask on an RPI

Overview

Flask is an amazing little Python web micro-framework for those who aren’t familiar with it. It allowed me to build out this entire application in about 8 hours of total dev time (including a whole bunch of time just not quite grokking flask-login). The minimal goals I wanted to achieve was to expose a very basic web presence for Pucci (the dog), along with building a very basic puppy cam. Since I had an old Raspberry Pi lying around, I figured that this might be the ideal project to use it for.

Please feel free to take a look at the code

Bill of Materials

  1. Raspberry Pi
  2. Microsoft LifeCam NX-3000
  3. Sweetbox Case (optional)

The Plumbing

In the interest of making this work as quickly as possible, the actual picture-taking logic is just a shell script running in cron (specifically once every 5 minutes). It likewise will examine all of the files in the directory and delete any that are more than a day old. The real magic is actually done by fswebcam as documented here.

fswebcam -r 320x240 --jpeg 80 -D 3 -S 13 \ 
/home/pi/poochpics/$DATE.jpg

Technically the webcam should support higher resolution pictures, but I suspect that it isn’t quite as compatible as I was led to believe it was. The -D 3 -S 13 are very important for me as the camera was corrupting 70+% of the images that it was capturing. These arguments will first delay the capture for 3 seconds and then skip the first 13 frames captured, finally generating a photo based on the 14th frame captured. This numbers were very scientifically found by simply playing with the webcam until it was returning reliable results 100% of the time (it is possible that others will be able to operate the webcam without any delay or skipping any frames).

Now that all of the photo generation and automatic purging of old images is handled the actual responsibilities for the web application are pretty slim: basically just a regular old mostly static web page with the ability to login to a secure area which will have the actual photos on display.

I made the jump to almost 100% Windows at home (since I have been working on Windows machine for pretty much my entire career), and decided to use this project as an excuse to try out the Python Tools now available in Visual Studio (spoiler alert: they are awesome). I can’t say that I have ever really used an IDE for Python development before (traditionally I’ve done it in a mix of Vim and Sublime Text), so I can’t compare it to some of the other Python IDEs out there, but as someone who gets paid to do C# in Visual Studio 2015, the experience was very nice.

Implementing the Web Application

In order to actually get things working I just started with the default template that comes with VS for Flask + Jinja2 templating (I contemplated doing this project as an Angular app with a Flask RESTful backend, but decided against it). The code is pretty basic especially considering the entire application only consists of 4 routes and doesn’t really do any magic (there isn’t even a CRUD component to it). The one thing that isn’t exactly standard was my choice for authentication. As I mentioned earlier, this application does use flask-login, and while my original thought was to just hardcode the credentials, I ended up not going down that path as I couldn’t come up with a non-hacky way to persist the credentials that wasn’t less complex than just adding a SQLite database with some credentials tossed into it. To that end if you look at __init__.py you’ll notice the need to have a SQLite db called test.db. This database just has a single table called “user” which will store ids, usernames, emails, and bcrypt hashed passwords:

Deployment

It really is an exciting time to be alive when I can build something on a Core i7 desktop with 32 GB of RAM, and then relatively effortlessly deploy it onto a computer the size of a microcontroller with a whopping 512MB of RAM and a sub-1Ghz ARM processor. The deployment is actually pretty standard: it’s just Apache2 with mod_wsgi and the appropriate wiring as described here. The most interesting part of all this is probably the way that DNS is being handled: Namecheap now offers Dynamic DNS, so I have ddclient running on the Pi, automatically updating my home IP address to Namecheap’s DNS servers. If you want to try it out for yourself and give me a little boost in the wallet as well sign up here.

The only thing I’m a little nervous about with this setup is whether or not the relatively underpowered RPi really is going to do that well connected to the public internet. That being said, it is pretty heavily firewalled, with only port 80 exposed so its a fairly limited attack surface for any of those internet hooligans.

I hope you enjoyed reading about my very small flask application on a RPi, please reach out to me on Twitter @lukebearl or head over to Github.

Saturday, 9 April 2016

One Month Retrospective

One Month In

The company I work for recently started a new initiative: a brand new piece of software completely divorced from the software we traditionally worked on. I along with three of my colleagues were selected to lead the entire architecture and build out all of the core features. All four of us are somewhat experienced developers, but none of us has ever worked on an architecture team at the very beginning of a software project which is very much enterprise-class software.

Just to not confuse anyone, when I say enterprise-class or “big” software I’m specifically referring to software that is expected to grow to encompass multiple modules and have a code base in excess of 500 KLOC. For smaller applications the concerns I bring up here probably aren’t relevant. In this article I am specifically referring to software which is (hopefully) going to have a lifetime measured in many years if not decades with hopefully only minimal refactoring of the core structure.

What We Did

As happens so often in the software world, we were given a whole bunch of pretty “loose” requirements, and it was up to the four us with minimal direction to prioritize and implement everything that we needed. The project basically ended up being implemented in the following order:

  1. Project Layout (we used the Onion Architecture, which I have become a very big fan of)
  2. Initial Core Application Services
  3. Some development niceties that are ASP.NET specific (like things to ensure that we always have an Anti-Forgery Token, etc.)
  4. The Authentication and Authorization systems (using ASP.NET Identity)
  5. The logging framework
  6. Site Navigation and initial site pages for core things

What We Probably Should Have Done

While everything works with the order we did the work in, it is also causing a number of issues because as we finish certain tasks we then have to go back and update other code. The most painful item on this list is the logging framework. I am now thoroughly convinced that one of the first things that should be setup in any new large project is a logging framework. It doesn’t help much for development at the very beginning, but as soon as your first release happens and you push the application live to a web server or anywhere that isn’t a developer’s desktop that logging framework becomes your best friend when something breaks. We happen to be a 100% Microsoft shop, so we could always do something fancy with remote debugging, but that has issues of its own (including ensuring that you can reproduce the issue).

Lessons Learned

Large enterprise-scale software is challenging to design, there will always be a number of moving parts. As developers and architects it makes our lives easier if we take a step back from the initial problem and try to see if there are dependencies which don’t necessarily block development, but which will require a fair amount of rework in order to incorporate after the fact. Logging is probably an example that will be true for just about every software project out there, but another great example is a localization framework (I developed one that doesn’t use resx files because I don’t like that approach). At minimum before any views are created, the localization should be fleshed out, otherwise there will be a massive amount of rework (depending on what the view contains it may be almost a full rewrite).

I hope that anyone who reads this can not repeat the mistakes made, although these mistakes are hardly the most costly out there.