This blog post was originally written by FarmBot contributor
Rick Carlino.
I was recently asked over email about our decision to use
Skynet for the
Farmbot Project. For those who don’t follow my usual antics, Farmbot is an opensource agricultural robot that aims to automate farming. I am a core contributor to the project and handle most of the web based stuff, occasionally taking a dive in to the hardware side of the project.
The question was a great opportunity for me to reflect on the decision to use skynet and think about the problems that we are attempting to solve. Here are my thoughts on the matter and why we ended up going using Skynet.
Skynet
Skynet is an internet-of-things platform that has been described as ‘device-to-device instant messaging’. It adds extra functionality to the
MQTT message protocol, such as support for REST and Websockets. The servers are publicly available and open to all. You can register a device ID on the network by doing a simple HTTP POST request and receive JSON messages in seconds. Various modules have been written to support the platform on different hardware, including
Skynet OS for arduino.
Our Old Setup
We were treating each Farmbot as a server that stored everything onboard and was manipulated via RESTful JSON interfaces. It was not the best way to tackle the problem. Trying to shoehorn a device to serve as a traditional REST API had a number of drawbacks including:
- Difficult to work around TCP port restrictions (firewalls, overly secure routers, port forwarding, etc)
- Initial client setup was cumbersome.
- Authentication / authorization needed to be setup from scratch.
- Device software required many external dependencies, which would often cause problems during setup.
- Running a full web server stack on a constrained device was resource intensive.
- It was difficult to handle lost messages if the device went offline
- Message delivery was not always guaranteed (see above).
- The typical request-response cycle of HTTP was not always a good fit for our use case, especially for outbound messages or telemetry broadcasting.
Our Current Setup
Our new setup treats all devices involved as API consumers of
Skynet. Almost all services plug in to Skynet as a client rather than a server. There is a soon-to-be-released web based component that allows the user to interact with the device in the browser directly (think
Farmville for the real world). Background processes such as measuring weather data and watering plants are handled by a background job workers and a decision support system.
We made the change for a number of reasons:
- There is no need for us to proxy connections through our domain or handle cross domain security issues. All browsers connect to Skynet directly, alleviating strain on our web server. This means I don’t need to spend time dealing with CORS, JSONP or API proxying.
- Guaranteed message delivery made intermittent connectivity less of a design concern.
- Authentication responsibilities have been offloaded to Skynet, which lets us work on other features.
- Using Websockets instead of REST means we never need to do polling for realtime events. HTTP polling is almost always a bad idea, so I was glad to have an alternative.
- There is a REST API available if we need it (but we haven’t yet, aside from minor debugging).
Although it’s been a good move for us and a step in the right
direction, there still have been some hurdles:
- The websocket API is heavily dependent on Socket.io. It’s easy to find adapters for webscoket clients in almost any language, but finding one that supports the Socket.io protocol has not been easy. Most Socket.io libraries in Ruby make the assumption that we are trying to act as a server, which is not the case for Farmbot. This has been our biggest pain point with the Skynet platform thusfar, as our socket client has been a bit fragile.
- It’s a very ‘edge’ technology, and occasional quirks are found in the API, such as slight differences between the REST API and the Socket API.
- We are still trying to find ways for non-technical users to deal with device discovery and ‘ownership’ when a new device enters Farmbot device enters Skynet. An LCD screen displaying the Skynet UUID seems to be the most prominent idea at the moment, but the decision has not been finalized.