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
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
main.cpp@6:4a25f3b9caef, 2017-09-08 (annotated)
- 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?
User | Revision | Line number | New 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 | }*/ |