• No results found

In previous projects, you have used the HTTP method GET to request information from a web server. This project uses the POST method. Making a POST is still a request from a client that the server is expected to respond to. However, the

POST method tells the server that the client is sending additional information after the usual HTTP request header.

This is the way information is sent to a web server when you submit forms on webpages, and it is also the way that you need to send tweets to ThingTweet.

A valid POST request to ThingTweet looks like this:

POST /apps/thingtweet/1/statuses/update HTTP/1.0[crlf]

Host: api.thingspeak.com[crlf]

Connection: close[crlf]

Content-Type: application/x-www-form-urlencoded[crlf]

Content-Length: 72[crlf]

[crlf]

api_key=THE16DIGITAPIKEY&status=This is your message to post on Twitter.

Content-Length specifies the number of bytes in the data.

The Content-Type field specifies how the data (the string starting with “api_key=”) is encoded.

When using the URL encoding scheme, you send key/value pairs as character strings separated by an ampersand. Keys are like variable names, and to work with another system you will have to use the keys that it tells you to. The value of a key/value pair can be any kind of data provided that it is encoded in the correct way. To avoid interfering with the HTTP request, spaces in values should be replaced with a ‘+’, and other non-alphanumeric characters in the data should be replaced by a percent sign followed by the hexadecimal number of the character.

Sending spaces, exclamation marks, and periods as un-encoded characters is usually fine, but they are often encoded anyway. The string “This is your message to post on Twitter!” can be encoded as

This+is+your+message+to+post+on+Twitter%21.

If you plan to send a wide variety of non-alphanumeric characters, or do not know what type of characters you will be sending, then you should implement a function to replace non-alphanumeric characters using URL encoding. This project does not do that because the messages are hard-coded into the sketch and contain only basic characters.

The POST request above sends two values to ThingTweet:

1. api_key is required so that ThingTweet knows which Twitter account to send the information to.

2. status is required by Twitter. It contains the text of the status update.

Aside from api_key, ThingTweet passes the key/value pairs on to Twitter so you can add any of the fields from the status update method in Twitter’s API:

Field Description

status The text of your status update. Usually limited to 140 characters.

in_reply_to_status_id The ID of an existing status update that this update is in reply to.

lat Specifies the geographic latitude that this tweet refers to.

long Specifies the geographic longitude that this tweet refers to.

place_id A geocode of a particular place in the world.

display_coordinates Whether or not to put a pin where the tweet has been sent from. This should be either true or false.

trim_user

Whether or not to display the full author’s details when this tweet is displayed in a timeline. This should be either true or false.

include_entities

Specifies whether the tweet includes additional

metadata in an entities node. This should be either true or false.

You can also include special commands such as direct messaging and retweets.

These commands are usually sent at the start of the status update message and, although not used in this project, a list of these can be found at

https://support.twitter.com/articles/14020-twitter-for-sms-basic-features

Extend the tweet() function to send a POST request by adding the following the code before the call to myClient.stop():

myClient.print("POST ");

myClient.print(wFile);

myClient.println(" HTTP/1.0");

myClient.print("Host: ");

myClient.println(wServer);

myClient.println("Connection: close");

myClient.println("Content-Type: application/x-www-form-urlencoded");

myClient.print("Content-Length: ");

myClient.println(message.length()+32);

myClient.println();

//POST some data

myClient.print("api_key=");

myClient.print(API_Key);

myClient.print("&status=");

myClient.println(message);

The Content-Length is 32 plus the number of characters in the message string. 32 refers to the number of characters used in the first part of the data,

api_key=THE16DIGITAPIKEY&status=.

After the server receives the number of bytes of data indicated by the Content-Length field, it processes your request and returns an HTTP response header followed by single value to indicate whether the action succeeded.

To process the server’s response:

1. Check that the HTTP status code of the response is 200. For more information, see Reacting to HTTP Status Codes.

2. Skip the remainder of the HTTP header and read the value sent by ThingTweet, which will usually be only one character.

3. Return true if the value is the ASCII character ‘1’ (49), and false if it is anything else.

The code for the tweet() function should now look similar to this:

boolean tweet(String message) { boolean result = true;

digitalWrite(LED, HIGH);

Serial.print("Connecting to ThingTweet… ");

if (myClient.connect(wServer, 80) != 1) { Serial.println("FAILED!");

return false;

}

Serial.println("OK!");

myClient.print("POST ");

myClient.print(wFile);

myClient.println(" HTTP/1.0");

myClient.print("Host: ");

myClient.println(wServer);

myClient.println("Connection: close");

myClient.println("Content-Type: application/x-www-form-urlencoded");

myClient.print("Content-Length: ");

myClient.println(message.length()+32);

myClient.println();

//POST some data

myClient.print("api_key=");

myClient.print(API_Key);

myClient.print("&status=");

myClient.println(message);

char rc = 0;

skipHeader();

while(myClient.connected()) { if (myClient.available() > 0) { rc = myClient.read();

break;

} }

if (rc == '1') result = true;

else

result = false;

myClient.stop();

digitalWrite(LED, LOW);

return result;

}

This function currently ignores the HTTP status code, which is not a

recommended course of action, but checking only the ThingTweet return code is usually sufficient while testing.