From arduino to rails through api

Some years ago I used / to save a stream of data generated from a sensor attached to an Arduino board. Unfortunately  this service is no more available, but you can build your own data stream repository with rails and heroku.

In this example we read temperatures from an Arduino sensor and then we save data via API using a rails app.

There are several guides to build REST APIs using rails. This tutorial integrates some best practices but you need to focus your work on a smaller subset, depending on your need. Rails and JSON give you the perfect combination for a fast and comprehensive developement.

Rails api controllers

# /app/api/temperatures_controller.rb

module Api
  class TemperaturesController < ActionController::Base
    skip_before_action :verify_authenticity_token, if: :json_request?

    def index
      temperatures = Temperature.all
      if temperatures.any?
        render json: temperatures
        render json: {}, status: :not_found

    def show
      temperature = Temperature.find(params[:id]) rescue nil
      if temperature
        render json: temperature
        render json: {}, status: :not_found

    def create
      temperature =
        render json: temperature, location: api_temperature_path(, status: :created
        render json: { errors: temperature.errors }, status: :unprocessable_entity



    def json_request?


    def temperature_params

Test locally

During your development you can test your API with curl, here are some examples for saving and retrieving JSON data feeds:

# create
curl -v loalhost:3000/api/temperatures -X POST 
     -H "Accept: application/json" 
     -H "Content-Type: application/json" 
     -d '{"temperature": {"value": 20}}'

# index
curl -v loalhost:3000/api/temperatures

# show
curl -v loalhost:3000/api/temperatures/1

Your goal now is to create a POST request from Arduino just like the one generated with curl.

Arduino post request

To send data to a rails app you need an Anduino Ethernet Shield + Arduino or an Arduino Yun. In this example we are using an Anduino Ethernet Shield and we run on it this code:

#include <SPI.h>
#include <Ethernet.h>

// assign a MAC address for the ethernet controller.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
// fill in your address here:
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

// fill in an available IP address on your network here,
// for manual configuration:
IPAddress ip(192,168,1,10);
// initialize the library instance:
EthernetClient client;

char server[] = "";   

unsigned long lastConnectionTime = 0;       
boolean lastConnected = false;              
const unsigned long postingInterval = 60000;

float temperature;  
int reading;  
int lm35Pin = 5;
float referenceVoltage;

void setup() {
  // Open serial communications and wait for port to open:

  referenceVoltage = 1.1;

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // DHCP failed, so use a fixed IP address:
    Ethernet.begin(mac, ip);

void loop() {
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  if (client.available()) {
    char c =;

  // if there's no net connection, but there was one last time
  // through the loop, then stop the client:
  if (!client.connected() && lastConnected) {

  // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
    reading = analogRead(lm35Pin);
    temperature = (referenceVoltage * reading) / 1023;
  // store the state of the connection for next time through
  // the loop:
  lastConnected = client.connected();

// this method makes a HTTP connection to the server:
void sendData(int thisData) {
  // if there's a successful connection:
  String JsonData = "{"temperature": {"value": ";
  JsonData = JsonData + thisData;
  JsonData = JsonData + "}}";
  if (client.connect(server, 80)) {
    // send the HTTP PUT request:
    client.println("POST /api/temperatures HTTP/1.1");
    client.println("User-Agent: Arduino/1.0");
    client.println("Accept: application/json");
    client.print("Content-Length: ");

    // last pieces of the HTTP PUT request:
    client.println("Content-Type: application/json");
    client.println("Connection: close");
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
   // note the time that the connection was made or attempted:
  lastConnectionTime = millis();

The example above shows how to manage ethernet configuration, transform reading from analog input sensor and how to send JSON data to our Rails app.

Keep in mind it is possible to use another board to collect and send data, for example Spark Core and Electric Imp are perfect beacause already integrated with WiFi module.

The social media hamster

(la muerte peluda is back)

Every hackathon we host at Mikamai usually means a lot of leftovers. From pizza crusts to burned LEDs, you can find a lot of useful and useless stuff even in the deepest and darkest corners of our huge open space.

And in one of these dark corners I found a scared little friend, which I suddenly decided to adopt.


We became BFFs, and we do everything together, coding, drinking, pranking the teammates and cycling, but he wanted to be useful to me, so I went into my cove and start thinking… what an ex cartoon eating plush hamster can do for me?

The answer was quite obvious! He can warn me whenever someone tweets me or cites me in a tweet! Genius!

So, here are the ingredients

  • Twitter streaming APIs
  • Electric IMP (I decided to use an Electric Imp just because I had a spare one, you can even use a spark core or an Arduino Yún)
  • A servo
  • Chopsticks
  • Some screws
  • Cable ties
  • Something heavy
  • Obviously, absulutely essential, a plush hamster
  • An USB power adapter or a USB battery pack if you want your project to be portable


I also used an LED for visual debugging, I tried to put a pair of LEDs instead of my hamster’s eyes, but it was too scary, and it remembered a lot my creepy doll, so I decided not to use them

Then I had to make the hamster move with the servo. It’s just a prototype, so I decided to keep it very very simple, and I secured the hamster to the servo with a chopstick, some copper wire and some screws to keep the hamster from doing a barrel roll. The surgery was not so traumatic, so my hamster is still happy. Then I fixed the servo to an heavy metal plate with a cable tie, just to provide a solid base.

I drilled some holes to the chopstick


Then put some screws in it and i secured the chopstick to the servo


And I used a bit of copper wire to secure the hamster to the screws



And a cable tie to fix the servo to the metal plate


Now everything’s in place!


The circuit is dead simple. Just connect the power pins of the servo to the GND-VIN pins of the Electric Imp, and the third pin to the Imp’s pin number 7


The Electric Imp is one of the easiest platforms to configure, thanks to the Blink app, so you can have it online in a couple of minutes. You can even use your phone as hotspot, it works perfectly and it makes your social hamster fully portable.


Now, the code. The Electric imp platform gives you all the instruments to interact with the whole world of APIs and webservices. Basically, the code is splitted in two: An agent, that runs on the Electric Imp Cloud servers, and a device, which is your electric Imp

[Copy & Paste from the official Electric Imp documentation]

The agent object represents the imp’s agent: the server-side Squirrel, running in the Electric Imp’s cloud servers, that deals with Internet requests and responses on behalf of the imp. The agent object is used to mediate communication between the imp and its agent.

The device object represents the server-based agent’s view of the imp and is used to mediate communication between the agent and the imp.

[End of copy&paste]

So here we go with our agent code. It’s based on the useful twitter library included in the Electric Imp webservices reference. I also added this piece of code to generate the tweet event manually

// test function for manual hamster shaking
function requestHandler(request, response) {
  try {
    // check if the user sent led as a query parameter
    if ("tweet" in request.query) {
        device.send("tweet", null); 
    // send a response back saying everything was OK.
    response.send(200, "tweet test ok");
  } catch (ex) {
    response.send(500, "Internal Server Error: " + ex);

// register the HTTP handler

To enable the twitter stream real time parsing, I just needed to configure these twitter constants

// Twitter Keys
const API_KEY = "";
const API_SECRET = "";
const AUTH_TOKEN = "";
const TOKEN_SECRET = "";

and this line"@jeko", onTweet);

which basically tells to the stream object to catch all the tweets containing the string “@jeko”

So, here’s the complete agent code

// Copyright (c) 2013 Electric Imp
// This file is licensed under the MIT License

// Twitter Keys
const API_KEY = "";
const API_SECRET = "";
const AUTH_TOKEN = "";
const TOKEN_SECRET = "";

class Twitter {
    // OAuth
    _consumerKey = null;
    _consumerSecret = null;
    _accessToken = null;
    _accessSecret = null;

    // URLs
    streamUrl = "";
    tweetUrl = "";

    // Streaming
    streamingRequest = null;
    _reconnectTimeout = null;
    _buffer = null;

    constructor (consumerKey, consumerSecret, accessToken, accessSecret) {
        this._consumerKey = consumerKey;
        this._consumerSecret = consumerSecret;
        this._accessToken = accessToken;
        this._accessSecret = accessSecret;

        this._reconnectTimeout = 60;
        this._buffer = "";

     * function: Tweet
     *   Posts a tweet to the user's timeline
     * Params:
     *   status - the tweet
     *   cb - an optional callback
     * Return:
     *   bool indicating whether the tweet was successful(if no cb was supplied)
     *   nothing(if a callback was supplied)
    function tweet(status, cb = null) {
        local headers = { };

        local request = _oAuth1Request(tweetUrl, headers, { "status": status} );
        if (cb == null) {
            local response = request.sendsync();
            if (response && response.statuscode != 200) {
                server.log(format("Error updating_status tweet. HTTP Status Code %i:rn%s", response.statuscode, response.body));
                return false;
            } else {
                return true;
        } else {

     * function: Stream
     *   Opens a connection to twitter's streaming API
     * Params:
     *   searchTerms - what we're searching for
     *   onTweet - callback function that executes whenever there is data
     *   onError - callback function that executes whenever there is an error
    function stream(searchTerms, onTweet, onError = null) {
        server.log("Opening stream for: " + searchTerms);
        // Set default error handler
        if (onError == null) onError = _defaultErrorHandler.bindenv(this);

        local method = "statuses/filter.json"
        local headers = { };
        local post = { track = searchTerms };
        local request = _oAuth1Request(streamUrl + method, headers, post);

        this.streamingRequest = request.sendasync(

            function(resp) {
                // connection timeout
                server.log("Stream Closed (" + resp.statuscode + ": " + resp.body +")");
                // if we have autoreconnect set
                if (resp.statuscode == 28) {
                    stream(searchTerms, onTweet, onError);
                } else if (resp.statuscode == 420) {
                    imp.wakeup(_reconnectTimeout, function() { stream(searchTerms, onTweet, onError); }.bindenv(this));
                    _reconnectTimeout *= 2;

            function(body) {
                 try {
                    if (body.len() == 2) {
                        _reconnectTimeout = 60;
                        _buffer = "";

                    local data = null;
                    try {
                        data = http.jsondecode(body);
                    } catch(ex) {
                        _buffer += body;
                        try {
                            data = http.jsondecode(_buffer);
                        } catch (ex) {
                    if (data == null) return;

                    // if it's an error
                    if ("errors" in data) {
                        server.log("Got an error");
                    else {
                        if (_looksLikeATweet(data)) {
                } catch(ex) {
                    // if an error occured, invoke error handler
                    onError([{ message = "Squirrel Error - " + ex, code = -1 }]);


    /***** Private Function - Do Not Call *****/
    function _encode(str) {
        return http.urlencode({ s = str }).slice(2);

    function _oAuth1Request(postUrl, headers, data) {
        local time = time();
        local nonce = time;

        local parm_string = http.urlencode({ oauth_consumer_key = _consumerKey });
        parm_string += "&" + http.urlencode({ oauth_nonce = nonce });
        parm_string += "&" + http.urlencode({ oauth_signature_method = "HMAC-SHA1" });
        parm_string += "&" + http.urlencode({ oauth_timestamp = time });
        parm_string += "&" + http.urlencode({ oauth_token = _accessToken });
        parm_string += "&" + http.urlencode({ oauth_version = "1.0" });
        parm_string += "&" + http.urlencode(data);

        local signature_string = "POST&" + _encode(postUrl) + "&" + _encode(parm_string);

        local key = format("%s&%s", _encode(_consumerSecret), _encode(_accessSecret));
        local sha1 = _encode(http.base64encode(http.hash.hmacsha1(signature_string, key)));

        local auth_header = "oauth_consumer_key=""+_consumerKey+"", ";
        auth_header += "oauth_nonce=""+nonce+"", ";
        auth_header += "oauth_signature=""+sha1+"", ";
        auth_header += "oauth_signature_method=""+"HMAC-SHA1"+"", ";
        auth_header += "oauth_timestamp=""+time+"", ";
        auth_header += "oauth_token=""+_accessToken+"", ";
        auth_header += "oauth_version="1.0"";

        local headers = { 
            "Authorization": "OAuth " + auth_header

        local url = postUrl + "?" + http.urlencode(data);
        local request =, headers, "");
        return request;

    function _looksLikeATweet(data) {
        return (
            "created_at" in data &&
            "id" in data &&
            "text" in data &&
            "user" in data

    function _defaultErrorHandler(errors) {
        foreach(error in errors) {
            server.log("ERROR " + error.code + ": " + error.message);



function onTweet(tweetData) {
    // log the tweet, and who tweeted it (there is a LOT more info in tweetData)
    server.log(format("%s - %s", tweetData.text, tweetData.user.screen_name));
    device.send("tweet", null); 

// test function for manual hamster shaking
function requestHandler(request, response) {
  try {
    // check if the user sent led as a query parameter
    if ("tweet" in request.query) {
        device.send("tweet", null); 
    // send a response back saying everything was OK.
    response.send(200, "tweet test ok");
  } catch (ex) {
    response.send(500, "Internal Server Error: " + ex);
}"yoursearchstring", onTweet);

// register the HTTP handler

Then, here’s the device code, based on the electric Imp PWM Servo example

// These values may be different for your servo
const SERVO_MIN = 0.03;
const SERVO_MAX = 0.1;

// create global variable for servo and configure
servo <- hardware.pin7;
servo.configure(PWM_OUT, 0.02, SERVO_MIN);

// assign pin9 to a global variable
led <- hardware.pin9;
// configure LED pin for DIGITAL_OUTPUT

// global variable to track current state of LED pin
state <- 0;
// set LED pin to initial value (0 = off, 1 = on)

// expects a value between 0.0 and 1.0
function SetServo(value) {
  local scaledValue = value * (SERVO_MAX-SERVO_MIN) + SERVO_MIN;

// expects a value between -80.0 and 80.0
function SetServoDegrees(value) {
  local scaledValue = (value + 81) / 161.0 * (SERVO_MAX-SERVO_MIN) + SERVO_MIN;

// current position (we'll flip between 0 and 1)
position <- 0;

function HamsterDance() {

function ShakeRattleAndRoll(ledState){
    server.log("Let's shake the hamster!");  
    // turn on the led for visual debugging
    // turn off the led


// initialize the servo to the start position

//shake the hamster when got a tweet message from the Agent
agent.on("tweet", ShakeRattleAndRoll);

And… that’s it! Just connect the Electric Imp to a power source, configure the wifi via the Electric Imp mobile App, and start tweeting! Your hamster will be soo happy to warn you whenever a tweet is coming!!

Ciao and happy hacking!


Intel Galileo: Getting Started with Mac OS X

A step-by-step tutorial by jeko

IMPORTANT: Connect your intel Galileo to the 5V power supply before any other connection or you will damage the board.

During the Rome Maker Faire, I was lucky to get an Intel Galileo. But when I had to use it, it was suddenly clear that it’s not as straightforward as Arduino. I had to resort to desperate measures and do something that really only a very restricted class of noble people do, I had to read the manual.


The getting started guide by Intel really helped, but the problem is that it’s clearly written by engineers, while the Galileo board wants to attract makers, designers, artists and many people that are used to the “tutorial” or “step by step” approach and are not really into manual reading.

I used to be an RTFM fanatic, but I’m getting old, and I have learned to appreciate when people help me, so I’m very happy to contribute and give some help to those in need.

So. You have an Intel Galileo board, a Mac (I assume you have Mac OS X Mavericks installed), and you want to run the very first basic example: the “Blink” sketch from the Arduino examples. Right?


This is what you have to do, straight and easy.

So, let’s start:

  1. Download the Galileo software from the Intel website. If you already have the Arduino IDE, don’t overwrite it. Even if the Intel software is based on the Arduino IDE, it is not 100% identical, and it will only manage the Galileo board, so if you want to use them both, simply unzip the Intel software, rename it into “Galileo”, and move it into your Application folder. Don’t rename it into something with spaces, and do not put it into folders with a space in their name, because it won’t work.
  2. Plug the 5V adapter, wait 10 seconds and then connect the USB client (the little usb port next to the ethernet plug) to your Mac’s USB port
  3. You have to wait a minute: it takes a little while for the USB stack to start on the Galileo board, then you can start the Galileo IDE
  4. Go to Tools > Port menu and select the /dev/cuXXX serial port. If you don’t see the port, close the IDE, wait a minute, and open it again.
  5. Now, you have to update the Galileo’s firmware, so, go on Help > Firmware Upgrade. If everything is ok, you should see a message asking for confirmation if the 5V power cable is plugged in. Since you have followed these instructions, it should be, so click yes, do the same on the next dialog and the process should begin. It will take 5-6 minutes. During the process, avoid touching the cables or the board or the IDE. Just sit down and relax.
  6. When the process is complete, the “Target Firmware upgraded successfully.” message is displayed. Click OK to close the message.
  7. Now choose the blink example from File > Examples > 01.Basics > Blink

Upload the blink sketch and you’re done! It’s time to celebrate! 🙂


P.S. The Quark processor can become very hot, don’t worry it’s normal.

The “Facebook’s Like” Alarm

Hi there! Ever wanted to know in real time if someone likes your facebook page?

We’ve got the solution for you! Here, in Mikamai, as most companies do, we have a Facebook page, and we are very proud of it. We wanted to have some kind of physical feedback in our office, to let us know in real time when we get a new fan.

So, that’s how we did it.

First of all, the device. We needed to have it on 24/7, it should be very cheap, low powered, and we wanted to have the possibility to add new features (audio, video, lights, physical devices ecc…) so the perfect choice was the RaspberryPI

Second, the programming language. The obvious choice for us is Ruby 🙂

Third… what will happen? We wanted something simple, effective and not too annoying, so we choose a simple sound, the Super Mario coin sample was perfect for us.

The set up is very very simple.

We started froma a brand new RaspberryPI, and we installed Ruby with RVM, following these easy steps

everything worked like a charm.

Then, we put this simple script in /home/pi/like_it/

require 'rubygems'
require 'net/http'
require 'json'

LIKES_FILE = "likes"
PLAYER = (RUBY_PLATFORM == "armv6l-linux-eabihf") ? "omxplayer" : "mpg123"

while true do
    response = Net::HTTP.get_response("","/mikamai")
    json = JSON.parse(response.body)

    old_likes =, 'r').gets.to_i
    likes = json["likes"].to_i

    if (likes > old_likes)
      #fixme: with mpg123 the -o local option (obviously) returns an error, it's non blocking but could be fixed
      system(PLAYER + " coin.mp3 -o local")
      p "like"
    end, 'w') { |file| file.write(likes) }

    sleep (10)

If you are using GIT (You have to install GIT on your RaspberryPI as well) simply go in the home directory via ssh and checkout the project from

In the Github project we also added a simple start script

#! /bin/sh

cd $DIR

# stdout goes in trash, stderr gets logged 
rvm-auto-ruby like_it.rb 1> /dev/null 2> $DIR/logs/like_it_error &

the coin sample file, the (empty) log files for errors and stdout, and the counter file (using a database for this project is a bit overkill)

and… that’s it!

The script is supersimple, it runs an infinite loop and checks for new likes every 10 seconds (since the real time API for likes is not available yet). It just calls the Facebook Open Graph Public API, it searches for the “likes” counter in the JSON file, and confronts it with the likes previously stored in the “likes” file. If the likes are increasing, it plays the audio file.

Simple, stupid and sooo effective 🙂

To make it start automatically everytime the RaspberryPI reboots, jus add this in the /etc/rc.local file

# starts like-it daemon as pi user
su pi -c '/home/pi/like_it/start'