Ambient Library

Fork of AmbientLib by Takehiko Shimojima

Ambient library. It provides "set" function to set data to a packet and "send" function to send the packet to the Ambient server. It also provides "bulk_send" function to send multiple data. (Japanese: IoT用のクラウドサービス「Ambient」のデーター送信ライブラリーです。Ambientはマイコンから送られたセンサーデーターを受信し、蓄積し、可視化(グラフ化)します。http://ambidata.io)

Files at this revision

API Documentation at this revision

Comitter:
TakehikoShimojima
Date:
Sat May 07 01:11:27 2016 +0000
Commit message:
initial

Changed in this revision

Ambient.cpp Show annotated file Show diff for this revision Revisions of this file
Ambient.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Ambient.cpp	Sat May 07 01:11:27 2016 +0000
@@ -0,0 +1,147 @@
+#include "Ambient.h"
+
+#define _DEBUG 0
+
+#if _DEBUG
+#define DBG(...) { printf(__VA_ARGS__); }
+#define ERR(...) { printf(__VA_ARGS__); }
+#else
+#define DBG(...)
+#define ERR(...)
+#endif /* _DBG */
+
+const char* AMBIENT_HOST = "54.65.206.59";
+const int AMBIENT_PORT = 80;
+const char* AMBIENT_HOST_DEV = "192.168.0.8";
+const int AMBIENT_PORT_DEV = 4567;
+
+const char * ambient_keys[] = {"\"d1\":\"", "\"d2\":\"", "\"d3\":\"", "\"d4\":\"", "\"d5\":\"", "\"d6\":\"", "\"d7\":\"", "\"d8\":\"", "\"lat\":\"", "\"lng\":\"", "\"created\":\""};
+
+AMBIENT::AMBIENT() {
+}
+
+bool
+AMBIENT::init(unsigned int channelId, const char * writeKey, TCPSocketConnection * s, int dev) {
+    this->channelId = channelId;
+
+    if (sizeof(writeKey) > AMBIENT_WRITEKEY_SIZE) {
+        ERR("writeKey length > AMBIENT_WRITEKEY_SIZE");
+        return false;
+    }
+    strcpy(this->writeKey, writeKey);
+
+    if(NULL == s) {
+        ERR("Socket Pointer is NULL, open a socket.");
+        return false;
+    }
+    this->s = s;
+    this->dev = dev;
+    if (dev) {
+        strcpy(this->host, AMBIENT_HOST_DEV);
+        this->port = AMBIENT_PORT_DEV;
+    } else {
+        strcpy(this->host, AMBIENT_HOST);
+        this->port = AMBIENT_PORT;
+    }
+    for (int i = 0; i < AMBIENT_NUM_PARAMS; i++) {
+        this->data[i].set = false;
+    }
+    return true;
+}
+
+bool
+AMBIENT::set(int field, char * data) {
+    --field;
+    if (field < 0 || field >= AMBIENT_NUM_PARAMS) {
+        return false;
+    }
+    if (strlen(data) > AMBIENT_DATA_SIZE) {
+        return false;
+    }
+    this->data[field].set = true;
+    strcpy(this->data[field].item, data);
+
+    return true;
+}
+
+bool
+AMBIENT::clear(int field) {
+    --field;
+    if (field < 0 || field >= AMBIENT_NUM_PARAMS) {
+        return false;
+    }
+    this->data[field].set = false;
+
+    return true;
+}
+
+bool
+AMBIENT::send() {
+
+    int retry;
+    for (retry = 0; retry < AMBIENT_MAX_RETRY; retry++) {
+        int ret;
+        ret = this->s->connect(this->host, this->port);
+        if (ret == 0) {
+            break ;
+        }
+    }
+    if(retry == AMBIENT_MAX_RETRY) {
+        ERR("Could not connect socket to host\r\n");
+        return false;
+    }
+
+    char str[360] = {0};
+    char header[54] = {0};
+    char host[32] = {0};
+    char contentLen[28] = {0};
+    const char *contentType = "Content-Type: application/json\r\n\r\n";
+    char body[192] = {0};
+
+    strcat(body, "{\"writeKey\":\"");
+    strcat(body, this->writeKey);
+    strcat(body, "\",");
+
+    for (int i = 0; i < AMBIENT_NUM_PARAMS; i++) {
+        if (this->data[i].set) {
+            strcat(body, ambient_keys[i]);
+            strcat(body, this->data[i].item);
+            strcat(body, "\",");
+        }
+    }
+    body[strlen(body) - 1] = '\0';
+
+    strcat(body, "}\r\n");
+
+    sprintf(header, "POST /api/v2/channels/%d/data HTTP/1.1\r\n", this->channelId);
+    if (this->port == 80) {
+        sprintf(host, "Host: %s\r\n", this->host);
+    } else {
+        sprintf(host, "Host: %s:%d\r\n", this->host, this->port);
+    }
+    sprintf(contentLen, "Content-Length: %d\r\n", strlen(body));
+    sprintf(str, "%s%s%s%s%s", header, host, contentLen, contentType, body);
+
+    DBG("sending: %d bytes\r\n%s", strlen(str), str);
+
+    int ret;
+    ret = this->s->send_all(str, strlen(str));
+    wait_ms(30);
+    DBG("%d bytes sent\r\n", ret);
+    if (ret < 0) {
+        ERR("send failed\r\n");
+        return false;
+    }
+
+    ret = this->s->receive(str,sizeof(str));
+    str[ret]=0;
+    DBG("Received String : (%d)\r\n%s\r\n",ret, str);
+
+    this->s->close();
+
+    for (int i = 0; i < AMBIENT_NUM_PARAMS; i++) {
+        this->data[i].set = false;
+    }
+
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Ambient.h	Sat May 07 01:11:27 2016 +0000
@@ -0,0 +1,112 @@
+#ifndef AMBIENT_H
+#define AMBIENT_H
+
+#include "mbed.h"
+#include "TCPSocketConnection.h"
+
+#define AMBIENT_WRITEKEY_SIZE 18
+#define AMBIENT_MAX_RETRY 5
+#define AMBIENT_DATA_SIZE 24
+#define AMBIENT_NUM_PARAMS 11
+
+/** AMBIENT class
+ * to send data to Ambient service.
+ *
+ * Exsample:
+ * @code
+ * #include "mbed.h"
+ * #include "EthernetInterface.h"
+ * #include "Ambient.h"
+ * #include "HDC1000.h"
+ * 
+ * unsigned int channelId = 100;
+ * const char* writeKey = "ライトキー";
+ * AMBIENT ambient;
+ * 
+ * HDC1000      hdc1000(p9,p10);
+ * 
+ * int main() {
+ *     printf("start\r\n");
+ * 
+ *     EthernetInterface eth;
+ *     eth.init(); //Use DHCP
+ *     eth.connect();
+ * 
+ *     TCPSocketConnection socket;
+ *     ambient.init(channelId, writeKey, &socket);
+ * 
+ *     printf("Ambient send to ch: %d\r\n", channelId);
+ * 
+ *     while (true) {
+ *         float temp, humid;
+ *         char tempbuf[12], humidbuf[12];
+ * 
+ *         hdc1000.get();
+ *         temp = hdc1000.temperature();
+ *         humid = hdc1000.humidity();
+ * 
+ *         sprintf(tempbuf, "%2.1f", temp);
+ *         ambient.set(1, tempbuf);
+ *         sprintf(humidbuf, "%2.0f", humid);
+ *         ambient.set(2, humidbuf);
+ *         printf("Temp: %s C, Humid: %s %%\r\n", tempbuf, humidbuf);
+ *         
+ *         ambient.send();
+ *         
+ *         wait(30.0);
+ *     }
+ * }
+ * @endcode
+ */
+class AMBIENT
+{
+public:
+    /** Create AMBIENT instance
+     */
+    AMBIENT(void);
+
+    /** Initialize the instance
+     * @param channelId Initialize the Ambient instance with channelId.
+     * @param writeKey and writeKey
+     * @param s and pointer to socket
+     * @returns
+     *    true on success,
+     *    false on error
+     */
+    bool init(unsigned int channelId, const char * writeKey, TCPSocketConnection * s, int dev = 0);
+    /** Set data on field-th field of payload.
+     * @param field index of payload (1 to 8)
+     * @param data data
+     * @returns
+     *    true on success,
+     *    false on error
+     */
+    bool set(int field, char * data);
+    /** Clear data on field-th field of payload.
+     * @param field index of payload (1 to 8)
+     * @returns
+     *    true on success,
+     *    false on error
+     */
+    bool clear(int field);
+
+    /** Send data to Ambient
+     */
+    bool send(void);
+
+private:
+
+    TCPSocketConnection * s;
+    unsigned int channelId;
+    char writeKey[AMBIENT_WRITEKEY_SIZE];
+    int dev;
+    char host[18];
+    int port;
+
+    struct {
+        int set;
+        char item[AMBIENT_DATA_SIZE];
+    } data[AMBIENT_NUM_PARAMS];
+};
+
+#endif // AMBIENT_H
\ No newline at end of file