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

Committer:
miaotwilio
Date:
Fri Sep 08 07:35:33 2017 +0000
Revision:
6:4a25f3b9caef
Parent:
5:ded8fe5991a2
Child:
8:f8a346582627
bug fixes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
miaotwilio 0:b32fa0c757d7 1 #include "MTSCellularManager.hpp"
miaotwilio 5:ded8fe5991a2 2 #include "TripDataReader.hpp"
miaotwilio 0:b32fa0c757d7 3 #include "TlsMQTTClient.hpp"
miaotwilio 0:b32fa0c757d7 4 #include "Certificates.h"
miaotwilio 2:d4dcf1ebaa99 5 #include "config.hpp"
miaotwilio 0:b32fa0c757d7 6 #include <mbed.h>
miaotwilio 0:b32fa0c757d7 7 #include <mtsas.h>
miaotwilio 0:b32fa0c757d7 8 #include <ssl.h>
miaotwilio 0:b32fa0c757d7 9
miaotwilio 0:b32fa0c757d7 10 // This line controls the regulator's battery charger.
miaotwilio 0:b32fa0c757d7 11 // BC_NCE = 0 enables the battery charger
miaotwilio 0:b32fa0c757d7 12 // BC_NCE = 1 disables the battery charger
miaotwilio 0:b32fa0c757d7 13 DigitalOut bc_nce(PB_2);
miaotwilio 5:ded8fe5991a2 14
miaotwilio 1:5a896191c3c4 15 DigitalOut ledGPS(D8);
miaotwilio 1:5a896191c3c4 16
miaotwilio 6:4a25f3b9caef 17 static bool enableODB = false;
miaotwilio 6:4a25f3b9caef 18 static Ticker vehicleDataSamplingTicker;
miaotwilio 6:4a25f3b9caef 19 static const int VEHICLE_DATA_SAMPLING_PERIOD_MS = 50;
miaotwilio 6:4a25f3b9caef 20 static const int VEHICLE_DATA_REPORTING_PERIOD_MS = 3000;
miaotwilio 5:ded8fe5991a2 21 MTSSerial obd(D1, D0);
miaotwilio 5:ded8fe5991a2 22 DigitalOut ledOBD(D6);
miaotwilio 5:ded8fe5991a2 23 static TripDataReader* pTripDataReader = NULL;
miaotwilio 5:ded8fe5991a2 24 static void vehicleDataSamplingCallback();
miaotwilio 5:ded8fe5991a2 25
miaotwilio 6:4a25f3b9caef 26 DigitalOut vehicleDataLED(D5);
miaotwilio 5:ded8fe5991a2 27 static void sendVehicleData(const MTSCellularManager::GPSStatus& gpsStatus,
miaotwilio 5:ded8fe5991a2 28 const TripDataReader::TripData& tripData);
miaotwilio 5:ded8fe5991a2 29
miaotwilio 6:4a25f3b9caef 30 static bool exitCmd = false;
miaotwilio 0:b32fa0c757d7 31
miaotwilio 0:b32fa0c757d7 32 int main() {
miaotwilio 0:b32fa0c757d7 33 // Disable the battery charger unless a battery is attached.
miaotwilio 0:b32fa0c757d7 34 bc_nce = 1;
miaotwilio 1:5a896191c3c4 35
miaotwilio 6:4a25f3b9caef 36 vehicleDataLED = 1;
miaotwilio 1:5a896191c3c4 37 ledGPS = 1;
miaotwilio 6:4a25f3b9caef 38
miaotwilio 0:b32fa0c757d7 39 // Change the baud rate of the debug port from the default 9600 to 115200.
miaotwilio 0:b32fa0c757d7 40 Serial debug(USBTX, USBRX);
miaotwilio 0:b32fa0c757d7 41 debug.baud(115200);
miaotwilio 0:b32fa0c757d7 42
miaotwilio 0:b32fa0c757d7 43 //Sets the log level to INFO, higher log levels produce more log output.
miaotwilio 0:b32fa0c757d7 44 //Possible levels: NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE
miaotwilio 0:b32fa0c757d7 45 mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
miaotwilio 0:b32fa0c757d7 46
miaotwilio 1:5a896191c3c4 47 logInfo("Program started");
miaotwilio 6:4a25f3b9caef 48
miaotwilio 6:4a25f3b9caef 49 logInfo("Vehicle ID: %s, TYPE: %s", VEHICLE_ID, VEHICLE_TYPE);
miaotwilio 6:4a25f3b9caef 50 if (0 == strcmp(VEHICLE_TYPE, "CAR")) {
miaotwilio 6:4a25f3b9caef 51 logInfo("Enable OBD for it is a car");
miaotwilio 6:4a25f3b9caef 52 enableODB = true;
miaotwilio 6:4a25f3b9caef 53 }
miaotwilio 6:4a25f3b9caef 54
miaotwilio 1:5a896191c3c4 55 logInfo("Initializing cellular");
miaotwilio 0:b32fa0c757d7 56 MTSCellularManager cellularManager("wireless.twilio.com");
miaotwilio 0:b32fa0c757d7 57 if (! cellularManager.init()) {
miaotwilio 0:b32fa0c757d7 58 while (true) {
miaotwilio 0:b32fa0c757d7 59 logError("failed to initialize cellular radio");
miaotwilio 0:b32fa0c757d7 60 wait(1);
miaotwilio 0:b32fa0c757d7 61 }
miaotwilio 0:b32fa0c757d7 62 }
miaotwilio 0:b32fa0c757d7 63
miaotwilio 1:5a896191c3c4 64 {
miaotwilio 1:5a896191c3c4 65 logInfo("Initializing GPS");
miaotwilio 1:5a896191c3c4 66 cellularManager.enableGps();
miaotwilio 1:5a896191c3c4 67 logInfo("GPS Initialized");
miaotwilio 1:5a896191c3c4 68 }
miaotwilio 1:5a896191c3c4 69
miaotwilio 5:ded8fe5991a2 70 TripDataReader tripDataReader(obd, ledOBD);
miaotwilio 5:ded8fe5991a2 71 pTripDataReader = &tripDataReader;
miaotwilio 6:4a25f3b9caef 72 while (enableODB) {
miaotwilio 5:ded8fe5991a2 73 logInfo("Initializing OBD");
miaotwilio 5:ded8fe5991a2 74 int r = tripDataReader.init();
miaotwilio 5:ded8fe5991a2 75 logInfo("OBD Initialization result: %d", r);
miaotwilio 5:ded8fe5991a2 76 if (0 == r) {
miaotwilio 5:ded8fe5991a2 77 logInfo("Initializing OBD sampling ticker");
miaotwilio 5:ded8fe5991a2 78 vehicleDataSamplingTicker.attach(
miaotwilio 5:ded8fe5991a2 79 &vehicleDataSamplingCallback,
miaotwilio 5:ded8fe5991a2 80 VEHICLE_DATA_SAMPLING_PERIOD_MS / 1000.);
miaotwilio 5:ded8fe5991a2 81 logInfo("OBD sampling ticker initialized");
miaotwilio 5:ded8fe5991a2 82 break;
miaotwilio 5:ded8fe5991a2 83 }
miaotwilio 5:ded8fe5991a2 84 wait_ms(100);
miaotwilio 5:ded8fe5991a2 85 }
miaotwilio 5:ded8fe5991a2 86
miaotwilio 1:5a896191c3c4 87 logInfo("Initializing CyaSSL");
miaotwilio 0:b32fa0c757d7 88 CyaSSL_Init();
miaotwilio 0:b32fa0c757d7 89
miaotwilio 1:5a896191c3c4 90 while (!exitCmd) {
miaotwilio 5:ded8fe5991a2 91 wait_ms(VEHICLE_DATA_REPORTING_PERIOD_MS);
miaotwilio 6:4a25f3b9caef 92 TripDataReader::TripData tripData;
miaotwilio 6:4a25f3b9caef 93 if (enableODB) {
miaotwilio 6:4a25f3b9caef 94 tripData = tripDataReader.getTripData();
miaotwilio 6:4a25f3b9caef 95 tripDataReader.resetAverageWindow();
miaotwilio 6:4a25f3b9caef 96 }
miaotwilio 1:5a896191c3c4 97 MTSCellularManager::GPSStatus gpsStatus = cellularManager.gpsPollStatus();
miaotwilio 1:5a896191c3c4 98 if (gpsStatus.success) {
miaotwilio 1:5a896191c3c4 99 ledGPS = 0;
miaotwilio 5:ded8fe5991a2 100 sendVehicleData(gpsStatus, tripData);
miaotwilio 1:5a896191c3c4 101 } else {
miaotwilio 1:5a896191c3c4 102 ledGPS = 1;
miaotwilio 1:5a896191c3c4 103 }
miaotwilio 1:5a896191c3c4 104 }
miaotwilio 1:5a896191c3c4 105
miaotwilio 1:5a896191c3c4 106 logInfo("Cleaning up CyaSSL");
miaotwilio 1:5a896191c3c4 107 CyaSSL_Cleanup();
miaotwilio 1:5a896191c3c4 108
miaotwilio 1:5a896191c3c4 109 logInfo("Shutting down cellular");
miaotwilio 1:5a896191c3c4 110 cellularManager.uninit();
miaotwilio 1:5a896191c3c4 111
miaotwilio 1:5a896191c3c4 112 logInfo("Program finished");
miaotwilio 1:5a896191c3c4 113 wait(1E12);
miaotwilio 1:5a896191c3c4 114 return 0;
miaotwilio 1:5a896191c3c4 115 }
miaotwilio 1:5a896191c3c4 116
miaotwilio 5:ded8fe5991a2 117 static void vehicleDataSamplingCallback() {
miaotwilio 5:ded8fe5991a2 118 pTripDataReader->sample();
miaotwilio 5:ded8fe5991a2 119 }
miaotwilio 5:ded8fe5991a2 120
miaotwilio 5:ded8fe5991a2 121 static void sendVehicleData(const MTSCellularManager::GPSStatus& gpsStatus,
miaotwilio 5:ded8fe5991a2 122 const TripDataReader::TripData& tripData) {
miaotwilio 6:4a25f3b9caef 123 vehicleDataLED = 0;
miaotwilio 1:5a896191c3c4 124
miaotwilio 1:5a896191c3c4 125 logInfo("Connecting MQTT Client");
miaotwilio 0:b32fa0c757d7 126 TlsMQTTClient client = TlsMQTTClient();
miaotwilio 0:b32fa0c757d7 127 MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
miaotwilio 2:d4dcf1ebaa99 128 data.clientID.cstring = VEHICLE_ID;
miaotwilio 2:d4dcf1ebaa99 129 data.username.cstring = VEHICLE_KEY;
miaotwilio 2:d4dcf1ebaa99 130 data.password.cstring = VEHICLE_SECRET;
miaotwilio 3:0a48c984e15b 131 int result = client.connect(MQTT_GATEWAY_HOST, MQTT_GATEWAY_PORT, MQTT_GATEWAY_PROD_ROOT_CA_PEM, data);
miaotwilio 3:0a48c984e15b 132 if (MQTT::SUCCESS == result) {
miaotwilio 0:b32fa0c757d7 133 MQTT::Message message;
miaotwilio 0:b32fa0c757d7 134 char buf[512];
miaotwilio 0:b32fa0c757d7 135
miaotwilio 1:5a896191c3c4 136 logInfo("MQTT connected");
miaotwilio 0:b32fa0c757d7 137
miaotwilio 6:4a25f3b9caef 138 if (enableODB) {
miaotwilio 6:4a25f3b9caef 139 sprintf(buf, "{"
miaotwilio 6:4a25f3b9caef 140 "\"runtime\": %d,"
miaotwilio 6:4a25f3b9caef 141 "\"miles\": %d,"
miaotwilio 6:4a25f3b9caef 142 "\"speed\": %f,"
miaotwilio 6:4a25f3b9caef 143 "\"minT\": %f,"
miaotwilio 6:4a25f3b9caef 144 "\"maxT\": %f,"
miaotwilio 6:4a25f3b9caef 145 "\"avgT\": %f,"
miaotwilio 6:4a25f3b9caef 146 "\"fuel\": %d,"
miaotwilio 6:4a25f3b9caef 147 "\"brake\": %d,"
miaotwilio 6:4a25f3b9caef 148 "\"lat\": %lf,"
miaotwilio 6:4a25f3b9caef 149 "\"lon\": %lf"
miaotwilio 6:4a25f3b9caef 150 "}",
miaotwilio 5:ded8fe5991a2 151 tripData.runtime,
miaotwilio 5:ded8fe5991a2 152 tripData.distance,
miaotwilio 5:ded8fe5991a2 153 tripData.averageSpeed,
miaotwilio 5:ded8fe5991a2 154 tripData.minimumThrottle,
miaotwilio 5:ded8fe5991a2 155 tripData.maximumThrottle,
miaotwilio 5:ded8fe5991a2 156 tripData.averageThrottle,
miaotwilio 5:ded8fe5991a2 157 tripData.fuel,
miaotwilio 5:ded8fe5991a2 158 tripData.hardBrakeCount,
miaotwilio 1:5a896191c3c4 159 gpsStatus.latitudeVal,
miaotwilio 1:5a896191c3c4 160 gpsStatus.longitudeVal);
miaotwilio 6:4a25f3b9caef 161 } else {
miaotwilio 6:4a25f3b9caef 162 sprintf(buf, "{"
miaotwilio 6:4a25f3b9caef 163 "\"speed\": %f,"
miaotwilio 6:4a25f3b9caef 164 "\"lat\": %lf,"
miaotwilio 6:4a25f3b9caef 165 "\"lon\": %lf"
miaotwilio 6:4a25f3b9caef 166 "}",
miaotwilio 6:4a25f3b9caef 167 gpsStatus.speedVal,
miaotwilio 6:4a25f3b9caef 168 gpsStatus.latitudeVal,
miaotwilio 6:4a25f3b9caef 169 gpsStatus.longitudeVal);
miaotwilio 6:4a25f3b9caef 170 }
miaotwilio 6:4a25f3b9caef 171
miaotwilio 0:b32fa0c757d7 172 message.qos = MQTT::QOS1;
miaotwilio 0:b32fa0c757d7 173 message.payload = (void*)buf;
miaotwilio 0:b32fa0c757d7 174 message.payloadlen = strlen(buf) + 1;
miaotwilio 1:5a896191c3c4 175 logInfo("MQTT message publishing buf: %s", buf);
miaotwilio 2:d4dcf1ebaa99 176 int rc = client.publish("sync/lists/vehicle-" VEHICLE_ID "-data", message);
miaotwilio 1:5a896191c3c4 177 logInfo("MQTT message publish result: %d", rc);
miaotwilio 0:b32fa0c757d7 178
miaotwilio 1:5a896191c3c4 179 logInfo("MQTT disconnecting");
miaotwilio 0:b32fa0c757d7 180 client.disconnect();
miaotwilio 3:0a48c984e15b 181 } else {
miaotwilio 3:0a48c984e15b 182 logError("MQTT connection failed %d", result);
miaotwilio 0:b32fa0c757d7 183 }
miaotwilio 6:4a25f3b9caef 184 vehicleDataLED = 1;
miaotwilio 1:5a896191c3c4 185 }
miaotwilio 0:b32fa0c757d7 186
miaotwilio 1:5a896191c3c4 187 /*
miaotwilio 1:5a896191c3c4 188 static void subscribeToTest2() {
miaotwilio 1:5a896191c3c4 189 rc = client.subscribe("sync/lists/test2", MQTT::QOS1, test2Handler);
miaotwilio 1:5a896191c3c4 190 logInfo("MQTT subscription result: %d", rc);
miaotwilio 0:b32fa0c757d7 191 }
miaotwilio 0:b32fa0c757d7 192
miaotwilio 0:b32fa0c757d7 193 static void test2Handler(MQTT::MessageData& data) {
miaotwilio 0:b32fa0c757d7 194 static const size_t MAX_DISPLAY_MESSAGE_SIZE = 30;
miaotwilio 0:b32fa0c757d7 195 char buf[MAX_DISPLAY_MESSAGE_SIZE + 1];
miaotwilio 0:b32fa0c757d7 196 if (data.message.payloadlen <= MAX_DISPLAY_MESSAGE_SIZE) {
miaotwilio 0:b32fa0c757d7 197 strncpy(buf, (char*)data.message.payload, data.message.payloadlen);
miaotwilio 0:b32fa0c757d7 198 buf[data.message.payloadlen] = '\0';
miaotwilio 0:b32fa0c757d7 199 } else {
miaotwilio 0:b32fa0c757d7 200 strncpy(buf, (char*)data.message.payload, MAX_DISPLAY_MESSAGE_SIZE - 3);
miaotwilio 0:b32fa0c757d7 201 buf[MAX_DISPLAY_MESSAGE_SIZE-3] = '.';
miaotwilio 0:b32fa0c757d7 202 buf[MAX_DISPLAY_MESSAGE_SIZE-2] = '.';
miaotwilio 0:b32fa0c757d7 203 buf[MAX_DISPLAY_MESSAGE_SIZE-1] = '.';
miaotwilio 0:b32fa0c757d7 204 buf[MAX_DISPLAY_MESSAGE_SIZE] = '\0';
miaotwilio 0:b32fa0c757d7 205 }
miaotwilio 0:b32fa0c757d7 206 logDebug("topic %s payload received len %d data %s", data.topicName.lenstring.data, data.message.payloadlen, buf);
miaotwilio 0:b32fa0c757d7 207
miaotwilio 0:b32fa0c757d7 208 // sync client can send binary data using payload format:
miaotwilio 0:b32fa0c757d7 209 // {
miaotwilio 0:b32fa0c757d7 210 // "payload": "ZXhpdA==", # base64 encoded "exit"
miaotwilio 0:b32fa0c757d7 211 // "_iot_meta": {
miaotwilio 0:b32fa0c757d7 212 // "payload_encoding": "base64",
miaotwilio 0:b32fa0c757d7 213 // "payload_type": "application/octet-stream",
miaotwilio 0:b32fa0c757d7 214 // }
miaotwilio 0:b32fa0c757d7 215 // }
miaotwilio 0:b32fa0c757d7 216 if (0 == strncmp((char*)data.message.payload, "exit", data.message.payloadlen)) {
miaotwilio 0:b32fa0c757d7 217 exitCmd = true;
miaotwilio 0:b32fa0c757d7 218 }
miaotwilio 1:5a896191c3c4 219 }*/