Arduino Twitter

From ProjectPages
Jump to: navigation, search

Aims

For this project I wanted to be able to post to a twitter account for my Arduino. Amongst other ideas, I thought I might use this so that my plants can tell me when they need watering.

Overview

I had to learn about a few different technologies to complete this project. The first one was the Twitter API. I found this link REST API v1.1 Resources to be extremely useful in understanding what could be achieved through the API.

I planned to implement a PHP proxy on my hosted web account and to have the Arduino call the proxy to post the Tweets.

It seems, from my reading, that the authentication overhead imposed in v1.1 of the Twitter API puts this out of reach of a simple Arduino.

So, the first thing to do was the implement the PHP and get some Tweets into my account.

The Twitter API

The first step is to set up a new Twitter App. This will give you the various authentication data that you will need for the PHP proxy.

The PHP Proxy

After a couple of false starts I found this PHP library, which made life really simple - TwitterOAuth by @Ricard0Per — a simple PHP library for API v1.1

I copied all the files into a folder on my hosted web site and then added my authentication information into Example.php. This allowed me to quickly test that all was working.

I then edited Example.php to perform the tasks I wanted. My final code is shown below. I have highlighted the areas that you will need to change. Some of the changes I implemented were to take values using HTTP POST and, from those values, determine which feature of the Twitter API to use. This could easily be expanded to expose other functions from the API.

If you change $_POST to $_GET, you can drive the proxy from a browser with a simple GET string. <syntaxhighlight line lang="PHP"> // makes it easy to switch between GET and POST $URLparams = $_POST; </syntaxhighlight>

I used this method to test all the functions and then changed over to the POST method.

In order to test the POST method, I wrote a simple html file <syntaxhighlight line lang="html5">

type:
query:
count:
</syntaxhighlight> This will return the twenty most recent Tweets containing the word arduino

The full code for twitterProxy.php: <syntaxhighlight line highlight="12-23" lang="PHP"> <?php

require_once __DIR__ . '/twitteroauth/twitteroauth.php'; require_once __DIR__ . '/twitteroauth/Exception/TwitterException.php';


use twitteroauth\twitteroauth;

date_default_timezone_set('UTC');


/**

* Array with the OAuth tokens provided by Twitter when you create application
*
* output_format - Optional - Values: text|json|array|object - Default: object
*/

$config = array(

   'consumer_key' => 'abc123xyz',
   'consumer_secret' => 'abc123xyz',
   'oauth_token' => 'abc123xyz',
   'oauth_token_secret' => 'abc123xyz',
   'output_format' => 'array'

);

/**

* Instantiate twitteroauth class with set tokens
*/

$tw = new twitteroauth($config);

// makes it easy to switch between GET and POST $URLparams = $_POST;


switch ($URLparams['type']) {

   case "search":

// * Returns a collection of the most recent Tweets with matching search string // * https://api.twitter.com/1.1/search/tweets.json

if (isset($URLparams['query'])){

$query = urlencode($URLparams['query']); $count = 5; if(isset($URLparams['count'])){ $count = $URLparams['count']; }

$params = array( 'q' => $query, 'count' => $count, );

// * Send a GET call with set parameters

$response = $tw->get('search/tweets', $params);

//var_dump($response); foreach ($response['statuses'] as $myResponse){

echo "
"; echo "

" . urldecode($myResponse['text']) . "

"; echo "

Source: " . $myResponse['source'] . "

"; echo "

Name: " . $myResponse['user']['name'] . " Screen Name: " . $myResponse['user']['name'] ."

";

} }

       break;
   case "timeline":

// * Returns a collection of the most recent Tweets posted by the user // * https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline

$params = array( 'screen_name' => $URLparams['screenname'], 'count' => 5, 'exclude_replies' => true );

// // * Send a GET call with set parameters

$response = $tw->get('statuses/user_timeline', $params);

// var_dump($response); foreach ($response as $myResponse){

echo "

" . urldecode($myResponse['text']) . "

";

}

break;

   case "list":

// * Creates a new list for the authenticated user // * https://dev.twitter.com/docs/api/1.1/post/lists/create // *

$params = array( 'name' => 'TwOAuth', 'mode' => 'private', 'description' => 'Test List', );

// * Send a POST call with set parameters

$response = $tw->post('lists/create', $params);

