@@ -62,7 +62,7 @@ inline int strncasecmp(const char *s1, const char *s2, size_t n) {
62
62
* The user application sees only the JSON body, not the timetoken.
63
63
* As soon as the body ends, PubSubclient reads the rest of HTTP reply
64
64
* itself and disconnects. The stored timetoken is used in the next call
65
- * to the PubSub ::subscribe method.
65
+ * to the PubNub ::subscribe() method.
66
66
*/
67
67
class PubSubClient : public PubNub_BASE_CLIENT {
68
68
public:
@@ -174,13 +174,39 @@ class PubNub {
174
174
* @return boolean whether begin() was successful.
175
175
*/
176
176
bool begin (const char *publish_key, const char *subscribe_key, const char *origin = " pubsub.pubnub.com" ) {
177
- d_publish_key = publish_key;
178
- d_subscribe_key = subscribe_key;
179
- d_origin = origin;
180
- d_uuid = 0 ;
181
- d_auth = 0 ;
177
+ d_publish_key = publish_key;
178
+ d_subscribe_key = subscribe_key;
179
+ d_origin = origin;
180
+ d_uuid = 0 ;
181
+ d_auth = 0 ;
182
+ d_last_http_status_code_class = http_scc_unknown;
182
183
}
183
184
185
+ /* *
186
+ * HTTP status code class. It is defined by the first digit of the
187
+ * HTTP status code.
188
+ *
189
+ * @see RFC 7231 Section 6
190
+ */
191
+ enum http_status_code_class {
192
+ /* * This is not defined in the RFC, we use it to indicate
193
+ "none/unknown" */
194
+ http_scc_unknown = 0 ,
195
+ /* * The request was received, continuing process */
196
+ http_scc_informational = 1 ,
197
+ /* * The request was successfully received, understood, and
198
+ accepted */
199
+ http_scc_success = 2 ,
200
+ /* * Further action needs to be taken in order to complete the
201
+ request */
202
+ http_scc_redirection = 3 ,
203
+ /* * The request contains bad syntax or cannot be fulfilled */
204
+ http_scc_client_error = 4 ,
205
+ /* * The server failed to fulfill an apparently valid
206
+ request */
207
+ http_scc_server_error = 5
208
+ };
209
+
184
210
/* *
185
211
* Set the UUID identification of PubNub client. This is useful
186
212
* e.g. for presence identification.
@@ -204,19 +230,25 @@ class PubNub {
204
230
}
205
231
206
232
/* *
207
- * Publish
208
- *
209
- * Send a message (assumed to be well-formed JSON) to a given channel.
233
+ * Publish/Send a message (assumed to be well-formed JSON) to a
234
+ * given channel.
210
235
*
211
236
* Note that the reply can be obtained using code like:
212
237
213
- client = publish("demo", "\"lala\"");
214
- if (!client) return; // error
238
+ client = PubNub.publish("demo", "\"lala\"");
239
+ if (!client) {
240
+ Serial.println("Failed to publish, got no response from PubNub");
241
+ return;
242
+ }
243
+ if (PubNub.get_last_http_status_code_class() != PubNub::http_scc_success) {
244
+ Serial.print("Got HTTP status code error from PubNub, class: ");
245
+ Serial.print((int)PubNub.get_last_http_status_code_class(), DEC);
246
+ }
215
247
while (client->connected()) {
216
248
// More sophisticated code will want to add timeout handling here
217
249
while (client->connected() && !client->available()) ; // wait
218
250
char c = client->read();
219
- Serial.print(c);
251
+ Serial.print(c);
220
252
}
221
253
client->stop();
222
254
@@ -235,12 +267,10 @@ class PubNub {
235
267
inline PubNub_BASE_CLIENT *publish (const char *channel, const char *message, int timeout = 30 );
236
268
237
269
/* *
238
- * Subscribe
239
- *
240
- * Listen for a message on a given channel. The function will block
241
- * and return when a message arrives. Typically, you will run this
242
- * function from loop() function to keep listening for messages
243
- * indefinitely.
270
+ * Subscribe/Listen for a message on a given channel. The function
271
+ * will block and return when a message arrives. Typically, you
272
+ * will run this function from loop() function to keep listening
273
+ * for messages indefinitely.
244
274
*
245
275
* As a reply, you will get a JSON array with messages, e.g.:
246
276
* ["msg1",{msg2:"x"}]
@@ -265,6 +295,14 @@ class PubNub {
265
295
* @return string Stream-ish object with reply message or 0 on error. */
266
296
inline PubNub_BASE_CLIENT *history (const char *channel, int limit = 10 , int timeout = 310 );
267
297
298
+ /* * Returns the HTTP status code class of the last PubNub
299
+ transaction. If the transaction failed without getting a
300
+ (HTTP) response, it will be "unknown".
301
+ */
302
+ inline http_status_code_class get_last_http_status_code_class () const {
303
+ return d_last_http_status_code_class;
304
+ }
305
+
268
306
private:
269
307
enum PubNub_BH {
270
308
PubNub_BH_OK,
@@ -279,6 +317,9 @@ class PubNub {
279
317
const char *d_origin;
280
318
const char *d_uuid;
281
319
const char *d_auth;
320
+
321
+ // / The HTTP status code class of the last PubNub transaction
322
+ http_status_code_class d_last_http_status_code_class;
282
323
283
324
PubNub_BASE_CLIENT publish_client, history_client;
284
325
PubSubClient subscribe_client;
@@ -450,6 +491,7 @@ inline PubNub_BASE_CLIENT *PubNub::publish(const char *channel, const char *mess
450
491
return 0 ;
451
492
}
452
493
494
+ d_last_http_status_code_class = http_scc_unknown;
453
495
client.flush ();
454
496
client.print (" GET /publish/" );
455
497
client.print (d_publish_key);
@@ -491,16 +533,12 @@ inline PubNub_BASE_CLIENT *PubNub::publish(const char *channel, const char *mess
491
533
enum PubNub::PubNub_BH ret = this ->_request_bh (client, t_start, timeout, have_param ? ' &' : ' ?' );
492
534
switch (ret) {
493
535
case PubNub_BH_OK:
494
- /* Success and reached body, return handle to the client
495
- * for further perusal. */
496
536
return &client;
497
537
case PubNub_BH_ERROR:
498
- /* Failure. */
499
538
client.stop ();
500
539
while (client.connected ()) ;
501
540
return 0 ;
502
541
case PubNub_BH_TIMEOUT:
503
- /* Time out. Try again. */
504
542
client.stop ();
505
543
while (client.connected ()) ;
506
544
goto retry;
@@ -524,6 +562,7 @@ inline PubSubClient *PubNub::subscribe(const char *channel, int timeout)
524
562
return 0 ;
525
563
}
526
564
565
+ d_last_http_status_code_class = http_scc_unknown;
527
566
client.flush ();
528
567
client.print (" GET /subscribe/" );
529
568
client.print (d_subscribe_key);
@@ -549,10 +588,8 @@ inline PubSubClient *PubNub::subscribe(const char *channel, int timeout)
549
588
/* Success and reached body. We need to eat '[' first,
550
589
* as our API contract is to return only the "message body"
551
590
* part of reply from subscribe. */
552
- if (!client.wait_for_data ()
553
- || client.read () != ' [' ) {
554
- /* Something unexpected. */
555
- DBGprintln (" Unexpected body in subscribe" );
591
+ if (!client.wait_for_data () || client.read () != ' [' ) {
592
+ DBGprintln (" Unexpected body in subscribe response" );
556
593
client.stop ();
557
594
while (client.connected ()) ;
558
595
return 0 ;
@@ -565,13 +602,11 @@ inline PubSubClient *PubNub::subscribe(const char *channel, int timeout)
565
602
return &client;
566
603
567
604
case PubNub_BH_ERROR:
568
- /* Failure. */
569
605
client.stop ();
570
606
while (client.connected ()) ;
571
607
return 0 ;
572
608
573
609
case PubNub_BH_TIMEOUT:
574
- /* Time out. Try again. */
575
610
client.stop ();
576
611
while (client.connected ()) ;
577
612
goto retry;
@@ -592,6 +627,7 @@ inline PubNub_BASE_CLIENT *PubNub::history(const char *channel, int limit, int t
592
627
return 0 ;
593
628
}
594
629
630
+ d_last_http_status_code_class = http_scc_unknown;
595
631
client.flush ();
596
632
client.print (" GET /history/" );
597
633
client.print (d_subscribe_key);
@@ -603,16 +639,12 @@ inline PubNub_BASE_CLIENT *PubNub::history(const char *channel, int limit, int t
603
639
enum PubNub::PubNub_BH ret = this ->_request_bh (client, t_start, timeout, ' ?' );
604
640
switch (ret) {
605
641
case PubNub_BH_OK:
606
- /* Success and reached body, return handle to the client
607
- * for further perusal. */
608
642
return &client;
609
643
case PubNub_BH_ERROR:
610
- /* Failure. */
611
644
client.stop ();
612
645
while (client.connected ()) ;
613
646
return 0 ;
614
647
case PubNub_BH_TIMEOUT:
615
- /* Time out. Try again. */
616
648
client.stop ();
617
649
while (client.connected ()) ;
618
650
goto retry;
@@ -653,15 +685,8 @@ inline enum PubNub::PubNub_BH PubNub::_request_bh(PubNub_BASE_CLIENT &client, un
653
685
/* Now, first digit of HTTP code. */
654
686
WAIT ();
655
687
char c = client.read ();
656
- if (c != ' 2' ) {
657
- /* HTTP code that is NOT 2xx means trouble.
658
- * kthxbai */
659
- DBGprint (" Wrong HTTP status first digit ASCII code: " );
660
- DBGprint ((int ) c, DEC);
661
- DBGprintln (" in bottom half" );
662
- return PubNub_BH_ERROR;
663
- }
664
-
688
+ d_last_http_status_code_class = static_cast <http_status_code_class>(c - ' 0' );
689
+
665
690
/* Now, we enter in a state machine that shall guide us through
666
691
* the remaining headers to the beginning of the body. */
667
692
enum {
0 commit comments