Last week I had lunch with a friend to talk about the projects we’re working on (and how I might be able to pursue one of these professionally) and one of the things we talked about was developing a line of devices that provide most of the features of things like connected thermostats, light switches, doorbells, etc. without requiring you to send data to “the cloud”. I talked about my plans to start by building a thermostat along these lines, but he suggested I start with something simpler. At the moment I didn’t understand that he was talking about the big picture, so I focused on rebutting his arguments on a technocal level.
It wasn’t until a few hours later that it dawned on me what he was getting at, but when it did, my brain kind of exploded and I saw how some of my best projects in the past may have been leading-up to this one.
When I realized that what my friend was getting at was that I start with the simplest device that could then serve as a building-block for consequitive designs, I stopped thinking about each device individually and started seeing them as a progression where each new device would build on the foundation of the last. This perspective change made me think a lot more about the software side of the devices and think about how it could be composed in layers that can be built-up or peeled-away to match the complexity and capabilities of each device. I then realized that I had already created and tested these layers long ago without even realizing that they were related.
Now it seems obvious, but isn’t that how hindsight always is?
The first project was RESTduino, which provides an HTTP interface to the GPIO of a networked microcontroller. This approach is somewhat commonplace now, but it was novel (dare I say, original?) when I first implemented it almost a decade ago. The second project was JSFS, an HTTP interface for storage (and more, but we’ll get into that later). I developed JSFS to address the specific problem of storing data for client-side Javascript applications. Again there are now many technologies like this, but when I started JSFS the options were slim, and the ones that existed were proprietary and certainly not portable. JSFS evolved into much more than a simple storage system, but at the heart of it was simply an HTTP interface to hardware resources, not completely unlike RESTduino.
Why I didn’t see the relationship between these two project before I’ll never know, but when I started thinking about creating a line of “smart” devices it clicked, and the more I thought about it I realized that a combination of these two systems could provide the “operating system” for everything from a microcontroller driving a lightswitch to a high-performance compute cluster.
I should elaborate a little on that last part. One of the features that I designed for JSFS but never implemented was the ability to execute code (JSFSX, if you will). In basic terms any file containing sourcecode (Javascript, Python, C Rust, etc.) could be executed by issuing a special HTTP request. In addition to executing this code, JSFS could use its federation features to distribute execution across a group of JSFS servers. Since JSFS already stores and distributes data, this parallel execution model would works not unlike Apache Spark, but simpler and with less programming language restrictions. I didn’t pursue this feature while JSFS was under active development because at the time the demand by its users was focused on storage, and the industry didn’t seem very interested in high-performance computing (things have changed in the last few years…)
So where is all this going? Well, as the programming model for RESTDuino/JSFS(X) fits with the needs of the devices I plan to design, I’m going to combine the two and re-implement it in Python, because Python is avaliable on all the processing architectures I’m targetting, from embedded microcontrollers to full-blown general-purpose computers. A microcontroller running the software I’m describing on top of MicroPython will have the same programming interface as a supercomputer running the same. Different devices will of course have different features, but these will all share the same API structure, and will all provide the same basic level of functionality.
Going back to the conversation that started this all, my next step is to write a version of this software (which doesn’t even have a name yet) that will run on hardware designed for the simplest of all these devices: a switch. This could be as simple asn a ESP8266 and a relay, but I want to make sure that what I’m building has the potential to be re-used as a building block for more sophisticated devices an as such I’m planning on building a switch that is a little more feature-rich than it needs to be. If I learned anything from watching the rise of devices like the iPhone, it’s that there’s value in providing hardware that you might not need immediately, especially if you’re designing something that will allow other programmers to devise new and unforseen applications for.