Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Cayenne-MQTT-mbed-MTSAS X_NUCLEO_IKS01A1 mbed mtsas_lat3
main.cpp
00001 #include "mbed.h" 00002 00003 #include "mtsas.h" 00004 00005 #include "MQTTTimer.h" 00006 #include "CayenneMQTTClient.h" 00007 #include "MQTTNetwork.h" 00008 00009 #include "x_nucleo_iks01a1.h" 00010 00011 #include <string> 00012 #include <sstream> 00013 00014 using std::string; 00015 typedef CayenneMQTT::MQTTClient<MQTTNetwork<Cellular>, MQTTTimer> MQTTClient; 00016 00017 // Cayenne authentication info. This should be obtained from the Cayenne Dashboard. 00018 string username = "da497640-dcce-11e6-b089-9f6bfa78ab33"; //"MQTT-Username"; 00019 string password = "68e890972b6cc0fc47fcd152554db7e78ec9b29f"; //"MQTT-Password"; 00020 string clientID = "dc9c10d0-ced9-11e7-98e1-8369df76aa6d"; //"MQTT-ClientID"; 00021 00022 DigitalOut Led1Out(D1); 00023 DigitalOut Led2Out(D0); 00024 DigitalOut Led3Out(D3); 00025 DigitalOut Led4Out(D6); 00026 DigitalOut Led5Out(D6); 00027 DigitalOut Led6Out(D8); 00028 DigitalOut Led7Out(D5); 00029 DigitalOut Led8Out(D4); 00030 DigitalOut Led9Out(D7); 00031 DigitalOut LedStatus(D2); 00032 00033 // Debug serial port 00034 //static Serial debug(USBTX, USBRX); 00035 Serial pc(USBTX, USBRX); 00036 00037 // MTSSerialFlowControl - serial link between processor and radio 00038 static MTSSerialFlowControl* io; 00039 00040 // Cellular - radio object for cellular operations (SMS, TCP, etc) 00041 Cellular* radio; 00042 00043 /* Instantiate the expansion board */ 00044 static X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(I2C_SDA, I2C_SCL); 00045 00046 /* Retrieve the composing elements of the expansion board */ 00047 static GyroSensor *gyroscope = mems_expansion_board->GetGyroscope(); 00048 static MotionSensor *accelerometer = mems_expansion_board->GetAccelerometer(); 00049 static MagneticSensor *magnetometer = mems_expansion_board->magnetometer; 00050 static HumiditySensor *humidity_sensor = mems_expansion_board->ht_sensor; 00051 static PressureSensor *pressure_sensor = mems_expansion_board->pt_sensor; 00052 static TempSensor *temp_sensor1 = mems_expansion_board->ht_sensor; 00053 static TempSensor *temp_sensor2 = mems_expansion_board->pt_sensor; 00054 00055 static const std::string apn = "b2b.tmobile.com"; //"iot.aer.net"; 00056 00057 CayenneMQTT::MessageData lastMessage; 00058 bool messageReady; 00059 bool gpsAvailable; 00060 00061 /* 00062 * Initialize cellular radio. 00063 */ 00064 bool init_mtsas() 00065 { 00066 io = new MTSSerialFlowControl(RADIO_TX, RADIO_RX, RADIO_RTS, RADIO_CTS); 00067 if (! io) 00068 return false; 00069 00070 io->baud(115200); 00071 radio = CellularFactory::create(io); 00072 if (! radio) 00073 return false; 00074 00075 logInfo("setting APN"); 00076 if (radio->setApn(apn) != MTS_SUCCESS) 00077 logError("failed to set APN to \"%s\"", apn.c_str()); 00078 00079 Transport::setTransport(radio); 00080 while (! radio->connect()) { 00081 logError("failed to bring up PPP link"); 00082 wait(2); 00083 } 00084 00085 printf("Signal Strength: %d\n\r", radio->getSignalStrength()); 00086 return true; 00087 } 00088 00089 /** 00090 * Print the message info. 00091 * @param[in] message The message received from the Cayenne server. 00092 */ 00093 void outputMessage(CayenneMQTT::MessageData& message) 00094 { 00095 switch (message.topic) { 00096 case COMMAND_TOPIC: 00097 printf("topic=Command"); 00098 break; 00099 case CONFIG_TOPIC: 00100 printf("topic=Config"); 00101 break; 00102 default: 00103 printf("topic=%d", message.topic); 00104 break; 00105 } 00106 printf(" channel=%d", message.channel); 00107 if (message.clientID) { 00108 printf(" clientID=%s", message.clientID); 00109 } 00110 if (message.type) { 00111 printf(" type=%s", message.type); 00112 } 00113 for (size_t i = 0; i < message.valueCount; ++i) { 00114 if (message.getValue(i)) { 00115 printf(" value=%s", message.getValue(i)); 00116 } 00117 if (message.getUnit(i)) { 00118 printf(" unit=%s", message.getUnit(i)); 00119 } 00120 } 00121 if (message.id) { 00122 printf(" id=%s", message.id); 00123 } 00124 printf("\r\n"); 00125 } 00126 00127 /** 00128 * 00129 * 00130 */ 00131 void setLEDs(bool newState) 00132 { 00133 // note: false = lit LED 00134 Led1Out = !newState; 00135 Led2Out = !newState; 00136 Led3Out = !newState; 00137 Led4Out = !newState; 00138 Led5Out = !newState; 00139 Led6Out = !newState; 00140 Led7Out = !newState; 00141 Led8Out = !newState; 00142 Led9Out = !newState; 00143 } 00144 00145 /** 00146 * Handle messages received from the Cayenne server. 00147 * @param[in] message The message received from the Cayenne server. 00148 */ 00149 void messageArrived(CayenneMQTT::MessageData& message) 00150 { 00151 int error = 0; 00152 //note: if you change this example to use mbed-os you will need a mutex 00153 lastMessage = message; 00154 messageReady = true; 00155 00156 } 00157 00158 /** 00159 * Connect to the Cayenne server. 00160 * @return Returns CAYENNE_SUCCESS if the connection succeeds, or an error code otherwise. 00161 */ 00162 int connectClient(MQTTClient &mqttClient, MQTTNetwork<Cellular> &network) 00163 { 00164 int error = 0; 00165 // Connect to the server. 00166 printf("Connecting to %s:%d\r\n", CAYENNE_DOMAIN, CAYENNE_PORT); 00167 while ((error = network.connect(CAYENNE_DOMAIN, CAYENNE_PORT)) != 0) { 00168 printf("TCP connect failed, error: %d\r\n", error); 00169 wait(2); 00170 } 00171 00172 if ((error = mqttClient.connect()) != MQTT::SUCCESS) { 00173 printf("MQTT connect failed, error: %d\r\n", error); 00174 return error; 00175 } 00176 printf("Connected\r\n"); 00177 00178 // Subscribe to required topics. 00179 if ((error = mqttClient.subscribe(COMMAND_TOPIC, CAYENNE_ALL_CHANNELS)) != CAYENNE_SUCCESS) { 00180 printf("Subscription to Command topic failed, error: %d\r\n", error); 00181 } 00182 if ((error = mqttClient.subscribe(CONFIG_TOPIC, CAYENNE_ALL_CHANNELS)) != CAYENNE_SUCCESS) { 00183 printf("Subscription to Config topic failed, error:%d\r\n", error); 00184 } 00185 00186 // Send device info. Here we just send some example values for the system info. These should be changed to use actual system data, or removed if not needed. 00187 mqttClient.publishData(SYS_VERSION_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, CAYENNE_VERSION); 00188 mqttClient.publishData(SYS_MODEL_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "mbedDevice"); 00189 //mqttClient.publishData(SYS_CPU_MODEL_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "CPU Model"); 00190 //mqttClient.publishData(SYS_CPU_SPEED_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "1000000000"); 00191 00192 return CAYENNE_SUCCESS; 00193 } 00194 00195 /** 00196 * Main loop where MQTT code is run. 00197 */ 00198 void loop(MQTTClient &mqttClient, MQTTNetwork<Cellular> &network) 00199 { 00200 // Start the countdown timer for publishing data every 5 seconds. Change the timeout parameter to publish at a different interval. 00201 MQTTTimer timer(1000); 00202 printf("Starting loop.\r\n"); 00203 while (true) { 00204 // Yield to allow MQTT message processing. 00205 mqttClient.yield(10); 00206 if(messageReady){ 00207 int error = 0; 00208 messageReady = false; 00209 // Add code to process the message. Here we just ouput the message data. 00210 outputMessage(lastMessage); 00211 00212 if (lastMessage.topic == COMMAND_TOPIC) { 00213 switch(lastMessage.channel) { 00214 case 0: 00215 // Set the onboard LED state 00216 bool value = atoi(lastMessage.getValue()); 00217 setLEDs(value); 00218 00219 // Publish the updated LED state 00220 if ((error = mqttClient.publishData(DATA_TOPIC, lastMessage.channel, NULL, NULL, Led1Out.read()==0?1:0)) != CAYENNE_SUCCESS) { 00221 printf("Publish LED state failure, error: %d\r\n", error); 00222 } 00223 break; 00224 } 00225 00226 // If this is a command message we publish a response. Here we are just sending a default 'OK' response. 00227 // An error response should be sent if there are issues processing the message. 00228 if ((error = mqttClient.publishResponse(lastMessage.id, NULL, lastMessage.clientID)) != CAYENNE_SUCCESS) { 00229 printf("Response failure, error: %d\r\n", error); 00230 } 00231 } 00232 } 00233 00234 // Check that we are still connected, if not, reconnect. 00235 if (!network.connected() || !mqttClient.connected()) { 00236 network.disconnect(); 00237 mqttClient.disconnect(); 00238 LedStatus = true; 00239 printf("Reconnecting\r\n"); 00240 while (connectClient(mqttClient, network) != CAYENNE_SUCCESS) { 00241 wait(2); 00242 printf("Reconnect failed, retrying\r\n"); 00243 } 00244 LedStatus = false; 00245 } 00246 00247 // Publish some example data every few seconds. This should be changed to send your actual data to Cayenne. 00248 if (timer.expired()) { 00249 printf("Sampling sensors\r\n"); 00250 int error = 0; 00251 float temp_data; 00252 temp_sensor1->get_temperature(&temp_data); 00253 printf("Temperature was: %f \r\n", temp_data); 00254 if ((error = mqttClient.publishData(DATA_TOPIC, 1, TYPE_TEMPERATURE, UNIT_CELSIUS, temp_data)) != CAYENNE_SUCCESS) { 00255 printf("Publish temperature failed, error: %d\r\n", error); 00256 } 00257 humidity_sensor->get_humidity(&temp_data); 00258 printf("Humidity was: %f \r\n", temp_data); 00259 if ((error = mqttClient.publishData(DATA_TOPIC, 2, TYPE_RELATIVE_HUMIDITY, UNIT_PERCENT, temp_data)) != CAYENNE_SUCCESS) { 00260 printf("Publish luminosity failed, error: %d\r\n", error); 00261 } 00262 pressure_sensor->get_pressure(&temp_data); 00263 printf("Pressure was: %f \r\n", temp_data); 00264 if ((error = mqttClient.publishData(DATA_TOPIC, 3, TYPE_BAROMETRIC_PRESSURE, UNIT_HECTOPASCAL, temp_data)) != CAYENNE_SUCCESS) { 00265 printf("Publish barometric pressure failed, error: %d\r\n", error); 00266 } 00267 printf("Led is: %s\r\n", Led1Out.read() > 0 ? "off" : "on"); 00268 if ((error = mqttClient.publishData(DATA_TOPIC, 0, "digital_actuator", UNIT_DIGITAL, Led1Out.read()==0?1:0)) != CAYENNE_SUCCESS) { 00269 printf("Publish LED status failed, error: %d\r\n", error); 00270 } 00271 00272 if(gpsAvailable){ 00273 // disconnect socket so we can query GPS 00274 mqttClient.disconnect(); 00275 network.disconnect(); 00276 00277 if( !radio->GPSenabled() ) { 00278 printf("GPS: enabling"); 00279 radio->GPSenable(); 00280 while( !radio->GPSenabled() ) { 00281 logInfo("..."); 00282 wait(5); 00283 } 00284 } 00285 //collect gps data 00286 Cellular::gpsData loc = radio->GPSgetPosition(); 00287 00288 LedStatus = true; 00289 printf("Reconnecting\r\n"); 00290 while (connectClient(mqttClient, network) != CAYENNE_SUCCESS) { 00291 wait(2); 00292 printf("Reconnect failed, retrying\r\n"); 00293 } 00294 00295 if(loc.success == false){ 00296 printf("GPSgetPosition failed\r\n"); 00297 } else { 00298 switch(loc.fix){ 00299 case 0: 00300 case 1: 00301 printf("GPS - no Lock\r\n"); break; 00302 case 2: 00303 printf("GPS - 2d Lock\r\n"); break; 00304 case 3: 00305 printf("GPS - 3d Lock\r\n"); break; 00306 } 00307 } 00308 if(loc.fix > 1){ 00309 std::string payload = loc.latitude + ","; 00310 payload += loc.longitude; 00311 payload += ","; 00312 payload += loc.altitude; 00313 error = mqttClient.publishData(DATA_TOPIC, 4, "gps", "m", payload.c_str()); 00314 if( error != CAYENNE_SUCCESS) { 00315 printf("Publish GPS latitude status failed, error: %d\r\n", error); 00316 } 00317 // error = mqttClient.publishData(DATA_TOPIC, 5, "location_long", NULL, loc.longitude.c_str()); 00318 // if( error != CAYENNE_SUCCESS) { 00319 // printf("Publish GPS longitude status failed, error: %d\r\n", error); 00320 // } 00321 } 00322 } 00323 // Restart the countdown timer for publishing data every 5 seconds. Change the timeout parameter to publish at a different interval. 00324 timer.countdown_ms(5000); 00325 } else { 00326 // debug 00327 // printf("Timer: %d", timer.left_ms()); 00328 } 00329 } 00330 } 00331 00332 int main() 00333 { 00334 pc.baud(115200); 00335 setLEDs(false); 00336 LedStatus = true; 00337 mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL); 00338 // init radio, setup Cayenne connection 00339 if (!init_mtsas()) { 00340 while (true) { 00341 logError("failed to initialize cellular radio"); 00342 wait(1); 00343 } 00344 } 00345 00346 // Test with a ping 00347 if(radio->ping("www.google.com")){ 00348 printf("Ping test succeeded!\r\n"); 00349 } else { 00350 printf("Failed ping test!\r\n"); 00351 } 00352 00353 gpsAvailable = radio 00354 ->GPSenable(); 00355 MQTTNetwork<Cellular> network(*radio); 00356 messageReady = false; 00357 MQTTClient mqttClient(network, username.c_str(), password.c_str(), clientID.c_str()); 00358 00359 // Set the default function that receives Cayenne messages. 00360 mqttClient.setDefaultMessageHandler(messageArrived); 00361 00362 // Connect to Cayenne. 00363 if (connectClient(mqttClient, network) == CAYENNE_SUCCESS) { 00364 // Run main loop. 00365 LedStatus = false; 00366 loop(mqttClient, network); 00367 } 00368 else { 00369 printf("Connection failed, exiting\r\n"); 00370 } 00371 00372 if (mqttClient.connected()) 00373 mqttClient.disconnect(); 00374 if (network.connected()) 00375 network.disconnect(); 00376 00377 return 0; 00378 }
Generated on Wed Jul 13 2022 16:11:37 by
1.7.2