Arduino Yún + Twitter Streaming API blink example

This is a simple example on how to run some code on the Arduino side of the Arduino Yún on specific events fired through the Twitter Streaming API

i.e. when a tweet containing a specific #hashtag is twitted, Arduino blinks an LED

I love this experiment because it’s near real time and it gives a lot of possibilities, and it’s very easy to set up

Requirements

  • An Arduino Yún (obviously) with an external SD card (required for hosting the Python libraries you’ll need)
  • A twitter app you own
  • The Tweepy library for Python
  • And, finally… this code
  • 🙂

Instructions

“I love instructions, they give me confidence.”
me

  1. In case you haven’t done it yet, upgrade your Arduino Yún to the latest version and expand it’s disk space using the SD card
  2. Log to your Arduino using ssh
  3. Install a bunch of useful stuff
     $ opkg update
     $ opkg install git
     $ opkg install python-expat
     $ opkg install python-openssl
     $ opkg install python-bzip2
    

    easy_install

     $ opkg install distribute
    

    pip

     $ easy_install pip
    

    tweepy

     $ pip install tweepy
    

    or install it manually cloning it from github

      $ git clone https://github.com/tweepy/tweepy.git
      $ cd tweepy
      $ python setup.py install
    
  4. If you don’t have one, create your twitter app
    and get your consumer key and consumer secret. Then, generate an access token and get your access token and access token secret

  5. Create a working folder for all the scripts (i.e. /root/python)

     $ mkdir /root/python
     $ cd /root/python
    

    and, while in the python folder, clone the Twitter Blink example

      $ git clone git@github.com:amicojeko/TwitterBlink.git
    

    don’t forget to make the kill_processes.sh script executable!

      $ chmod +x kill_processes.sh
    
  6. Then use vi or nano (I personally installed vim) to put your twitter app configuration data into the streaming.py script, and to configure the string to be searched inside the Twitter Stream Maelstrom
     $ nano streaming.py
    

    now everything should be ready.

  7. Open the Arduino IDE and load the TwitterBlink.ino script that is in the Arduino folder (you can download it from GitHub )

  8. Configure the script folder (in case you created a folder different from root/python/ in the previuos steps)

    You can customize the script for your needings, in it’s initial configuration it will blink the LED attached to pin 13 (and the built in LED as well) so it’s perfect for testing

  9. Upload the script to Arduino, it should start working as soon as it’s uploaded

  10. Have fun!!

cheers!

Jeko

From arduino to rails through api

Some years ago I used pachube.com / cosm.com 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
    protect_from_forgery
    skip_before_action :verify_authenticity_token, if: :json_request?

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

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

    def create
      temperature = Temperature.new(temperature_params)
      if temperature.save
        render json: temperature, location: api_temperature_path(temperature.id), status: :created
      else
        render json: { errors: temperature.errors }, status: :unprocessable_entity
      end
    end

    ...
    ...

    protected

    def json_request?
      request.format.json?
    end


    private

    def temperature_params
      params.require(:temperature).permit(:value)
    end
  end
end

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[] = "tantiauguriatutti.herokuapp.com";   

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:
  Serial.begin(9600);

  analogReference(INTERNAL);
  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 = client.read();
    Serial.print(c);
  }

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

  // 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;
    sendData(temperature);
  }
  // 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)) {
    Serial.println("connecting...");
    // send the HTTP PUT request:
    client.println("POST /api/temperatures HTTP/1.1");
    client.println("Host: tantiauguriatutti.herokuapp.com");
    client.println("User-Agent: Arduino/1.0");
    client.println("Accept: application/json");
    client.print("Content-Length: ");
    client.println(JsonData.length());

    // last pieces of the HTTP PUT request:
    client.println("Content-Type: application/json");
    client.println("Connection: close");
    client.println();
    client.println(JsonData);
  } 
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
   // 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.

Facebook Graph API without user generated access token

[EDIT] This method is meant to be used only by server side applications, in general it’s not a good practice to include the app_id and app_secret in an API call!

Since I started using the Facebook Graph API, the Access Token generation has always been by biggest problem: they are not easy to generate, and they expire!

So you need to make calls to the Facebook Graph API from a Facebook APP and you don’t want to use a user generated token? There is an easy way!

There is an alternative method to call the Facebook Graph API that doesn’t require a user generated token:

https://graph.facebook.com/endpoint?key=value&access_token=app_id|app_secret

And… That’s it!! Just give to your app the right permissions, and you’ll never need to generate an Access Token again!!

Returning only an HTTP status code

If your making an API and some methods of your controller doesn’t need to render anything peculiar, you could rely on the head method.

head :ok

For an exhaustive list of the rails mapping you can use the handy cheat gem, created by Josh Susser.

$ gem install cheat
$ cheat status_codes
status_codes:
  Use these codes for the #head or #render methods.  ex:
    head :ok
    render :file => '404.html.erb', :status => :not_found
  
status_codes:
  Use these codes for the #head or #render methods.  ex:
    head :ok
    render :file => '404.html.erb', :status => :not_found
  
  1xx Informational
  
  100 => :continue
  101 => :switching_protocols
  102 => :processing
  
  2xx Success
  
  200 => :ok
...