Connecting a Multi-Tech Systems Dragonfly™ to Twilio's Sync for IoT Quickstart. Blink a dev board LED.

Dependencies:   MQTT MbedJSONValue mbed mtsas

Fork of DragonflyMQTT by miao zhicheng

Code to connect a Multi-Tech® MultiConnect® Dragonfly™ to Twilio's Sync for IoT: https://www.twilio.com/docs/api/devices

Uses MQTT over TLS and subscribes to a topic where you can control an LED. See also our Quickstart using this code, here: https://www.twilio.com/docs/quickstart/sync-iot/mqtt-multi-tech-multiconnect-dragonfly-sync-iot

Revision:
0:b32fa0c757d7
Child:
1:5a896191c3c4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TlsMQTTClient.cpp	Tue May 09 13:16:48 2017 +0000
@@ -0,0 +1,151 @@
+#include <cyassl/ctaocrypt/types.h>
+#include "TlsMQTTClient.hpp"
+
+TlsMQTTClient::TlsMQTTClient() :
+    tcp(NULL), ctx(NULL), ssl(NULL),
+    mqttClient(new MQTTClient(*this)) {
+}
+
+int TlsMQTTClient::connect(const char* host, const int port,
+        const char* certificates,
+        MQTTPacket_connectData& options) {
+    cleanupTransport();
+
+    // create TCP transport
+    tcp = new TCPSocketConnection();
+    if (tcp->connect(host, port)) {
+        logError("tcp connection failed");
+        goto fail;
+    }
+
+    // setup SSL context
+    ctx = CyaSSL_CTX_new((CYASSL_METHOD *)CyaSSLv23_client_method());
+    { //Localize pMethod array for less overall memory time-use
+        SSLMethod peerMethod = certificates != NULL ? (SSLMethod)(VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : VERIFY_NONE;
+        std::string pMethod;
+        if(peerMethod == VERIFY_NONE) {
+            pMethod = "not verify peer";
+        } else if (peerMethod == VERIFY_PEER) {
+            pMethod = "verify peer if certificates available";
+            //Load the CA certificate(s) (If using multiple, concatenate them in the buffer being passed)
+            if (SSL_SUCCESS != CyaSSL_CTX_load_verify_buffer(ctx, (const unsigned char*)certificates, strlen(certificates), SSL_FILETYPE_PEM)) {
+                logError("unable to load root certificates");
+                goto fail;
+            }
+        }
+        logDebug("SSL connection set to %s", pMethod.c_str());
+        CyaSSL_CTX_set_verify(ctx, peerMethod, 0); //SSL_VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_NONE, SSL_VERIFY_PEER
+    }
+
+    // setup SSL operations
+    ssl = CyaSSL_new(ctx);
+
+    CyaSSL_SetIOReadCtx(ssl, this);
+    CyaSSL_SetIORecv(ctx, ioRecv);
+    CyaSSL_SetIOWriteCtx(ssl, this);
+    CyaSSL_SetIOSend(ctx, ioSend);
+
+    // SSL connect
+    {
+        int ret = CyaSSL_connect(ssl);
+    
+        if (ret != SSL_SUCCESS) {
+            logError("SSL_connect failed");
+            int err = CyaSSL_get_error(ssl, ret);
+            char data[CYASSL_MAX_ERROR_SZ];
+            char data_new[CYASSL_MAX_ERROR_SZ];
+            strcpy(data_new, CyaSSL_ERR_error_string(err, data));
+            if(!strcmp(data,data_new)) {
+                logError("Error code [%d] is [%s]\r\n", err, data);
+            } else {
+                logError("Failed to get error code [%d], Reason: [%s]\r\n", err, data_new);
+            }
+            goto fail;
+        }
+    }
+
+    return mqttClient->connect(options);
+
+fail:
+    cleanupTransport() ;
+    return MQTT::FAILURE;
+}
+
+int TlsMQTTClient::publish(const char* topicName, MQTT::Message& message) {
+    return mqttClient->publish(topicName, message);
+}
+
+int TlsMQTTClient::publish(const char* topicName, void* payload, size_t payloadlen, enum MQTT::QoS qos, bool retained) {
+    return mqttClient->publish(topicName, payload, payloadlen, qos, retained);
+}
+
+int TlsMQTTClient::publish(const char* topicName, void* payload, size_t payloadlen, unsigned short& id, enum MQTT::QoS qos, bool retained) {
+    return mqttClient->publish(topicName, payload, payloadlen, id, qos, retained);
+}
+
+int TlsMQTTClient::subscribe(const char* topicFilter, enum MQTT::QoS qos, MessageHandler mh) {
+    return mqttClient->subscribe(topicFilter, qos, mh);
+}
+
+int TlsMQTTClient::unsubscribe(const char* topicFilter) {
+    return mqttClient->unsubscribe(topicFilter);
+}
+
+int TlsMQTTClient::disconnect() {
+    int r = mqttClient->disconnect();
+    cleanupTransport();
+    return r;
+}
+
+int TlsMQTTClient::yield(unsigned long timeout_ms) {
+    return mqttClient->yield(timeout_ms);
+}
+
+bool TlsMQTTClient::isConnected() {
+    return mqttClient->isConnected();
+}
+
+void TlsMQTTClient::cleanupTransport() {
+    if (ssl) {
+        logTrace("freeing ssl");
+        CyaSSL_free(ssl) ;
+        ssl = NULL ;
+    }
+    if (ctx) {
+        logTrace("freeing ssl ctx");
+        CyaSSL_CTX_free(ctx) ;
+        ctx = NULL ;
+    }
+    if (tcp) {
+        if (tcp->is_connected()) {
+            logTrace("disconnect tcp");
+            tcp->close();
+        }
+        logTrace("freeing tcp");
+        delete tcp;
+        tcp = NULL;
+    }
+}
+
+TlsMQTTClient::~TlsMQTTClient() {
+    cleanupTransport();
+    delete mqttClient;
+}
+
+int TlsMQTTClient::read(unsigned char* data, int max, int timeout) {
+    return CyaSSL_read(ssl, data, max);
+}
+
+int TlsMQTTClient::write(const unsigned char* data, int length, int timeout) {
+    return CyaSSL_write(ssl, data, length);
+}
+
+int TlsMQTTClient::ioRecv(CYASSL* ssl, char *buf, int sz, void *ctx) {
+    TlsMQTTClient* thiz = (TlsMQTTClient*) ctx;
+    return thiz->tcp->receive(buf, sz);
+}
+
+int TlsMQTTClient::ioSend(CYASSL* ssl, char *buf, int sz, void *ctx) {
+    TlsMQTTClient* thiz = (TlsMQTTClient*) ctx;
+    return thiz->tcp->send(buf, sz);
+}