var_dump($response);

       break;

case "status": // * Creates a new tweet for the authenticated user // * https://dev.twitter.com/docs/api/1.1/post/statuses/update

$status = stripslashes($URLparams['status'] . " " . date('D, d M Y H:i:s'));

$params = array( 'status' => $status );

// // * Send a POST call with set parameters

$response = $tw->post('statuses/update', $params);

var_dump($response);

break;

}

?> </syntaxhighlight>

The Arduino

Once again I had to scour the internet to find examples where others had done similar things. In this process I have learned about the anatomy of a POST header. One of the ways I did this was by using the Google Chrome developer tools. I ran the html file above to test the POST process and then Chrome can show you exactly what is being sent.

My saviour was * UIPEthernet: A plugin-replacement of the stock Arduino Ethernet library for ENC28J60 shields and breakout boards. Please have a look at my Arduino Ethernet page to see how I started out with this library. The attraction is that it will run all of the Arduino Ethernet examples out there on the internet simply by changing the name of the include file.

I started out from the WebClient example from the Arduino Ethernet Library page. Then I had a look at Arduino – HTTP Post Requests and that gave me a good steer. I wrote the code below, remembering to change #include <Ethernet.h> to #include <UIPEthernet.h>, and it worked straight away.

Tweet generated by Arduino

<syntaxhighlight line> /*

 HTTP POST client


This sketch sends a POST to a website in order to pass data.
This example was used to send a Tweet to a PHP program that provides a proxy to the Twitter API 

Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13

created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe, based on work by Adrian McEwen
modified 04 Jan 2013
by Tony Norman 

*/
  1. include <SPI.h>
  2. include <UIPEthernet.h>

// Enter a MAC address for your controller below. // Newer Ethernet shields have a MAC address printed on a sticker on the shield byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // if you don't want to use DNS (and reduce your sketch size) // use the numeric IP instead of the name for the server: //IPAddress server(74,125,232,128); // numeric IP for Google (no DNS) char server[] = "www.indianbeantree.co.uk"; // name address for Google (using DNS)

// Set the static IP address to use if the DHCP fails to assign IPAddress ip(192,168,22,177);

// Initialize the Ethernet client library // with the IP address and port of the server // that you want to connect to (port 80 is default for HTTP): EthernetClient client;

void setup() {

// Open serial communications and wait for port to open:
 Serial.begin(9600);
  while (!Serial) {
   ; // wait for serial port to connect. Needed for Leonardo only
 }
 // start the Ethernet connection:
 if (Ethernet.begin(mac) == 0) {
   Serial.println("Failed to configure Ethernet using DHCP");
   // no point in carrying on, so do nothing forevermore:
   // try to congifure using IP address instead of DHCP:
   Ethernet.begin(mac, ip);
 }
 // give the Ethernet shield a second to initialize:
 delay(1000);
 Serial.println("connecting...");
 
 String host, data;
 //this is the string of data to be sent by the POST
 data="type=status&status=Sent%20by%20%23arduino&action=Submit";
 
 //this is the website that is hosting the PHP proxy
 host="www.yourdomain.co.uk";
 // if you get a connection, report back via serial:
 if (client.connect(server, 80)) {
   Serial.println("connected");
   // Make a HTTP POST request the  host plus the '/yourphpfolder/twitterProxy.php'

// should be the full URL path to your PHP host

   client.println("POST /yourphpfolder/twitterProxy.php HTTP/1.1");

// set the Host

   client.print("Host: ");
   client.println(host);
   client.println("Connection: close");

// calculates and passes the length of the data

   client.print("Content-Length: ");
   client.println(data.length());
   client.println("Content-Type: application/x-www-form-urlencoded");

// need a blank line so that the server knows that the data comes next

   client.println();

// now we send the data string

   client.println(data);
 } 
 else {
   // kf you didn't get a connection to the server:
   Serial.println("connection failed");
 }

}

void loop() {

 // if there are incoming bytes available 
 // from the server, read them and print them:
 if (client.available()) {
   char c = client.read();
   Serial.print(c);
 }
 // if the server's disconnected, stop the client:
 if (!client.connected()) {
   Serial.println();
   Serial.println("disconnecting.");
   client.stop();
   // do nothing forevermore:
   while(true);
 }

} </syntaxhighlight>

Links

Example Arduino HTTP POST