source: rtos_arduino/trunk/arduino_lib/libraries/PubNub/PubNub.h@ 211

Last change on this file since 211 was 211, checked in by ertl-honda, 8 years ago

公開されているコードを追加

File size: 8.3 KB
Line 
1#ifndef PubNub_h
2#define PubNub_h
3
4
5#include <stdint.h>
6
7
8/* By default, the PubNub library is built to work with the Ethernet
9 * shield. WiFi shield support can be enabled by commenting the
10 * following line and commenting out the line after that. Refer
11 * to the PubNubJsonWifi sketch for a complete example. */
12#define PubNub_Ethernet
13//#define PubNub_WiFi
14
15
16#if defined(PubNub_Ethernet)
17#include <Ethernet.h>
18#define PubNub_BASE_CLIENT EthernetClient
19
20#elif defined(PubNub_WiFi)
21#include <WiFi.h>
22#define PubNub_BASE_CLIENT WiFiClient
23
24#else
25#error PubNub_BASE_CLIENT set to an invalid value!
26#endif
27
28
29/* Some notes:
30 *
31 * (i) There is no SSL support on Arduino, it is unfeasible with
32 * Arduino Uno or even Arduino Mega's computing power and memory limits.
33 * All the traffic goes on the wire unencrypted and unsigned.
34 *
35 * (ii) We re-resolve the origin server IP address before each request.
36 * This means some slow-down for intensive communication, but we rather
37 * expect light traffic and very long-running sketches (days, months),
38 * where refreshing the IP address is quite desirable.
39 *
40 * (iii) We let the users read replies at their leisure instead of
41 * returning an already preloaded string so that (a) they can do that
42 * in loop() code while taking care of other things as well (b) we don't
43 * waste precious RAM by pre-allocating buffers that are never needed.
44 *
45 * (iv) If you are having problems connecting, maybe you have hit
46 * a bug in Debian's version of Arduino pertaining the DNS code. Try using
47 * an IP address as origin and/or upgrading your Arduino package.
48 *
49 * (v) The optional timeout parameter allows you to specify a timeout
50 * period after which the subscribe call shall be retried. Note
51 * that this timeout is applied only for reading response, not for
52 * connecting or sending data; use retransmission parameters of
53 * the Ethernet library to tune this. As a rule of thumb, timeout
54 * smaller than 30 seconds may still block longer with flaky
55 * network. Default server-side timeout of PubNub API is 300s.
56 *
57 * (vi) If some of the PubNub calls fail with your WiFi shield (e.g. you
58 * see "subscribe error" and similar messages in serial console), your
59 * WiFi shield firmware may be buggy - e.g. a WiFi shield bought
60 * commercially in May 2013 had a firmware that had to be upgaded.
61 * This is not so difficult to do, simply follow:
62 *
63 * http://arduino.cc/en/Hacking/WiFiShieldFirmwareUpgrading
64 *
65 * (vii) The vendor firmware for the WiFi shield has dubious TCP implementation;
66 * for example, TCP ports of outgoing connections are always chosen from the
67 * same sequence, so if you reset your Arduino, some of the new connections
68 * may interfere with an outstanding TCP connection that has not been closed
69 * before the reset; i.e. you will typically see a single failed request
70 * somewhere down the road after a reset.
71 *
72 * (viii) It is essential to use a new enough Arduino version so that
73 * the WiFi library actually works properly. Most notably, version 1.0.5
74 * has been confirmed to work while Arduino 1.0.4 is broken.
75 */
76
77
78/* This class is a thin EthernetClient wrapper whose goal is to
79 * automatically acquire time token information when reading
80 * subscribe call response.
81 *
82 * (i) The user application sees only the JSON body, not the timetoken.
83 * As soon as the body ends, PubSubclient reads the rest of HTTP reply
84 * itself and disconnects. The stored timetoken is used in the next call
85 * to the PubSub::subscribe method then. */
86class PubSubClient : public PubNub_BASE_CLIENT {
87public:
88 PubSubClient() :
89 PubNub_BASE_CLIENT(), json_enabled(false)
90 {
91 strcpy(timetoken, "0");
92 }
93
94 /* Customized functions that make reading stop as soon as we
95 * have hit ',' outside of braces and string, which indicates
96 * end of JSON body. */
97 virtual int read();
98 virtual int read(uint8_t *buf, size_t size);
99 virtual void stop();
100
101 /* Block until data is available. Returns false in case the
102 * connection goes down or timeout expires. */
103 bool wait_for_data(int timeout = 310);
104
105 /* Enable the JSON state machine. */
106 void start_body();
107
108 inline char *server_timetoken() { return timetoken; }
109
110private:
111 void _state_input(uint8_t ch, uint8_t *nextbuf, size_t nextsize);
112 void _grab_timetoken(uint8_t *nextbuf, size_t nextsize);
113
114 /* JSON state machine context */
115 bool json_enabled:1;
116 bool in_string:1;
117 bool after_backslash:1;
118 int braces_depth;
119
120 /* Time token acquired during the last subscribe request. */
121 char timetoken[22];
122};
123
124
125enum PubNub_BH {
126 PubNub_BH_OK,
127 PubNub_BH_ERROR,
128 PubNub_BH_TIMEOUT,
129};
130
131class PubNub {
132public:
133 /* Init the Pubnub Client API
134 *
135 * This should be called after Ethernet.begin().
136 * Note that the string parameters are not copied; do not
137 * overwrite or free the memory where you stored the keys!
138 * (If you are passing string literals, don't worry about it.)
139 * Note that you should run only a single publish at once.
140 *
141 * @param string publish_key required key to send messages.
142 * @param string subscribe_key required key to receive messages.
143 * @param string origin optional setting for cloud origin.
144 * @return boolean whether begin() was successful. */
145 bool begin(const char *publish_key, const char *subscribe_key, const char *origin = "pubsub.pubnub.com");
146
147 /* Set the UUID identification of PubNub client. This is useful
148 * e.g. for presence identification.
149 *
150 * Pass NULL to unset. The string is not copied over (just like
151 * in begin()). See the PubNubSubscriber example for simple code
152 * that generates a random UUID (although not 100% reliable). */
153 void set_uuid(const char *uuid);
154
155 /* Set the authorization key/token of PubNub client. This is useful
156 * e.g. for access rights validation (PAM).
157 *
158 * Pass NULL to unset. The string is not copied over (just like
159 * in begin()). */
160 void set_auth(const char *auth);
161
162 /* Publish
163 *
164 * Send a message (assumed to be well-formed JSON) to a given channel.
165 *
166 * Note that the reply can be obtained using code like:
167 client = publish("demo", "\"lala\"");
168 if (!client) return; // error
169 while (client->connected()) {
170 // More sophisticated code will want to add timeout handling here
171 while (client->connected() && !client->available()) ; // wait
172 char c = client->read();
173 Serial.print(c);
174 }
175 client->stop();
176 * You will get content right away, the header has been already
177 * skipped inside the function. If you do not care about
178 * the reply, just call client->stop(); immediately.
179 *
180 * It returns an object that is typically EthernetClient (but it
181 * can be a WiFiClient if you enabled the WiFi shield).
182 *
183 * @param string channel required channel name.
184 * @param string message required message string in JSON format.
185 * @param string timeout optional timeout in seconds.
186 * @return string Stream-ish object with reply message or NULL on error. */
187 PubNub_BASE_CLIENT *publish(const char *channel, const char *message, int timeout = 30);
188
189 /**
190 * Subscribe
191 *
192 * Listen for a message on a given channel. The function will block
193 * and return when a message arrives. Typically, you will run this
194 * function from loop() function to keep listening for messages
195 * indefinitely.
196 *
197 * As a reply, you will get a JSON array with messages, e.g.:
198 * ["msg1",{msg2:"x"}]
199 * and so on. Empty reply [] is also normal and your code must be
200 * able to handle that. Note that the reply specifically does not
201 * include the time token present in the raw reply.
202 *
203 * @param string channel required channel name.
204 * @param string timeout optional timeout in seconds.
205 * @return string Stream-ish object with reply message or NULL on error. */
206 PubSubClient *subscribe(const char *channel, int timeout = 310);
207
208 /**
209 * History
210 *
211 * Receive list of the last N messages on the given channel.
212 *
213 * @param string channel required channel name.
214 * @param int limit optional number of messages to retrieve.
215 * @param string timeout optional timeout in seconds.
216 * @return string Stream-ish object with reply message or NULL on error. */
217 PubNub_BASE_CLIENT *history(const char *channel, int limit = 10, int timeout = 310);
218
219private:
220 enum PubNub_BH _request_bh(PubNub_BASE_CLIENT &client, unsigned long t_start, int timeout, char qparsep);
221
222 const char *publish_key, *subscribe_key;
223 const char *origin;
224 const char *uuid;
225 const char *auth;
226
227 PubNub_BASE_CLIENT publish_client, history_client;
228 PubSubClient subscribe_client;
229};
230
231extern class PubNub PubNub;
232
233#endif
Note: See TracBrowser for help on using the repository browser.