]> git.piffa.net Git - arduino/blob - books/pdummies/Libraries/Twitter/Twitter.h
multitasking
[arduino] / books / pdummies / Libraries / Twitter / Twitter.h
1 /* -*- c++ -*-
2  *
3  * Twitter.h
4  *
5  * Author: Markku Rossi <mtr@iki.fi>
6  *
7  * Copyright (c) 2011-2012 Markku Rossi
8  *
9  * This program is free software: you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation, either version 3 of the
12  * License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see
21  * <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #ifndef TWITTER_H
26 #define TWITTER_H
27
28 #if defined(ARDUINO) && ARDUINO >= 100
29 #include "Arduino.h"
30 #else
31 #include "WProgram.h"
32 #endif
33
34 #include <avr/pgmspace.h>
35 #include <EEPROM.h>
36 #include <sha1.h>
37 #include <Ethernet.h>
38 #include <Time.h>
39
40 class Twitter
41 {
42 public:
43
44   /* Constructs a new Twitter instance with the work buffer `buffer',
45      `buffer_len'. */
46   Twitter(char *buffer, size_t buffer_len);
47
48   /* Set the Twitter API endpoint configuration.
49
50      The argument `server' specifies the fully qualified server name
51      (e.g. `api.twitter.com').  The argument `uri' contains the API
52      URI at the server (e.g. `/1/statuses/update.json').
53
54      The arguments `ip', `port' specify the HTTP connection end-point.
55      If the argument `proxy' is false, the connection end-point must
56      be the Twitter server.  If the argument `proxy' is true, the
57      connection end-point must be specify you HTTP proxy server to use
58      for the operation.  The `ip' array must remain valid as long as
59      this twitter instance is used; the method does not copy the `ip'
60      argument but stores a pointer to the provided value. */
61   void set_twitter_endpoint(const prog_char server[], const prog_char uri[],
62                             IPAddress ip, uint16_t port, bool proxy);
63
64   /* Set the client application identification to `consumer_key',
65      `consumer_secret'. */
66   void set_client_id(const prog_char consumer_key[],
67                      const prog_char consumer_secret[]);
68
69   /* Set the twitter account identification to program memory data
70      `access_token', `token_secret. */
71   void set_account_id(const prog_char access_token[],
72                       const prog_char token_secret[]);
73
74   /* Set the twitter account identification to EEPROM memory data
75      `access_token', `token_secret'. */
76   void set_account_id(int access_token, int token_secret);
77
78   /* Tests if this twitter instance is ready for twitter
79      communication.  The method returns true if twitter messages can
80      be sent and false if the twitter instance is still initializing.
81      You should keep calling this method from your loop() and do your
82      twitter interactions when this method returns true. */
83   bool is_ready(void);
84
85   /* Gets the current UTC time.  The twitter module queries and
86      maintains the UTC time based on server HTTP `Date' response
87      header.  The method returns the current UTC Unix time in seconds,
88      or 0 if the time has not been resolved yet.  This will return a
89      non-zero value after init() has returned true. */
90   unsigned long get_time(void);
91
92   /* Post status message `message' to twitter.  The message must be
93      UTF-8 encoded.  The method returns true if the status message was
94      posted and false on error. */
95   bool post_status(const char *message);
96
97   /* URL encode character `ch' into the buffer `buffer'.  The method
98      returns a pointer to the next byte after the encoded value. */
99   static char *url_encode(char *buffer, char ch);
100
101   /* URL encode c-string `data' into the buffer `buffer'.  The method
102      returns a pointer to the next byte after the encoded value. */
103   static char *url_encode(char *buffer, const char *data);
104
105   /* URL encode program memory c-string `data' into the buffer
106      `buffer'.  The method returns a pointer to the next byte after
107      the encoded value. */
108   static char *url_encode_pgm(char *buffer, const prog_char data[]);
109
110   /* URL encode EEPROM memory c-string that starts from address
111      `address' into the buffer `buffer'.  The method returns a pointer
112      to the next byte after the encoded value. */
113   static char *url_encode_eeprom(char *buffer, int address);
114
115   /* Hex encode binary data `data', `data_len' into the buffer
116      `buffer'.  The method returns a pointer to the next byte after
117      the encoded value. */
118   static char *hex_encode(char *buffer, const uint8_t *data, size_t data_len);
119
120   /* Base64 encode binary data `data', `data_len' into the buffer
121      `buffer'.  The method returns a pointer to the next byte after
122      the encoded value. */
123   static char *base64_encode(char *buffer, const uint8_t *data,
124                              size_t data_len);
125
126 private:
127
128   /* Create a random nonce into the member `nonce.  The method uses
129      `timestamp' as its random seed so you must set it before calling
130      this method. */
131   void create_nonce(void);
132
133   /* Compute OAuth signature for the status message `message'.  The
134      method uses the current state from consumer and access tokens and
135      from `timestamp' and `nonce' member.  The computed signature will
136      remain in the global `Sha1' instance and is pointed by
137      `signature'.  You must not use the `Sha1' instance before you
138      have consumed value. */
139   void compute_authorization(const char *message);
140
141   /* Add character `ch' into the authorization signature hmac. */
142   void auth_add(char ch);
143
144   /* Add string `str' into the authorization signature hmac. */
145   void auth_add(const char *str);
146
147   /* Add program memory string `str' into the authorization signature
148      hmac. */
149   void auth_add_pgm(const prog_char str[]);
150
151   /* Add request parameter `key', `value' into the authorization
152      signature hmac.  The argument `workbuf' specifies a working
153      buffer for the method. */
154   void auth_add_param(const char *key, const char *value, char *workbuf);
155
156   /* Add authorization parameter separator into the authorization
157      signature hmac. */
158   void auth_add_param_separator(void);
159
160   /* Add request key-value separator into the authorization signature
161      hmac. */
162   void auth_add_value_separator(void);
163
164   /* Print program memory string `str' to the output stream of the
165      HTTP client `client'. */
166   static void http_print(Client *client, const prog_char str[]);
167
168   /* Print program memory string `str' and line separator string to
169      the output stream of the HTTP client `client'. */
170   static void http_println(Client *client, const prog_char str[]);
171
172   /* Print line separator string to the output stream of the HTTP
173      client `client'. */
174   static void http_newline(Client *client);
175
176   /* Print the argument program memory string to serial output. */
177   static void println(const prog_char str[]);
178
179   /* Read a line from the connection `client' into the buffer `buffer'
180      that has `buflen' bytes of space.  The method returns true if a
181      line was read and false on error. */
182   static bool read_line(Client *client, char *buffer, size_t buflen);
183
184   /* Queries the current time with a HEAD request to the server.  The
185      method returns true if the time was retrieved and false on
186      error. */
187   bool query_time(void);
188
189   /* Process the response header line `buffer' and update the system
190      `basetime' if the header is a HTTP Date header.  The method
191      returns true if the header line was a `Date' header and false
192      otherwise. */
193   bool process_date_header(char *buffer);
194
195   /* Parse the value of the HTTP Date header `date'.  The method
196      returns the Unix time value in seconds or 0 if the header could
197      not be parsed. */
198   long parse_date(char *date);
199
200   /* Parse month name `str' and return its number (1-12).  The method
201      returns a pointer to the end of the parsed month in `end'.  The
202      method returns 0 if the month could not be parsed. */
203   int parse_month(char *str, char **end);
204
205   /* The base timestamp for current time computation. */
206   unsigned long basetime;
207
208   /* Last milliseconds from the system clock. */
209   unsigned long last_millis;
210
211   /* Flags. */
212
213   /* Is the provided HTTP end point a HTTP proxy or the Twitter
214      server? */
215   unsigned int proxy : 1;
216
217   /* Is access token in PGM or in EEPROM? */
218   unsigned int access_token_pgm : 1;
219
220   /* Random nonce for the OAuth request. */
221   uint8_t nonce[8];
222
223   /* Request timestamp as Unix time. */
224   unsigned long timestamp;
225
226   /* This points to Sha1 so don't touch it before you have consumed
227      the value. */
228   uint8_t *signature;
229
230   /* Work buffer. */
231   char *buffer;
232
233   /* The size of the work buffer `buffer'. */
234   size_t buffer_len;
235
236   /* Twitter server host name. */
237   const prog_char *server;
238
239   /* Twitter API URI at the server. */
240   const prog_char *uri;
241
242   /* An IP address to connnect to. */
243   IPAddress ip;
244
245   /* TCP port number to connnect to. */
246   uint16_t port;
247
248   /* Application consumer key. */
249   const prog_char *consumer_key;
250
251   /* Application consumer secret. */
252   const prog_char *consumer_secret;
253
254   /* Twitter account access token. */
255   union
256   {
257     const prog_char *pgm;
258     int eeprom;
259   } access_token;
260
261   /* Twitter account access token secret. */
262   union
263   {
264     const prog_char *pgm;
265     int eeprom;
266   } token_secret;
267 };
268
269 #endif /* not TWITTER_H */