diff --git a/Adafruit_MQTT.cpp b/Adafruit_MQTT.cpp new file mode 100644 index 0000000..f5fa185 --- /dev/null +++ b/Adafruit_MQTT.cpp @@ -0,0 +1,86 @@ +#include "Adafruit_MQTT.h" + + +Adafruit_MQTT::Adafruit_MQTT(char *server, uint16_t port, char *user, char *key) { + strncpy(servername, server, SERVERNAME_SIZE); + servername[SERVERNAME_SIZE-1] = 0; + portnum = port; + serverip = 0; + strncpy(username, user, USERNAME_SIZE); + username[USERNAME_SIZE-1] = 0; + strncpy(userkey, key, KEY_SIZE); + userkey[KEY_SIZE-1] = 0; + + errno = 0; +} + +// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718028 +uint8_t Adafruit_MQTT::connectPacket(uint8_t *packet) { + uint8_t *p = packet; + + // fixed header, connection messsage no flags + p[0] = (MQTT_CTRL_CONNECT << 4) | 0x0; + p+=2; + // fill in packet[1] last + + p[0] = 0; + p[1] = 6; // (strlen(MQIdsp) + p+=2; + memcpy(p,"MQIdsp", 6); + p+=6; + + p[0] = MQTT_PROTOCOL_LEVEL; + p++; + + p[0] = MQTT_CONN_CLEANSESSION; + if (username[0] != 0) + p[0] |= MQTT_CONN_USERNAMEFLAG; + if (userkey[0] != 0) + p[0] |= MQTT_CONN_PASSWORDFLAG; + p++; + // TODO: add WILL support? + + p[0] = MQTT_CONN_KEEPALIVE >> 8; + p++; + p[0] = MQTT_CONN_KEEPALIVE & 0xFF; + p++; + + if (username[0] != 0) { + uint16_t len = strlen(username); + p[0] = len >> 8; p++; + p[0] = len & 0xFF; p++; + memcpy(p, username, len); + p+=len; + } + if (userkey[0] != 0) { + uint16_t len = strlen(userkey); + p[0] = len >> 8; p++; + p[0] = len & 0xFF; p++; + memcpy(p, userkey, len); + p+=len; + } + + uint8_t totallen = p - packet; + + // add two empty bytes at the end (?) + p[0] = 0; + p[1] = 0; + p+=2; + + + packet[1] = totallen; + + + return totallen+2; +} + + +Adafruit_MQTT_Publish::Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver, char *feed) { + mqtt = mqttserver; + strncpy(feedname, feed, FEEDNAME_SIZE); + feedname[FEEDNAME_SIZE-1] = 0; + + errno = 0; +} + + diff --git a/Adafruit_MQTT.h b/Adafruit_MQTT.h new file mode 100644 index 0000000..af47e38 --- /dev/null +++ b/Adafruit_MQTT.h @@ -0,0 +1,69 @@ +#ifndef _ADAFRUIT_MQTT_H_ +#define _ADAFRUIT_MQTT_H_ + +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#define MQTT_PROTOCOL_LEVEL 3 + +#define MQTT_CTRL_CONNECT 0x1 +#define MQTT_CTRL_CONNECTACK 0x2 + +#define SERVERNAME_SIZE 25 +#define USERNAME_SIZE 25 +#define KEY_SIZE 41 +#define FEEDNAME_SIZE 25 + +#define CONNECT_TIMEOUT_MS 3000 + +#define MQTT_CONN_USERNAMEFLAG 0x80 +#define MQTT_CONN_PASSWORDFLAG 0x40 +#define MQTT_CONN_WILLRETAIN 0x20 +#define MQTT_CONN_WILLQOS 0x08 +#define MQTT_CONN_WILLFLAG 0x04 +#define MQTT_CONN_CLEANSESSION 0x02 +#define MQTT_CONN_KEEPALIVE 15 // in seconds + +#define MAXBUFFERSIZE 200 + +class Adafruit_MQTT { + public: + Adafruit_MQTT(char *server, uint16_t port, char *user, char *key); + uint8_t connectPacket(uint8_t *packet); + protected: + int8_t errno; + char servername[SERVERNAME_SIZE]; + uint32_t serverip; + int16_t portnum; + char username[USERNAME_SIZE]; + char userkey[KEY_SIZE]; + + uint8_t buffer[MAXBUFFERSIZE]; +}; + +class Adafruit_MQTT_Publish { + public: + Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver, char *feed); + + bool publish(char *s); + bool publish(double f); + bool publish(int32_t i); + +private: + Adafruit_MQTT *mqtt; + char feedname[FEEDNAME_SIZE]; + int8_t errno; +}; + +class Adafruit_MQTT_Subscibe { + public: + Adafruit_MQTT_Subscibe(Adafruit_MQTT *mqttserver, char *feedname); + bool setCallback(void (*callback)(char *)); + +}; + + +#endif /* header guard */ diff --git a/Adafruit_MQTT_CC3000.cpp b/Adafruit_MQTT_CC3000.cpp new file mode 100644 index 0000000..5d25b2c --- /dev/null +++ b/Adafruit_MQTT_CC3000.cpp @@ -0,0 +1,103 @@ +#include "Adafruit_MQTT.h" +#include "Adafruit_MQTT_CC3000.h" +#include + +Adafruit_MQTT_CC3000::Adafruit_MQTT_CC3000(Adafruit_CC3000 *cc3k, char *server, uint16_t port, char *user, char *key) : Adafruit_MQTT(server, port, user, key), cc3000(cc3k) +{ + // nothin doin +} + +int8_t Adafruit_MQTT_CC3000::connect(void) { + uint32_t ip = 0; + + Watchdog.reset(); + + // look up IP address + if (serverip == 0) { + // Try looking up the website's IP address using CC3K's built in getHostByName + Serial.print(servername); Serial.print(F(" -> ")); + uint8_t dnsretries = 5; + + Watchdog.reset(); + while (ip == 0) { + if (! cc3000->getHostByName(servername, &ip)) { + Serial.println(F("Couldn't resolve!")); + dnsretries--; + Watchdog.reset(); + } + //Serial.println("OK"); Serial.println(ip, HEX); + if (!dnsretries) return -1; + delay(500); + } + + serverip = ip; + cc3000->printIPdotsRev(serverip); + Serial.println(); + } + + Watchdog.reset(); + + // connect to server + Serial.println("Connecting to TCP"); + mqttclient = cc3000->connectTCP(serverip, portnum); + uint8_t len = connectPacket(buffer); + Serial.println("MQTT connection packet:"); + for (uint8_t i=0; i + +class Adafruit_MQTT_CC3000 : public Adafruit_MQTT { + public: + Adafruit_MQTT_CC3000(Adafruit_CC3000 *cc3k, char *server, uint16_t port, char *user, char *key); + int8_t connect(void); + uint16_t readPacket(uint8_t *buffer, uint8_t maxlen, uint16_t timeout); + + private: + Adafruit_CC3000 *cc3000; + Adafruit_CC3000_Client mqttclient; +}; + + +#endif