Giving your Raspberry Pi a REST
The core code behind many of my Pi Projects.
I am breaking up this discussion over a few articles. There is a lot to talk about here ranging from how the components work, how we secure them from attack as well as tips on how to design and debug these kinds of systems.
Part 1 - Overview and Introduction
I have been using the Raspberry Pi platform to create a number of home-brew Internet of things (IoT) projects, and made a lot of the code available open-source on Github. Maybe some of it becomes useful to those who are also building projects from scratch.
So far I have published the code for:
pumphouse - Inverter and battery backup for a well pump and cistern.
insteonserver - Home control system
chickencoop - Automated chicken coop door.
And in the works:
garage door - secure remote garage door opener
garden - automated gardening watering system.
magic mirror - combined home IoT status panel
CANbus monitor - vehicle status panel
What all these projects all have a common is that they include an iOS client and a Linux server component that communicate using a RESTful API. REST is short for REpresentational State Transfer. An interface layered over the HTTP/S protocol.
And yes… there are other ways to communicate to IoT projects such as GATT over BLE. But HTTP/S allows you to access the servers remotely over the Internet.
The REST interface is fairly simple. It uses the HTTP operations GET, POST, PUT and DELETE to access resources with a stateless protocol. This means that the client doesn’t have to maintain a connection with the server. The client just sends a command to the server and gets a status reply back. The interface is also idempotent; the client can make that same call repeatedly and it will producing the same result.
A good way to illustrate this it is to examine when my chicken coop app want to access the state of the coop door. This is what the transaction looks like over HTTP:
→ GET /devices/door
← HTTP/1.1 200 - OK
In this case server replied with a http status code of 200 indicating that the request succeeded. The http body contained a JSON encoded response. In this case the door is in state 1 which means happens to mean open.
When the client attempt to close the coop door, it sends the following command over HTTP using the PUT request method and a JSON encoded payload with the desired door state.
→ PUT /devices/door HTTP/1.1
Content-Type: application/json; charset=utf-8
← HTTP/1.1 200 - OK
Separation of Concerns
This use of a REST API allows me to separate the design and implementation of the user interface and the actual IoT code that flips the relays and senses voltages. It means that as long as the API stays the same, I can update one component without breaking the other.
I found this indispensable for both supporting multiple client platforms, as well as handing client platform updates. This happens often in the Apple iOS world. It seems that every time Apple put out new release or new hardware, I had to rework some of my code.
Software design choices
I chose to develop the bulk of my server code in the C++ language. It was a good compromise that exploited the features of object oriented design and at the same time allowed me to get low level enough access to the actual machine without depending on someone else to make a interface wrapper. Trust me when I say I based this decision on experience. I have written code in a plethora of platforms and languages over some 45+ years (OK Boomer) and I know what works for me. Your millage may vary and feel free to code your own designs on what every trendy language you want.
Since I am currently using an iPhone as my personal portable platform, I code to write my client code in Swift. A programming language that seems to change every time Apple releases a new OS update. Which makes the REST API that much more indispensable.
Note that I didn’t say SwiftUI. I personally don’t believe that it is quite ready for primetime. But again chose your own poison.
In the next episode I will discuss the home rolled framework I use for all my server code. And.. some clues on how to extend and secure it.