Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/.gitignore
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/.gitignore	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/.gitignore	(revision 211)
@@ -0,0 +1,17 @@
+# Object files
+*.o
+
+# Libraries
+*.lib
+*.a
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/LICENSE
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/LICENSE	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/LICENSE	(revision 211)
@@ -0,0 +1,27 @@
+PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
+Copyright (c) 2013 PubNub Inc.
+http://www.pubnub.com/
+http://www.pubnub.com/terms
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
+Copyright (c) 2013 PubNub Inc.
+http://www.pubnub.com/
+http://www.pubnub.com/terms
Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/PubNub.cpp
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/PubNub.cpp	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/PubNub.cpp	(revision 211)
@@ -0,0 +1,481 @@
+#if defined(__AVR)
+#include <avr/pgmspace.h>
+#else
+#define strncasecmp_P(a, b, c) strncasecmp(a, b, c)
+#endif
+
+#include <ctype.h>
+#include "PubNub.h"
+
+// #define PUBNUB_DEBUG 1
+
+#ifdef PUBNUB_DEBUG
+#define DBGprint(x...) Serial.print(x)
+#define DBGprintln(x...) Serial.println(x)
+#else
+#define DBGprint(x...)
+#define DBGprintln(x...)
+#endif
+
+/* There are some special considerations when using the WiFi libary,
+ * compared to the Ethernet library:
+ *
+ * (i) The client object may return stale data from previous connection,
+ * so we should call .flush() after initiating a connection.
+ *
+ * (ii) It appears .stop() does not block on really terminating
+ * the connection, do that manually.
+ *
+ * (iii) Data may still be available while connected() returns false
+ * already; use available() test on a lot of places where we used
+ * connected() before.
+ */
+
+class PubNub PubNub;
+
+bool PubNub::begin(const char *publish_key_, const char *subscribe_key_, const char *origin_)
+{
+	publish_key = publish_key_;
+	subscribe_key = subscribe_key_;
+	origin = origin_;
+	uuid = NULL;
+	auth = NULL;
+}
+
+void PubNub::set_uuid(const char *uuid_)
+{
+	uuid = uuid_;
+}
+
+void PubNub::set_auth(const char *auth_)
+{
+	auth = auth_;
+}
+
+PubNub_BASE_CLIENT *PubNub::publish(const char *channel, const char *message, int timeout)
+{
+	PubNub_BASE_CLIENT &client = publish_client;
+	unsigned long t_start;
+	int have_param = 0;
+
+retry:
+	t_start = millis();
+	/* connect() timeout is about 30s, much lower than our usual
+	 * timeout is. */
+	if (!client.connect(origin, 80)) {
+		DBGprintln("Connection error");
+		client.stop();
+		return NULL;
+	}
+
+	client.flush();
+	client.print("GET /publish/");
+	client.print(publish_key);
+	client.print("/");
+	client.print(subscribe_key);
+	client.print("/0/");
+	client.print(channel);
+	client.print("/0/");
+
+	/* Inject message, URI-escaping it in the process.
+	 * We are careful to save RAM by not using any copies
+	 * of the string or explicit buffers. */
+	const char *pmessage = message;
+	while (pmessage[0]) {
+		/* RFC 3986 Unreserved characters plus few
+		 * safe reserved ones. */
+		size_t okspan = strspn(pmessage, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~" ",=:;@[]");
+		if (okspan > 0) {
+			client.write((const uint8_t *) pmessage, okspan);
+			pmessage += okspan;
+		}
+		if (pmessage[0]) {
+			/* %-encode a non-ok character. */
+			char enc[3] = {'%'};
+			enc[1] = "0123456789ABCDEF"[pmessage[0] / 16];
+			enc[2] = "0123456789ABCDEF"[pmessage[0] % 16];
+			client.write((const uint8_t *) enc, 3);
+			pmessage++;
+		}
+	}
+
+	if (auth) {
+		client.print(have_param ? '&' : '?');
+		client.print("auth=");
+		client.print(auth);
+		have_param = 1;
+	}
+	
+	enum PubNub_BH ret = this->_request_bh(client, t_start, timeout, have_param ? '&' : '?');
+	switch (ret) {
+	case PubNub_BH_OK:
+		/* Success and reached body, return handle to the client
+		 * for further perusal. */
+		return &client;
+	case PubNub_BH_ERROR:
+		/* Failure. */
+		client.stop();
+		while (client.connected()) ;
+		return NULL;
+	case PubNub_BH_TIMEOUT:
+		/* Time out. Try again. */
+		client.stop();
+		while (client.connected()) ;
+		goto retry;
+	}
+}
+
+PubSubClient *PubNub::subscribe(const char *channel, int timeout)
+{
+	PubSubClient &client = subscribe_client;
+	unsigned long t_start;
+	int have_param = 0;
+
+retry:
+	t_start = millis();
+	/* connect() timeout is about 30s, much lower than our usual
+	 * timeout is. */
+	if (!client.connect(origin, 80)) {
+		DBGprintln("Connection error");
+		client.stop();
+		return NULL;
+	}
+
+	client.flush();
+	client.print("GET /subscribe/");
+	client.print(subscribe_key);
+	client.print("/");
+	client.print(channel);
+	client.print("/0/");
+	client.print(client.server_timetoken());
+	if (uuid) {
+		client.print("?uuid=");
+		client.print(uuid);
+		have_param = 1;
+	}
+	if (auth) {
+		client.print(have_param ? '&' : '?');
+		client.print("auth=");
+		client.print(auth);
+		have_param = 1;
+	}
+
+	enum PubNub_BH ret = this->_request_bh(client, t_start, timeout, have_param ? '&' : '?');
+	switch (ret) {
+	case PubNub_BH_OK:
+		/* Success and reached body. We need to eat '[' first,
+		 * as our API contract is to return only the "message body"
+		 * part of reply from subscribe. */
+		if (!client.wait_for_data()
+		    || client.read() != '[') {
+			/* Something unexpected. */
+			DBGprintln("Unexpected body in subscribe");
+			client.stop();
+			while (client.connected()) ;
+			return NULL;
+		}
+		/* Now return handle to the client for further perusal.
+		 * PubSubClient class will make sure that the client does
+		 * not see the time token but we stop right after the
+		 * message body. */
+		client.start_body();
+		return &client;
+
+	case PubNub_BH_ERROR:
+		/* Failure. */
+		client.stop();
+		while (client.connected()) ;
+		return NULL;
+
+	case PubNub_BH_TIMEOUT:
+		/* Time out. Try again. */
+		client.stop();
+		while (client.connected()) ;
+		goto retry;
+	}
+}
+
+PubNub_BASE_CLIENT *PubNub::history(const char *channel, int limit, int timeout)
+{
+	PubNub_BASE_CLIENT &client = history_client;
+	unsigned long t_start;
+
+retry:
+	t_start = millis();
+	if (!client.connect(origin, 80)) {
+		DBGprintln("Connection error");
+		client.stop();
+		return NULL;
+	}
+
+	client.flush();
+	client.print("GET /history/");
+	client.print(subscribe_key);
+	client.print("/");
+	client.print(channel);
+	client.print("/0/");
+	client.print(limit, DEC);
+
+	enum PubNub_BH ret = this->_request_bh(client, t_start, timeout, '?');
+	switch (ret) {
+	case PubNub_BH_OK:
+		/* Success and reached body, return handle to the client
+		 * for further perusal. */
+		return &client;
+	case PubNub_BH_ERROR:
+		/* Failure. */
+		client.stop();
+		while (client.connected()) ;
+		return NULL;
+	case PubNub_BH_TIMEOUT:
+		/* Time out. Try again. */
+		client.stop();
+		while (client.connected()) ;
+		goto retry;
+	}
+}
+
+enum PubNub_BH PubNub::_request_bh(PubNub_BASE_CLIENT &client, unsigned long t_start, int timeout, char qparsep)
+{
+	/* Finish the first line of the request. */
+	client.print(qparsep);
+	client.print("pnsdk=PubNub-Arduino/1.0 HTTP/1.1\r\n");
+	/* Finish HTTP request. */
+	client.print("Host: ");
+	client.print(origin);
+	client.print("\r\nUser-Agent: PubNub-Arduino/1.0\r\nConnection: close\r\n\r\n");
+
+#define WAIT() do { \
+	while (!client.available()) { \
+		/* wait, just check for timeout */ \
+		if (millis() - t_start > (unsigned long) timeout * 1000) { \
+			DBGprintln("Timeout in bottom half"); \
+			return PubNub_BH_TIMEOUT; \
+		} \
+		if (!client.connected()) { \
+			/* Oops, connection interrupted. */ \
+			DBGprintln("Connection reset in bottom half"); \
+			return PubNub_BH_ERROR; \
+		} \
+	} \
+} while (0)
+
+	/* Read first line with HTTP code. */
+	/* "HTTP/1.x " */
+	do {
+		WAIT();
+	} while (client.read() != ' ');
+	/* Now, first digit of HTTP code. */
+	WAIT();
+	char c = client.read();
+	if (c != '2') {
+		/* HTTP code that is NOT 2xx means trouble.
+		 * kthxbai */
+		DBGprint("Wrong HTTP status first digit ");
+		DBGprint((int) c, DEC);
+		DBGprintln(" in bottom half");
+		return PubNub_BH_ERROR;
+	}
+
+	/* Now, we enter in a state machine that shall guide us through
+	 * the remaining headers to the beginning of the body. */
+	enum {
+		RS_SKIPLINE, /* Skip the rest of this line. */
+		RS_LOADLINE, /* Try loading the line in a buffer. */
+	} request_state = RS_SKIPLINE; /* Skip the rest of status line first. */
+	bool chunked = false;
+
+	while (client.connected() || client.available()) {
+		/* Let's hope there is no stray LF without CR. */
+		if (request_state == RS_SKIPLINE) {
+			do {
+				WAIT();
+			} while (client.read() != '\n');
+			request_state = RS_LOADLINE;
+
+		} else { /* request_state == RS_LOADLINE */
+			/* line[] must be enough to hold
+			 * Transfer-Encoding: chunked (or \r\n) */
+			const static char PROGMEM chunked_str[] = "Transfer-Encoding: chunked\r\n";
+			char line[sizeof(chunked_str)]; /* Not NUL-terminated! */
+			int linelen = 0;
+			char ch = 0;
+			do {
+				WAIT();
+				ch = client.read();
+				line[linelen++] = ch;
+				if (linelen == strlen_P(chunked_str)
+				    && !strncasecmp_P(line, chunked_str, linelen)) {
+					/* Chunked encoding header. */
+					chunked = true;
+					break;
+				}
+			} while (ch != '\n' && linelen < sizeof(line));
+			if (ch != '\n') {
+				/* We are not at the end of the line yet.
+				 * Skip the rest of the line. */
+				request_state = RS_SKIPLINE;
+			} else if (linelen == 2 && line[0] == '\r') {
+				/* Empty line. This means headers end. */
+				break;
+			}
+		}
+	}
+
+	if (chunked) {
+		/* There is one extra line due to Transfer-encoding: chunked.
+		 * Our minimalistic support means that we hope for just
+		 * a single chunk, just skip the first line after header. */
+		do {
+			WAIT();
+		} while (client.read() != '\n');
+	}
+
+	/* Body begins now. */
+	return PubNub_BH_OK;
+}
+
+
+int PubSubClient::read()
+{
+	int c = PubNub_BASE_CLIENT::read();
+	if (!json_enabled || c == -1)
+		return c;
+
+	this->_state_input(c, NULL, 0);
+	return c;
+}
+
+int PubSubClient::read(uint8_t *buf, size_t size)
+{
+	int len = PubNub_BASE_CLIENT::read(buf, size);
+	if (!json_enabled || len <= 0)
+		return len;
+	for (int i = 0; i < len; i++) {
+		this->_state_input(buf[i], &buf[i+1], len - i - 1);
+		if (!available() && !connected()) {
+			/* We have hit the end somewhere in this buffer.
+			 * From user perspective, only characters up to
+			 * index i are valid. */
+			return i + 1;
+		}
+	}
+	return len;
+}
+
+bool PubSubClient::wait_for_data(int timeout)
+{
+	unsigned long t_start = millis();
+	while (connected() && !available()) {
+		if (millis() - t_start > (unsigned long) timeout * 1000)
+			return false; /* Time out. */
+	}
+	return available();
+}
+
+void PubSubClient::stop()
+{
+	if ((!available() && !connected()) || !json_enabled) {
+		PubNub_BASE_CLIENT::stop();
+		return;
+	}
+	/* We are still connected. Read the rest of the stream so that
+	 * we catch the timetoken. */
+	while (wait_for_data()) {
+		char ch = read();
+		this->_state_input(ch, NULL, 0);
+	}
+	json_enabled = false;
+}
+
+void PubSubClient::start_body()
+{
+	json_enabled = true;
+	in_string = after_backslash = false;
+	braces_depth = 0;
+}
+
+void PubSubClient::_state_input(uint8_t ch, uint8_t *nextbuf, size_t nextsize)
+{
+	/* Process a single character on input, updating the JSON
+	 * state machine. If we reached the last character of input
+	 * (just before expected ","), we will eat the rest of the body,
+	 * update timetoken and close the connection. */
+	if (in_string) {
+		if (after_backslash) {
+			/* Whatever this is... */
+			after_backslash = false;
+			return;
+		}
+		switch (ch) {
+		case '"':
+			in_string = false;
+			if (braces_depth == 0)
+				goto body_end;
+			return;
+		case '\\':
+			after_backslash = true;
+			return;
+		default:
+			return;
+		}
+
+	} else {
+		switch (ch) {
+		case '"':
+			in_string = true;
+			return;
+		case '{':
+		case '[':
+			braces_depth++;
+			return;
+		case '}':
+		case ']':
+			braces_depth--;
+			if (braces_depth <= 0)
+				goto body_end;
+			return;
+		default:
+			return;
+		}
+	}
+
+	return;
+body_end:
+	/* End of data here. */
+	this->_grab_timetoken(nextbuf, nextsize);
+}
+
+void PubSubClient::_grab_timetoken(uint8_t *nextbuf, size_t nextsize)
+{
+	char new_timetoken[22];
+	size_t new_timetoken_len = 0;
+
+	/* Expected followup now is:
+	 * 	,"13511688131075270"]
+	 */
+	/* Somewhat unwieldy macros that will first exhaust nextbuf[],
+	 * then read directly from socket. */
+#define WAIT() do { \
+	if (nextsize > 0) \
+		break; \
+	if (!wait_for_data()) { \
+		/* Oops, connection interrupted. */ \
+		return; \
+	} \
+} while (0)
+#define GETCHAR() (nextsize > 0 ? (nextsize--, *nextbuf++) : read())
+	do { WAIT(); } while (GETCHAR() != ',');
+	do { WAIT(); } while (GETCHAR() != '"');
+	do {
+		WAIT();
+		char ch = GETCHAR();
+		if (ch == '"')
+			break;
+		new_timetoken[new_timetoken_len++] = ch;
+		if (new_timetoken_len >= sizeof(new_timetoken) - 1)
+			break;
+	} while (1);
+	memcpy(timetoken, new_timetoken, new_timetoken_len);
+	timetoken[new_timetoken_len] = 0;
+}
Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/PubNub.h
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/PubNub.h	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/PubNub.h	(revision 211)
@@ -0,0 +1,233 @@
+#ifndef PubNub_h
+#define PubNub_h
+
+
+#include <stdint.h>
+
+
+/* By default, the PubNub library is built to work with the Ethernet
+ * shield. WiFi shield support can be enabled by commenting the
+ * following line and commenting out the line after that. Refer
+ * to the PubNubJsonWifi sketch for a complete example. */
+#define PubNub_Ethernet
+//#define PubNub_WiFi
+
+
+#if defined(PubNub_Ethernet)
+#include <Ethernet.h>
+#define PubNub_BASE_CLIENT EthernetClient
+
+#elif defined(PubNub_WiFi)
+#include <WiFi.h>
+#define PubNub_BASE_CLIENT WiFiClient
+
+#else
+#error PubNub_BASE_CLIENT set to an invalid value!
+#endif
+
+
+/* Some notes:
+ *
+ * (i) There is no SSL support on Arduino, it is unfeasible with
+ * Arduino Uno or even Arduino Mega's computing power and memory limits.
+ * All the traffic goes on the wire unencrypted and unsigned.
+ *
+ * (ii) We re-resolve the origin server IP address before each request.
+ * This means some slow-down for intensive communication, but we rather
+ * expect light traffic and very long-running sketches (days, months),
+ * where refreshing the IP address is quite desirable.
+ *
+ * (iii) We let the users read replies at their leisure instead of
+ * returning an already preloaded string so that (a) they can do that
+ * in loop() code while taking care of other things as well (b) we don't
+ * waste precious RAM by pre-allocating buffers that are never needed.
+ *
+ * (iv) If you are having problems connecting, maybe you have hit
+ * a bug in Debian's version of Arduino pertaining the DNS code. Try using
+ * an IP address as origin and/or upgrading your Arduino package.
+ *
+ * (v) The optional timeout parameter allows you to specify a timeout
+ * period after which the subscribe call shall be retried. Note
+ * that this timeout is applied only for reading response, not for
+ * connecting or sending data; use retransmission parameters of
+ * the Ethernet library to tune this. As a rule of thumb, timeout
+ * smaller than 30 seconds may still block longer with flaky
+ * network. Default server-side timeout of PubNub API is 300s.
+ *
+ * (vi) If some of the PubNub calls fail with your WiFi shield (e.g. you
+ * see "subscribe error" and similar messages in serial console), your
+ * WiFi shield firmware may be buggy - e.g. a WiFi shield bought
+ * commercially in May 2013 had a firmware that had to be upgaded.
+ * This is not so difficult to do, simply follow:
+ *
+ *   	http://arduino.cc/en/Hacking/WiFiShieldFirmwareUpgrading
+ *
+ * (vii) The vendor firmware for the WiFi shield has dubious TCP implementation;
+ * for example, TCP ports of outgoing connections are always chosen from the
+ * same sequence, so if you reset your Arduino, some of the new connections
+ * may interfere with an outstanding TCP connection that has not been closed
+ * before the reset; i.e. you will typically see a single failed request
+ * somewhere down the road after a reset.
+ *
+ * (viii) It is essential to use a new enough Arduino version so that
+ * the WiFi library actually works properly. Most notably, version 1.0.5
+ * has been confirmed to work while Arduino 1.0.4 is broken.
+ */
+
+
+/* This class is a thin EthernetClient wrapper whose goal is to
+ * automatically acquire time token information when reading
+ * subscribe call response.
+ *
+ * (i) The user application sees only the JSON body, not the timetoken.
+ * As soon as the body ends, PubSubclient reads the rest of HTTP reply
+ * itself and disconnects. The stored timetoken is used in the next call
+ * to the PubSub::subscribe method then. */
+class PubSubClient : public PubNub_BASE_CLIENT {
+public:
+	PubSubClient() :
+		PubNub_BASE_CLIENT(), json_enabled(false)
+	{
+		strcpy(timetoken, "0");
+	}
+
+	/* Customized functions that make reading stop as soon as we
+	 * have hit ',' outside of braces and string, which indicates
+	 * end of JSON body. */
+	virtual int read();
+	virtual int read(uint8_t *buf, size_t size);
+	virtual void stop();
+
+	/* Block until data is available. Returns false in case the
+	 * connection goes down or timeout expires. */
+	bool wait_for_data(int timeout = 310);
+
+	/* Enable the JSON state machine. */
+	void start_body();
+
+	inline char *server_timetoken() { return timetoken; }
+
+private:
+	void _state_input(uint8_t ch, uint8_t *nextbuf, size_t nextsize);
+	void _grab_timetoken(uint8_t *nextbuf, size_t nextsize);
+
+	/* JSON state machine context */
+	bool json_enabled:1;
+	bool in_string:1;
+	bool after_backslash:1;
+	int braces_depth;
+
+	/* Time token acquired during the last subscribe request. */
+	char timetoken[22];
+};
+
+
+enum PubNub_BH {
+	PubNub_BH_OK,
+	PubNub_BH_ERROR,
+	PubNub_BH_TIMEOUT,
+};
+
+class PubNub {
+public:
+	/* Init the Pubnub Client API
+	 *
+	 * This should be called after Ethernet.begin().
+	 * Note that the string parameters are not copied; do not
+	 * overwrite or free the memory where you stored the keys!
+	 * (If you are passing string literals, don't worry about it.)
+	 * Note that you should run only a single publish at once.
+	 *
+	 * @param string publish_key required key to send messages.
+	 * @param string subscribe_key required key to receive messages.
+	 * @param string origin optional setting for cloud origin.
+	 * @return boolean whether begin() was successful. */
+	bool begin(const char *publish_key, const char *subscribe_key, const char *origin = "pubsub.pubnub.com");
+
+	/* Set the UUID identification of PubNub client. This is useful
+	 * e.g. for presence identification.
+	 *
+	 * Pass NULL to unset. The string is not copied over (just like
+	 * in begin()). See the PubNubSubscriber example for simple code
+	 * that generates a random UUID (although not 100% reliable). */
+	void set_uuid(const char *uuid);
+
+	/* Set the authorization key/token of PubNub client. This is useful
+	 * e.g. for access rights validation (PAM).
+	 *
+	 * Pass NULL to unset. The string is not copied over (just like
+	 * in begin()). */
+	void set_auth(const char *auth);
+
+	/* Publish
+	 *
+	 * Send a message (assumed to be well-formed JSON) to a given channel.
+	 *
+	 * Note that the reply can be obtained using code like:
+	     client = publish("demo", "\"lala\"");
+	     if (!client) return; // error
+	     while (client->connected()) {
+	       // More sophisticated code will want to add timeout handling here
+	       while (client->connected() && !client->available()) ; // wait
+	       char c = client->read();
+	       Serial.print(c);
+	     }
+	     client->stop();
+	 * You will get content right away, the header has been already
+	 * skipped inside the function. If you do not care about
+	 * the reply, just call client->stop(); immediately.
+	 *
+	 * It returns an object that is typically EthernetClient (but it
+	 * can be a WiFiClient if you enabled the WiFi shield).
+	 *
+	 * @param string channel required channel name.
+	 * @param string message required message string in JSON format.
+	 * @param string timeout optional timeout in seconds.
+	 * @return string Stream-ish object with reply message or NULL on error. */
+	PubNub_BASE_CLIENT *publish(const char *channel, const char *message, int timeout = 30);
+
+	/**
+	 * Subscribe
+	 *
+	 * Listen for a message on a given channel. The function will block
+	 * and return when a message arrives. Typically, you will run this
+	 * function from loop() function to keep listening for messages
+	 * indefinitely.
+	 *
+	 * As a reply, you will get a JSON array with messages, e.g.:
+	 * 	["msg1",{msg2:"x"}]
+	 * and so on. Empty reply [] is also normal and your code must be
+	 * able to handle that. Note that the reply specifically does not
+	 * include the time token present in the raw reply.
+	 *
+	 * @param string channel required channel name.
+	 * @param string timeout optional timeout in seconds.
+	 * @return string Stream-ish object with reply message or NULL on error. */
+	PubSubClient *subscribe(const char *channel, int timeout = 310);
+
+	/**
+	 * History
+	 *
+	 * Receive list of the last N messages on the given channel.
+	 *
+	 * @param string channel required channel name.
+	 * @param int limit optional number of messages to retrieve.
+	 * @param string timeout optional timeout in seconds.
+	 * @return string Stream-ish object with reply message or NULL on error. */
+	PubNub_BASE_CLIENT *history(const char *channel, int limit = 10, int timeout = 310);
+
+private:
+	enum PubNub_BH _request_bh(PubNub_BASE_CLIENT &client, unsigned long t_start, int timeout, char qparsep);
+
+	const char *publish_key, *subscribe_key;
+	const char *origin;
+	const char *uuid;
+	const char *auth;
+
+	PubNub_BASE_CLIENT publish_client, history_client;
+	PubSubClient subscribe_client;
+};
+
+extern class PubNub PubNub;
+
+#endif
Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/README.md
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/README.md	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/README.md	(revision 211)
@@ -0,0 +1,234 @@
+#PubNub Arduino Library
+
+This library allows your sketches to communicate with the PubNub cloud
+message passing system using an Ethernet shield. Your application can
+receive and send messages.
+
+##Copy-and-Paste-Ready Code!
+See how easy it is to [Publish](examples/PubNubPublisher) and [Subscribe](examples/PubNubSubscriber)!
+
+###Synopsis
+
+
+	void setup() {
+		Serial.begin(9600);
+		Ethernet.begin(mac);
+		PubNub.begin(pubkey, subkey);
+	}
+
+	void loop() {
+		/* Maintain DHCP lease. */
+		Ethernet.maintain();
+
+		/* Publish message. */
+		EthernetClient *pclient = PubNub.publish(pubchannel, "\"message\"");
+		if (pclient)
+			pclient->stop();
+
+		/* Wait for news. */
+		PubSubClient *sclient = PubNub.subscribe(subchannel);
+		if (!sclient) return; // error
+		char buffer[64]; size_t buflen = 0;
+		while (sclient->wait_for_data()) {
+			buffer[buflen++] = sclient->read();
+		}
+		buffer[buflen] = 0;
+		sclient->stop();
+
+		/* Print received message. You will want to look at it from
+		 * your code instead. */
+		Serial.println(buffer);
+		delay(10000);
+	}
+
+##Library Reference
+
+``bool PubNub.begin(char *publish_key, char *subscribe_key, char *origin)``
+
+To start using PubNub, use PubNub.begin().  This should be called after
+Ethernet.begin().
+
+Note that the string parameters are not copied; do not overwrite or free the
+memory where you stored the keys! (If you are passing string literals, don't
+worry about it.) Note that you should run only one of publish, subscribe and
+history requests each at once.
+
+The origin parameter is optional, defaulting to "pubsub.pubnub.com".
+
+``EthernetClient *publish(char *channel, char *message, int timeout)``
+
+Send a message (assumed to be well-formed JSON) to a given channel.
+
+Returns NULL in case of error, instead an instance of EthernetClient
+that you can use to read the reply to the publish command. If you
+don't care about it, call ``client->stop()`` right away.
+
+The timeout parameter is optional, defaulting to 305. See also
+a note about timeouts below.
+
+``PubSubClient *subscribe(char *channel)``
+
+Listen for a message on a given channel. The function will block
+and return when a message arrives. NULL is returned in case of error.
+The return type is PubSubClient, but from user perspective, you can
+work with it exactly like with EthernetClient; it also provides
+an extra convenience method ``wait_for_data()`` that allows you
+to wait for more data with sensible timeout.
+
+Typically, you will run this function from loop() function to keep
+listening for messages indefinitely.
+
+As a reply, you will get a JSON array with messages, e.g.:
+
+```
+	["msg1",{msg2:"x"}]
+```
+
+and so on. Empty reply [] is also normal and your code must be
+able to handle that. Note that the reply specifically does not
+include the time token present in the raw reply from PubNub;
+no need to worry about that.
+
+The timeout parameter is optional, defaulting to 305. See also
+a note about timeouts below.
+
+``EthernetClient *history(char *channel, int limit, int timeout)``
+
+Receive list of the last messages published on the given channel.
+The limit argument is optional and defaults to 10.
+
+The timeout parameter is optional, defaulting to 305. See also
+a note about timeouts below.
+
+##Installation
+
+Move the contents of the ``pubnub/arduino/`` directory to
+``~/sketchbook/libraries/PubNub/`` and restart your Arduino IDE.
+Try out the examples!
+
+##Supported Hardware
+
+The Arduino ecosystem features a multitude of platforms that
+have significant differences regarding their hardware capabilities;
+here, we list the status of PubNub support for various platforms:
+
+  * ATMega168-based generic boards (Duemilanove, Diecimila...):
+Not supported due to too small RAM and flash memory size.
+  * ATMega328-based generic boards (Duemilanove, Uno), Arduino
+Ethernet: Supported.  The space for user code may be somewhat limited.
+When using the aJson library, some memory saving tricks are required,
+see the top of the PubNubJson example.
+
+  * Arduino Mega (ATMega2560): Supported.
+  * Arduino Mega (ATMega1280): Untested, but should work just fine.
+
+Except Arduino Ethernet, network connectivity is provided by
+an external board ("shield"):
+
+  * Arduino Ethernet Shield: Supported. We tested only a shield that
+is based on the WizNet W5100 chip - but this should be the case for
+all but some ancient non-official ethernet shields.
+  * Arduino WiFi Shield: Supported, but new enough firmware and software
+is required.  The support must be enabled in the PubNub library.
+Please see the "WiFi Shield Support" section for details.
+
+##WiFi Shield Support
+
+The PubNub library supports the WiFi shield as well. In order
+to use the library with a WiFi-enabled Arduino, you will need
+to edit the file PubNub.h, commenting out the line
+
+	//#define PubNub_Ethernet
+
+and uncommenting
+
+	#define PubNub_WiFi
+
+It is essential to use a new enough Arduino version so that
+the WiFi library actually works properly. Most notably, version 1.0.5
+has been confirmed to work while Arduino 1.0.4 is broken!
+
+The WiFi shield carries its own microcontroller dedicated to the network
+communication and this microcontroller has upgradeable firmware.
+If some of the PubNub calls fail with your WiFi shield (e.g. you
+see "subscribe error" and similar messages in serial console),
+the firmware loaded on your WiFi shield may be buggy - e.g. a WiFi
+shield bought commercially in May 2013 came preloaded with firmware
+that had to be upgraded.  This is not so difficult to do, simply follow:
+
+	http://arduino.cc/en/Hacking/WiFiShieldFirmwareUpgrading
+
+	
+## WiFi Shield Support for "WiFi Shield 101"
+
+If you are using [Arduino WiFi Shield 101](https://www.arduino.cc/en/Main/ArduinoWiFiShield101), use WiFi101 library, instead of the WiFi library.
+
+Download a zip from Download a [zipped WiFi101 library](https://github.com/arduino-libraries/WiFi101/releases)
+and import the lib.
+
+To enable it in PubNub Library, edit `PubNub.h`:
+
+Comment out line 12:
+
+	//#define PubNub_Ethernet
+
+and uncomment line 13:
+
+	#define PubNub_WiFi
+
+then at line 21, where it says `#include <WiFi.h>`, replace it with:
+
+	#include <WiFi101.h>
+
+Now the `#define PubNub_WiFi` block should look like:
+
+```c
+#define PubNub_WiFi
+
+#if defined(PubNub_Ethernet)
+#include <Ethernet.h>
+#define PubNub_BASE_CLIENT EthernetClient
+
+#elif defined(PubNub_WiFi)
+#include <WiFi101.h>
+#define PubNub_BASE_CLIENT WiFiClient
+
+#else
+#error PubNub_BASE_CLIENT set to an invalid value!
+#endif
+```
+
+##Notes
+
+* There is no SSL support on Arduino, it is unfeasible with
+Arduino Uno or even Arduino Mega's computing power and memory limits.
+All the traffic goes on the wire unencrypted and unsigned.
+
+* We re-resolve the origin server IP address before each request.
+This means some slow-down for intensive communication, but we rather
+expect light traffic and very long-running sketches (days, months),
+where refreshing the IP address is quite desirable.
+
+* We let the users read replies at their leisure instead of
+returning an already preloaded string so that (a) they can do that
+in loop() code while taking care of other things as well (b) we don't
+waste precious RAM by pre-allocating buffers that are never needed.
+
+* If you are having problems connecting, maybe you have hit
+a bug in Debian's version of Arduino pertaining the DNS code. Try using
+an IP address as origin and/or upgrading your Arduino package.
+
+* The optional timeout parameter allows you to specify a timeout
+period after which the subscribe call shall be retried. Note
+that this timeout is applied only for reading response, not for
+connecting or sending data; use retransmission parameters of
+the Ethernet library to tune this. As a rule of thumb, timeout
+smaller than 30 seconds may still block longer with flaky
+network. Default server-side timeout of PubNub API is 300s.
+
+* The vendor firmware for the WiFi shield has dubious TCP implementation;
+for example, TCP ports of outgoing connections are always chosen from the
+same sequence, so if you reset your Arduino, some of the new connections
+may interfere with an outstanding TCP connection that has not been closed
+before the reset; i.e. you will typically see a single failed request
+somewhere down the road after a reset.
Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubDemo/PubNubDemo.ino
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubDemo/PubNubDemo.ino	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubDemo/PubNubDemo.ino	(revision 211)
@@ -0,0 +1,121 @@
+/*
+  PubNub sample client
+
+  This sample client will use just the minimal-footprint raw PubNub
+  interface where it is your responsibility to deal with the JSON encoding.
+
+  It will just send a hello world message and retrieve one back, reporting
+  its deeds on serial console.
+
+  Circuit:
+  * Ethernet shield attached to pins 10, 11, 12, 13
+  * (Optional.) LED on pin 8 for reception indication.
+  * (Optional.) LED on pin 9 for publish indication.
+
+  created 23 October 2012
+  by Petr Baudis
+
+  https://github.com/pubnub/pubnub-api/tree/master/arduino
+  This code is in the public domain.
+  */
+
+#include <SPI.h>
+#include <Ethernet.h>
+#include <PubNub.h>
+
+// Some Ethernet shields have a MAC address printed on a sticker on the shield;
+// fill in that address here, or choose your own at random:
+byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
+
+const int subLedPin = 8;
+const int pubLedPin = 9;
+
+char pubkey[] = "demo";
+char subkey[] = "demo";
+char channel[] = "hello_world";
+
+void setup()
+{
+	pinMode(subLedPin, OUTPUT);
+	pinMode(pubLedPin, OUTPUT);
+	digitalWrite(subLedPin, LOW);
+	digitalWrite(pubLedPin, LOW);
+
+	Serial.begin(9600);
+	Serial.println("Serial set up");
+
+	while (!Ethernet.begin(mac)) {
+		Serial.println("Ethernet setup error");
+		delay(1000);
+	}
+	Serial.println("Ethernet set up");
+
+	PubNub.begin(pubkey, subkey);
+	Serial.println("PubNub set up");
+}
+
+void flash(int ledPin)
+{
+	/* Flash LED three times. */
+	for (int i = 0; i < 3; i++) {
+		digitalWrite(ledPin, HIGH);
+		delay(100);
+		digitalWrite(ledPin, LOW);
+		delay(100);
+	}
+}
+
+void loop()
+{
+	Ethernet.maintain();
+
+	EthernetClient *client;
+
+	Serial.println("publishing a message");
+	client = PubNub.publish(channel, "\"\\\"Hello world!\\\" she said.\"");
+	if (!client) {
+		Serial.println("publishing error");
+		delay(1000);
+		return;
+	}
+	while (client->connected()) {
+		while (client->connected() && !client->available()) ; // wait
+		char c = client->read();
+		Serial.print(c);
+	}
+	client->stop();
+	Serial.println();
+	flash(pubLedPin);
+
+	Serial.println("waiting for a message (subscribe)");
+	PubSubClient *pclient = PubNub.subscribe(channel);
+	if (!pclient) {
+		Serial.println("subscription error");
+		delay(1000);
+		return;
+	}
+	while (pclient->wait_for_data()) {
+		char c = pclient->read();
+		Serial.print(c);
+	}
+	pclient->stop();
+	Serial.println();
+	flash(subLedPin);
+
+	Serial.println("retrieving message history");
+	client = PubNub.history(channel);
+	if (!client) {
+		Serial.println("history error");
+		delay(1000);
+		return;
+	}
+	while (client->connected()) {
+		while (client->connected() && !client->available()) ; // wait
+		char c = client->read();
+		Serial.print(c);
+	}
+	client->stop();
+	Serial.println();
+
+	delay(10000);
+}
Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubJson/PubNubJson.ino
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubJson/PubNubJson.ino	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubJson/PubNubJson.ino	(revision 211)
@@ -0,0 +1,209 @@
+/*
+  PubNub sample JSON-parsing client
+
+  This sample client will properly parse JSON-encoded PubNub subscription
+  replies using the aJson library. It will send a simple message, then
+  properly parsing and inspecting a subscription message received back.
+
+  This is achieved by integration with the aJson library. You will need
+  a version featuring Wiring Stream integration, that can be found
+  at http://github.com/interactive-matter/aJson as of 2012-11-12.
+
+  Circuit:
+  * Ethernet shield attached to pins 10, 11, 12, 13
+  * (Optional) Analog sensors attached to analog pin.
+  * (Optional) LEDs to be dimmed attached to PWM pins 8 and 9.
+
+
+  Note that due to use of the aJSON library, this sketch is more memory
+  sensitive than the others. In order to be able to use it on the boards
+  based on ATMega328, some special care is needed. Memory saving tips:
+
+  (i) Remove myI, dnsI from the sketch unless you need them.
+
+  (ii) In the aJSON library's utility/stringbuffer.c, change BUFFER_SIZE
+  from 256 to 128 or less. Note that this will limit the length of JSON
+  messages your script will be able to process.
+
+  (iii) In the file hardware/arduino/cores/arduino/HardwareSerial.cpp
+  which is part of your Arduino installation, decrease SERIAL_BUFFER_SIZE
+  from 64 to 16 or even smaller value (depends on your Serial usage).
+
+  Usually, (i) and (ii) is enough; try (iii) if you can't do one of these.
+  If you are still short on memory (will manifest as connection error,
+  there will be not enough memory left for EthernetClient), some very
+  aggressive code changes would be required, or re-consider whether you
+  cannot write ad-hoc JSON generating/parsing code covering just your
+  particular scenario instead of using the generic aJSON library.
+
+
+  created 26 October 2012
+  by Petr Baudis
+
+  https://github.com/pubnub/pubnub-api/tree/master/arduino
+  This code is in the public domain.
+  */
+
+#include <SPI.h>
+#include <Ethernet.h>
+#include <PubNub.h>
+#include <aJSON.h>
+
+// Some Ethernet shields have a MAC address printed on a sticker on the shield;
+// fill in that address here, or choose your own at random:
+const static byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
+
+// Memory saving tip: remove myI and dnsI from your sketch if you
+// are content to rely on DHCP autoconfiguration.
+IPAddress myI(10, 42, 0, 2);
+IPAddress dnsI(8, 8, 8, 8);
+
+const static char pubkey[] = "demo";
+const static char subkey[] = "demo";
+const static char channel[] = "hello_world";
+
+void setup()
+{
+	Serial.begin(9600);
+	Serial.println("Serial set up");
+
+	Ethernet.begin((byte*) mac, myI, dnsI);
+	Serial.println("Ethernet set up");
+
+	PubNub.begin(pubkey, subkey);
+	Serial.println("PubNub set up");
+}
+
+aJsonObject *createMessage()
+{
+	aJsonObject *msg = aJson.createObject();
+
+	aJsonObject *sender = aJson.createObject();
+	aJson.addStringToObject(sender, "name", "Arduino");
+	aJson.addNumberToObject(sender, "mac_last_byte", mac[5]);
+	aJson.addItemToObject(msg, "sender", sender);
+
+	int analogValues[6];
+	for (int i = 0; i < 6; i++) {
+		analogValues[i] = analogRead(i);
+	}
+	aJsonObject *analog = aJson.createIntArray(analogValues, 6);
+	aJson.addItemToObject(msg, "analog", analog);
+	return msg;
+}
+
+/* Process message like: { "pwm": { "8": 0, "9": 128 } } */
+void processPwmInfo(aJsonObject *item)
+{
+	aJsonObject *pwm = aJson.getObjectItem(item, "pwm");
+	if (!pwm) {
+		Serial.println("no pwm data");
+		return;
+	}
+
+	const static int pins[] = { 8, 9 };
+	const static int pins_n = 2;
+	for (int i = 0; i < pins_n; i++) {
+		char pinstr[3];
+		snprintf(pinstr, sizeof(pinstr), "%d", pins[i]);
+
+		aJsonObject *pwmval = aJson.getObjectItem(pwm, pinstr);
+		if (!pwmval) continue; /* Value not provided, ok. */
+		if (pwmval->type != aJson_Int) {
+			Serial.print(" invalid data type ");
+			Serial.print(pwmval->type, DEC);
+			Serial.print(" for pin ");
+			Serial.println(pins[i], DEC);
+			continue;
+		}
+
+		Serial.print(" setting pin ");
+		Serial.print(pins[i], DEC);
+		Serial.print(" to value ");
+		Serial.println(pwmval->valueint, DEC);
+		analogWrite(pins[i], pwmval->valueint);
+	}
+}
+
+void dumpMessage(Stream &s, aJsonObject *msg)
+{
+	int msg_count = aJson.getArraySize(msg);
+	for (int i = 0; i < msg_count; i++) {
+		aJsonObject *item, *sender, *analog, *value;
+		s.print("Msg #");
+		s.println(i, DEC);
+
+		item = aJson.getArrayItem(msg, i);
+		if (!item) { s.println("item not acquired"); delay(1000); return; }
+
+		processPwmInfo(item);
+
+		/* Below, we parse and dump messages from fellow Arduinos. */
+
+		sender = aJson.getObjectItem(item, "sender");
+		if (!sender) { s.println("sender not acquired"); delay(1000); return; }
+
+		s.print(" mac_last_byte: ");
+		value = aJson.getObjectItem(sender, "mac_last_byte");
+		if (!value) { s.println("mac_last_byte not acquired"); delay(1000); return; }
+		s.print(value->valueint, DEC);
+
+		s.print(" A2: ");
+		analog = aJson.getObjectItem(item, "analog");
+		if (!analog) { s.println("analog not acquired"); delay(1000); return; }
+		value = aJson.getArrayItem(analog, 2);
+		if (!value) { s.println("analog[2] not acquired"); delay(1000); return; }
+		s.print(value->valueint, DEC);
+
+		s.println();
+	}
+}
+
+void loop()
+{
+	Ethernet.maintain();
+
+	EthernetClient *client;
+
+	/* Publish */
+
+	Serial.print("publishing a message: ");
+	aJsonObject *msg = createMessage();
+	char *msgStr = aJson.print(msg);
+	aJson.deleteItem(msg);
+
+	// msgStr is returned in a buffer that can be potentially
+	// needlessly large; this call will "tighten" it
+	msgStr = (char *) realloc(msgStr, strlen(msgStr) + 1);
+
+	Serial.println(msgStr);
+	client = PubNub.publish(channel, msgStr);
+	free(msgStr);
+	if (!client) {
+		Serial.println("publishing error");
+		delay(1000);
+		return;
+	}
+	client->stop();
+
+	/* Subscribe and load reply */
+
+	Serial.println("waiting for a message (subscribe)");
+	client = PubNub.subscribe(channel);
+	if (!client) {
+		Serial.println("subscription error");
+		delay(1000);
+		return;
+	}
+
+	/* Parse */
+
+	aJsonClientStream stream(client);
+	msg = aJson.parse(&stream);
+	client->stop();
+	if (!msg) { Serial.println("parse error"); delay(1000); return; }
+	dumpMessage(Serial, msg);
+	aJson.deleteItem(msg);
+
+	delay(10000);
+}
Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubJsonWifi/PubNubJsonWifi.ino
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubJsonWifi/PubNubJsonWifi.ino	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubJsonWifi/PubNubJsonWifi.ino	(revision 211)
@@ -0,0 +1,201 @@
+/*
+  PubNub sample JSON-parsing client with WiFi support
+
+  This combines two sketches: the PubNubJson example of PubNub library
+  and the WifiWebClientRepeating example of the WiFi library.
+
+  This sample client will properly parse JSON-encoded PubNub subscription
+  replies using the aJson library. It will send a simple message, then
+  properly parsing and inspecting a subscription message received back.
+
+  This is achieved by integration with the aJson library. You will need
+  a version featuring Wiring Stream integration, that can be found
+  at http://github.com/pasky/aJson as of 2013-05-30.
+
+  Circuit:
+  * Wifi shield attached to pins 10, 11, 12, 13
+  * (Optional) Analog sensors attached to analog pin.
+  * (Optional) LEDs to be dimmed attached to PWM pins 8 and 9.
+
+
+  Please refer to the PubNubJson example description for some important
+  notes, especially regarding memory saving on Arduino Uno/Duemilanove.
+  You can also save some RAM by not using WiFi password protection.
+
+
+  created 30 May 2013
+  by Petr Baudis
+
+  https://github.com/pubnub/pubnub-api/tree/master/arduino
+  This code is in the public domain.
+  */
+
+#include <SPI.h>
+#include <WiFi.h>
+#include <PubNub.h>
+#include <aJSON.h>
+
+static char ssid[] = "yourNetwork";    // your network SSID (name)
+static char pass[] = "secretPassword"; // your network password
+static int keyIndex = 0;               // your network key Index number (needed only for WEP)
+
+const static char pubkey[] = "demo";
+const static char subkey[] = "demo";
+const static char channel[] = "hello_world";
+
+void setup()
+{
+	Serial.begin(9600);
+	Serial.println("Serial set up");
+
+	if (WiFi.status() == WL_NO_SHIELD) {
+	  Serial.println("WiFi shield not present");
+	  while(true); // stop
+	}
+
+	int status;
+	// attempt to connect to Wifi network:
+	do {
+		Serial.print("WiFi connecting to SSID: ");
+		Serial.println(ssid);
+
+		// Connect to the network. Uncomment whichever line is right for you:
+		//status = WiFi.begin(ssid); // open network
+		//status = WiFi.begin(ssid, keyIndex, key); // WEP network
+		status = WiFi.begin(ssid, pass); // WPA / WPA2 Personal network
+	} while (status != WL_CONNECTED);
+	Serial.println("WiFi set up");
+
+	PubNub.begin(pubkey, subkey);
+	Serial.println("PubNub set up");
+}
+
+aJsonObject *createMessage()
+{
+	aJsonObject *msg = aJson.createObject();
+
+	aJsonObject *sender = aJson.createObject();
+	aJson.addStringToObject(sender, "name", "Arduino");
+	aJson.addItemToObject(msg, "sender", sender);
+
+	int analogValues[6];
+	for (int i = 0; i < 6; i++) {
+		analogValues[i] = analogRead(i);
+	}
+	aJsonObject *analog = aJson.createIntArray(analogValues, 6);
+	aJson.addItemToObject(msg, "analog", analog);
+	return msg;
+}
+
+/* Process message like: { "pwm": { "8": 0, "9": 128 } } */
+void processPwmInfo(aJsonObject *item)
+{
+	aJsonObject *pwm = aJson.getObjectItem(item, "pwm");
+	if (!pwm) {
+		Serial.println("no pwm data");
+		return;
+	}
+
+	const static int pins[] = { 8, 9 };
+	const static int pins_n = 2;
+	for (int i = 0; i < pins_n; i++) {
+		char pinstr[3];
+		snprintf(pinstr, sizeof(pinstr), "%d", pins[i]);
+
+		aJsonObject *pwmval = aJson.getObjectItem(pwm, pinstr);
+		if (!pwmval) continue; /* Value not provided, ok. */
+		if (pwmval->type != aJson_Int) {
+			Serial.print(" invalid data type ");
+			Serial.print(pwmval->type, DEC);
+			Serial.print(" for pin ");
+			Serial.println(pins[i], DEC);
+			continue;
+		}
+
+		Serial.print(" setting pin ");
+		Serial.print(pins[i], DEC);
+		Serial.print(" to value ");
+		Serial.println(pwmval->valueint, DEC);
+		analogWrite(pins[i], pwmval->valueint);
+	}
+}
+
+void dumpMessage(Stream &s, aJsonObject *msg)
+{
+	int msg_count = aJson.getArraySize(msg);
+	for (int i = 0; i < msg_count; i++) {
+		aJsonObject *item, *sender, *analog, *value;
+		s.print("Msg #");
+		s.println(i, DEC);
+
+		item = aJson.getArrayItem(msg, i);
+		if (!item) { s.println("item not acquired"); delay(1000); return; }
+
+		processPwmInfo(item);
+
+		/* Below, we parse and dump messages from fellow Arduinos. */
+
+		sender = aJson.getObjectItem(item, "sender");
+		if (!sender) { s.println("sender not acquired"); delay(1000); return; }
+
+		s.print(" A2: ");
+		analog = aJson.getObjectItem(item, "analog");
+		if (!analog) { s.println("analog not acquired"); delay(1000); return; }
+		value = aJson.getArrayItem(analog, 2);
+		if (!value) { s.println("analog[2] not acquired"); delay(1000); return; }
+		s.print(value->valueint, DEC);
+
+		s.println();
+	}
+}
+
+void loop()
+{
+	// Intriguingly, the WiFi library doesn't seem to have a call
+	// equivalent to Ethernet.maintain();
+	//WiFi.maintain();
+
+	WiFiClient *client;
+
+	/* Publish */
+
+	Serial.print("publishing a message: ");
+	aJsonObject *msg = createMessage();
+	char *msgStr = aJson.print(msg);
+	aJson.deleteItem(msg);
+
+	// msgStr is returned in a buffer that can be potentially
+	// needlessly large; this call will "tighten" it
+	msgStr = (char *) realloc(msgStr, strlen(msgStr) + 1);
+
+	Serial.println(msgStr);
+	client = PubNub.publish(channel, msgStr);
+	free(msgStr);
+	if (!client) {
+		Serial.println("publishing error");
+		delay(1000);
+		return;
+	}
+	client->stop();
+
+	/* Subscribe and load reply */
+
+	Serial.println("waiting for a message (subscribe)");
+	client = PubNub.subscribe(channel);
+	if (!client) {
+		Serial.println("subscription error");
+		delay(1000);
+		return;
+	}
+
+	/* Parse */
+
+	aJsonClientStream stream(client);
+	msg = aJson.parse(&stream);
+	client->stop();
+	if (!msg) { Serial.println("parse error"); delay(1000); return; }
+	dumpMessage(Serial, msg);
+	aJson.deleteItem(msg);
+
+	delay(10000);
+}
Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubPublisher/PubNubPublisher.ino
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubPublisher/PubNubPublisher.ino	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubPublisher/PubNubPublisher.ino	(revision 211)
@@ -0,0 +1,86 @@
+/*
+  PubNub sample client
+
+  This sample client will publish raw (JSON pre-encoded) PubNub messages.
+
+  Circuit:
+  * Ethernet shield attached to pins 10, 11, 12, 13
+  * (Optional.) Analog sensors on pins A0 to A5.
+  * (Optional.) LED on pin 9 for success indication.
+
+  created 23 October 2012
+  by Petr Baudis
+
+  https://github.com/pubnub/pubnub-api/tree/master/arduino
+  This code is in the public domain.
+  */
+
+#include <SPI.h>
+#include <Ethernet.h>
+#include <PubNub.h>
+
+// Some Ethernet shields have a MAC address printed on a sticker on the shield;
+// fill in that address here, or choose your own at random:
+byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
+
+const int pubLedPin = 9;
+
+char pubkey[] = "demo";
+char subkey[] = "demo";
+char channel[] = "hello_world";
+
+void setup()
+{
+	pinMode(pubLedPin, OUTPUT);
+	digitalWrite(pubLedPin, LOW);
+
+	Serial.begin(9600);
+	Serial.println("Serial set up");
+
+	while (!Ethernet.begin(mac)) {
+		Serial.println("Ethernet setup error");
+		delay(1000);
+	}
+	Serial.println("Ethernet set up");
+
+	PubNub.begin(pubkey, subkey);
+	Serial.println("PubNub set up");
+}
+
+void flash(int ledPin)
+{
+	/* Flash LED three times. */
+	for (int i = 0; i < 3; i++) {
+		digitalWrite(ledPin, HIGH);
+		delay(100);
+		digitalWrite(ledPin, LOW);
+		delay(100);
+	}
+}
+
+void loop()
+{
+	Ethernet.maintain();
+
+	EthernetClient *client;
+
+	char msg[64] = "{\"analog\":[";
+	for (int i = 0; i < 6; i++) {
+		sprintf(msg + strlen(msg), "%d", analogRead(i));
+		if (i < 5)
+			strcat(msg, ",");
+	}
+	strcat(msg, "]}");
+
+	Serial.print("publishing message: ");
+	Serial.println(msg);
+	client = PubNub.publish(channel, msg);
+	if (!client) {
+		Serial.println("publishing error");
+	} else {
+		flash(pubLedPin);
+		client->stop();
+	}
+
+	delay(5000);
+}
Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubSubscriber/PubNubSubscriber.ino
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubSubscriber/PubNubSubscriber.ino	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubSubscriber/PubNubSubscriber.ino	(revision 211)
@@ -0,0 +1,96 @@
+/*
+  PubNub sample subscribe client
+
+  This sample client will subscribe to and handle raw PubNub messages
+  (not doing any JSON decoding).  It does so with a randomly generated
+  UUID.
+
+  Circuit:
+  * Ethernet shield attached to pins 10, 11, 12, 13
+  * (Optional.) LED on pin 8 for reception indication.
+  * Pin A4 unconnected (noise source for random number generator)
+
+  created 23 October 2012
+  by Petr Baudis
+
+  https://github.com/pubnub/pubnub-api/tree/master/arduino
+  This code is in the public domain.
+  */
+
+#include <SPI.h>
+#include <Ethernet.h>
+#include <PubNub.h>
+
+// Some Ethernet shields have a MAC address printed on a sticker on the shield;
+// fill in that address here, or choose your own at random:
+byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
+
+const int subLedPin = 8;
+
+char pubkey[] = "demo";
+char subkey[] = "demo";
+char channel[] = "hello_world";
+char uuid[] = "xxxxxxxx-xxxx-4444-9999-xxxxxxxxxxxx";
+
+void random_uuid() {
+	randomSeed(analogRead(4) + millis() * 1024);
+	snprintf(uuid, sizeof(uuid), "%04lx%04lx-%04lx-4444-9999-%04lx%04lx%04lx",
+		random(0x10000), random(0x10000), random(0x10000),
+		random(0x10000), random(0x10000), random(0x10000));
+}
+
+void setup()
+{
+	pinMode(subLedPin, OUTPUT);
+	digitalWrite(subLedPin, LOW);
+
+	Serial.begin(9600);
+	Serial.println("Serial set up");
+
+	while (!Ethernet.begin(mac)) {
+		Serial.println("Ethernet setup error");
+		delay(1000);
+	}
+	Serial.println("Ethernet set up");
+
+	PubNub.begin(pubkey, subkey);
+	random_uuid();
+	PubNub.set_uuid(uuid);
+	Serial.println("PubNub set up");
+}
+
+void flash(int ledPin)
+{
+	/* Flash LED three times. */
+	for (int i = 0; i < 3; i++) {
+		digitalWrite(ledPin, HIGH);
+		delay(100);
+		digitalWrite(ledPin, LOW);
+		delay(100);
+	}
+}
+
+void loop()
+{
+	Ethernet.maintain();
+
+	PubSubClient *client;
+
+	Serial.println("waiting for a message (subscribe)");
+	client = PubNub.subscribe(channel);
+	if (!client) {
+		Serial.println("subscription error");
+		delay(1000);
+		return;
+	}
+	Serial.print("Received: ");
+	while (client->wait_for_data()) {
+		char c = client->read();
+		Serial.print(c);
+	}
+	client->stop();
+	Serial.println();
+	flash(subLedPin);
+
+	delay(200);
+}
Index: rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubWifi101/PubNubWifi101.ino
===================================================================
--- rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubWifi101/PubNubWifi101.ino	(revision 211)
+++ rtos_arduino/trunk/arduino_lib/libraries/PubNub/examples/PubNubWifi101/PubNubWifi101.ino	(revision 211)
@@ -0,0 +1,65 @@
+
+/*
+  PubNub over WiFi Example using WiFi Shield 101
+  This sample client will publish raw (string) PubNub messages from boards like Arduino Uno and Zero with WiFi Shield 101
+  
+  See https://www.arduino.cc/en/Reference/WiFi101 for more info 
+  
+  created Dec 17, 2015
+  by Tomomi Imura
+*/
+  
+#include <SPI.h>
+#include <WiFi101.h>
+#include <PubNub.h>
+
+static char ssid[] = "your-wifi-network";   // your network SSID (name)
+static char pass[] = "password";            // your network password
+int status = WL_IDLE_STATUS;                // the Wifi radio's status
+
+const static char pubkey[] = "your-pub-key";
+const static char subkey[] = "your-sub-key";
+const static char channel[] = "hello_world";
+
+
+void setup() {
+  // put your setup code here, to run once:
+  Serial.begin(9600);
+  Serial.println("Serial set up");
+
+  // attempt to connect using WPA2 encryption:
+  Serial.println("Attempting to connect to WPA network...");
+  status = WiFi.begin(ssid, pass);
+
+  // if you're not connected, stop here:
+  if ( status != WL_CONNECTED) {
+    Serial.println("Couldn't get a wifi connection");
+    while (true);
+  } else {
+    Serial.print("WiFi connecting to SSID: ");
+    Serial.println(ssid);
+
+    PubNub.begin(pubkey, subkey);
+    Serial.println("PubNub set up");
+  }
+}
+
+void loop() {
+
+  /* Publish */
+  
+  WiFiClient *client;
+   
+  char msg[] = "\"Yo!\"";
+
+  client = PubNub.publish(channel, msg);
+
+  if (!client) {
+    Serial.println("publishing error");
+    delay(1000);
+    return;
+  }
+  client->stop();
+}
+
+
