Apiotics Gem

Apiotics Gem

The easy way to make your Rails application interact with IoT devices.


Add this line to your application's Gemfile:

gem "apiotics"

Or install it yourself as:

$ gem install apiotics

And then execute:

$ bundle
$ rails generate apiotics:install

On the Apiotics portal located at portal.apiotics.com, you can create a Hive for your project. Hives have Workers (each type of IoT device in your project will have a corresponding worker in the Hive). Workers have Drivers and, optionally, Scripts. Drivers and Scripts have interfaces. An example worker might be a Thermostat. The Thermostat has a Control Script with two interfaces: temperature and target temperature. If you set the target temperature to 72 and the temperature is 65, the Thermostat will turn the heat on. We'll use this example again and flesh it out below.

Once you have created a Hive, it will give you a public and a private API key. Best practice is to set environment variables in your development, test and production environments to equal these API keys. Then, set config.public_key and config.private_key in config/initializers/apiotics.rb to those environment variables. You can enter the API keys directly into the configuration file, but you should only do this if you never plan to put your Rails application and Hive into production, as it is a significant security risk.

Apiotics.configure do |config|
    config.public_key = ENV['APIOTICS_PUBLIC_API_KEY']
    config.private_key = ENV['APIOTICS_PRIVATE_API_KEY']
    config.local_port = 8001
    config.server_port = 8000
    config.tls = true
    config.local_logging = true


After you have installed the API keys, log in to the Apiotics portal (portal.apiotics.com) to see that your Hive has Workers and that those Workers have Drivers and, if applicable, Scripts defined. Each Worker, Driver or Script will have one or more Interfaces. For example, if you are making a connected Thermostat, your Hive might have a Worker named 'Thermostat' and it might have the following Drivers/Scripts: Thermometer, Furnace and Control.

Each of the Drivers/Scripts has Interfaces (all of this would be viewable on the portal.apiotics.com portal). The Control script might have two interfaces: Temperature and Target Temperature.

We want to be able to interact with these interfaces easily through our Rails application for all of the Thermostats that we have out there in the field.

Models and Tables

To do this, we will create a model in our Rails application with attributes that correspond to the interfaces we want to interact with. We will then create records in our Rails database that correspond to our devices. Once we've done that, we can interact with a database record using ActiveRecord as usual, but the attribute values from our database records will be automatically synced to the corresponding device.

Because our model is going to sync with our IoT devices, we need to use the Apiotics model generator that comes with the gem to create the model rather than the model generator that comes by default with Rails. To use it, we pass two arguments, the name of the Worker and the name of the Driver or Script that we want to interact with. In this case, our worker is Thermostat and we want to interact with Control, so we create the models as follows:

$ rails generate apiotics:model Thermostat Furnace
$ rails generate apiotics:model Thermostat Thermometer

This generator actually creates models inside a module. The module is in app/models/thermostat.rb and the models in app/models/thermostat/thermostat.rb, app/models/thermostat/furnace.rb and app/models/thermostat/thermometer.rb. Each model that you generate for one of your Thermostat Worker's Drivers/Scripts is placed in the app/models/thermostat directory.

Now you should migrate your database in order to create the database tables that correspond to your model.

$ rake db:migrate

Instances and Devices

Now that you have your models and database tables created, you can use them to communicate with the devices that are out in the field.

The first thing we need to do is establish a communications channel we can use to communicate between our Rails application and the devices in the field. To do this, we use a local server that handles sending communications to the remote devices and handles communications that we will receive from them.

To start it up in production:

$ rake comms:start

In development:

$ rake dev_comms:start

In test:

$ rake test_comms:start

This starts our communications server. If you want to stop the communications server for any reason simply:

In production:

$ rake comms:stop

In development:

$ rake dev_comms:stop

In test:

$ rake test_comms:stop

Note that you can only communicate with devices if the local communications server is running.

Communicating with Devices

Now that the preliminaries are out of the way, let's communicate with devices.

Open up your rails console again by typing:

$ rails c

In your console, type the following to get a device instance and assign it to the variable d:

> d = Thermostat::Thermostat.first

The first thing to do is to synchronize the database's data with the data from the device. (This sends a get request for each Interface in the current Driver/Script) To do this type in your console:

> d.thermometer.sync
> d.furnace.sync

Now that you are synced with the device, you can read and set the device's Interfaces easily right from Rails.

First, let's read the temperature.

> d.thermometer.temperature
=> "65" 

Let's say you want to turn the heat on. Here's how you do it:

> d.heat = "on"
=> "on"
> d.save

All of the communications to the device are taken care of for you. If the value of these Interfaces changes (if the ambient temperature rises or falls for example) then your database will be kept up to date via the communications server without needing to sync the device instance going forward so long as your comms server remains up and connected.

Building a Web Scaffold

Now that you can communicate with your devices from the rails console, let's create a web scaffold so that you can communicate with them via your web browser.

Run the Apiotics scaffold controller generator to generate a scaffold and views for your device.

> rails generate apiotics:controller Thermostat

This command installs a default controller and views for your Thermostat. Once they are installed, you can see them in your browser by starting up your development web server.

> rails server

Then in your web browser of choice, navigate to http://localhost:3000/thermostats. This page will show you a list of your Thermostat instances, as well as the current values of the different interfaces for your device. You can use the edit links for each device instance to change these values.

Adding Push Web Updates

Since we want to be able to see changes to our devices without refreshing our webpage manually, we can leverage Rails 5's ActionCable to push device updates to our page.

To do this, run:

> rails generate apiotics:channel Thermostat

This command installs a configuration file, in this case app/channels/thermostat_channel.rb, to define an ActionCable channel for your Worker, in this case thermostat_channel, as well as a coffeescript file, in this case app/assets/javascripts/channels/thermostat.coffee, that defines how the browser will update information from the server on the page.

In order for the ActionCable messages to actually transmit to the browser, we need to install Redis. Redis is an open source in-memory data store that ActionCable uses to implement its PubSub messaging.

The easiest way to install Redis (if you are on a Mac) is:

> brew install redis

Then, once it is installed, run:

> redis-server

In your Rails application, edit your config/cable.yml file to look as follows:

  adapter: redis

  adapter: redis

  adapter: redis

Add the following to your Gemfile:

gem 'jquery-rails'

And run

> bundle install

Next, open up your app/assets/javascripts/application.js file. Make sure you add the following lines to it above the require_tree . line, if you have it.

//= require jquery
//= require jquery_ujs

Then, restart your Rails server and your comms server. Once you have done that, the values on the Thermostats page will update via push notifications.


The gem is available as open source under the terms of the MIT License.

Mac Dougherty