Secretariat STIoTChallenge / Mbed 2 deprecated STIoTChallenge2019

Dependencies:   Cayenne-MQTT-mbed mbed X_NUCLEO_IKS01A2 X_NUCLEO_IDW01M1v2 NetworkSocketAPI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* Includes */
00002 #include "mbed.h"
00003 #include "XNucleoIKS01A2.h"
00004 #include "MQTTTimer.h"
00005 #include "CayenneMQTTClient.h"
00006 #include "MQTTNetworkIDW01M1.h"
00007 #include "SpwfInterface.h"
00008 
00009 /* Instantiate the expansion board */
00010 static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);
00011 
00012 /* Retrieve the composing elements of the expansion board */
00013 static LSM303AGRMagSensor *magnetometer = mems_expansion_board->magnetometer;
00014 static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
00015 static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor;
00016 static LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro;
00017 static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer;
00018 
00019 // WiFi network info.
00020 char* ssid = "iPhone";
00021 char* wifiPassword = "abcd1234";
00022 
00023 // Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
00024 char* username = "4f3fbcb0-3796-11e9-ad96-c15442ccb423";
00025 char* password = "9e099f3d9aaedd7b76ca94044c6bb488c3999e3c";
00026 char* clientID = "4fb9dca0-3f13-11e9-a6b5-e30ec853fbf2";
00027 
00028 SpwfSAInterface interface(D8, D2); // TX, RX
00029 MQTTNetwork<SpwfSAInterface> network(interface);
00030 CayenneMQTT::MQTTClient<MQTTNetwork<SpwfSAInterface>, MQTTTimer> mqttClient(network, username, password, clientID);
00031 
00032 /***********************************************************/
00033 /* External sensor and output/actuators declared here      */
00034 /***********************************************************/
00035 DigitalOut led1(LED1);
00036 //DigitalOut ledy(D1);
00037 
00038 /* Helper function for printing floats & doubles */
00039 static char *print_double(char* str, double v, int decimalDigits=2)
00040 {
00041   int i = 1;
00042   int intPart, fractPart;
00043   int len;
00044   char *ptr;
00045 
00046   /* prepare decimal digits multiplicator */
00047   for (;decimalDigits!=0; i*=10, decimalDigits--);
00048 
00049   /* calculate integer & fractinal parts */
00050   intPart = (int)v;
00051   fractPart = (int)((v-(double)(int)v)*i);
00052 
00053   /* fill in integer part */
00054   sprintf(str, "%i.", intPart);
00055 
00056   /* prepare fill in of fractional part */
00057   len = strlen(str);
00058   ptr = &str[len];
00059 
00060   /* fill in leading fractional zeros */
00061   for (i/=10;i>1; i/=10, ptr++) {
00062     if (fractPart >= i) {
00063       break;
00064     }
00065     *ptr = '0';
00066   }
00067 
00068   /* fill in (rest of) fractional part */
00069   sprintf(ptr, "%i", fractPart);
00070 
00071   return str;
00072 }
00073 
00074 /**
00075 * Print the message info.
00076 * @param[in] message The message received from the Cayenne server.
00077 */
00078 void outputMessage(CayenneMQTT::MessageData& message)
00079 {
00080     switch (message.topic)  {
00081     case COMMAND_TOPIC:
00082         printf("topic=Command");
00083         break;
00084     case CONFIG_TOPIC:
00085         printf("topic=Config");
00086         break;
00087     default:
00088         printf("topic=%d", message.topic);
00089         break;
00090     }
00091     printf(" channel=%d", message.channel);
00092     if (message.clientID) {
00093         printf(" clientID=%s", message.clientID);
00094     }
00095     if (message.type) {
00096         printf(" type=%s", message.type);
00097     }
00098     for (size_t i = 0; i < message.valueCount; ++i) {
00099         if (message.getValue(i)) {
00100             printf(" value=%s", message.getValue(i));
00101         }
00102         if (message.getUnit(i)) {
00103             printf(" unit=%s", message.getUnit(i));
00104         }
00105     }
00106     if (message.id) {
00107         printf(" id=%s", message.id);
00108     }
00109     printf("\n");
00110 }
00111 
00112 /**
00113 * Handle messages received from the Cayenne server.
00114 * @param[in] message The message received from the Cayenne server.
00115 */
00116 void messageArrived(CayenneMQTT::MessageData& message)
00117 {
00118     int error = 0;
00119     // Add code to process the message. Here we just ouput the message data.
00120     outputMessage(message);
00121 
00122     if (message.topic == COMMAND_TOPIC) {
00123         switch(message.channel) {               /****************************************************/
00124         case 0:                                 /* the channel number for input                     */
00125             // Set the onboard LED state        /*                                                  */
00126             led1 = atoi(message.getValue());    /*can add other function after received input signal*/
00127             // Publish the updated LED state    /****************************************************/
00128             if ((error = mqttClient.publishData(DATA_TOPIC, message.channel, NULL, NULL, message.getValue())) != CAYENNE_SUCCESS) {
00129                 printf("Publish LED state failure, error: %d\n", error);
00130             }
00131             break;
00132         }
00133         
00134         // If this is a command message we publish a response. Here we are just sending a default 'OK' response.
00135         // An error response should be sent if there are issues processing the message.
00136         if ((error = mqttClient.publishResponse(message.id, NULL, message.clientID)) != CAYENNE_SUCCESS) {
00137             printf("Response failure, error: %d\n", error);
00138         }
00139     }
00140 }
00141 
00142 /**
00143 * Connect to the Cayenne server.
00144 * @return Returns CAYENNE_SUCCESS if the connection succeeds, or an error code otherwise.
00145 */
00146 int connectClient(void)
00147 {
00148     int error = 0;
00149     // Connect to the server.
00150     printf("Connecting to %s:%d\n", CAYENNE_DOMAIN, CAYENNE_PORT);
00151     while ((error = network.connect(CAYENNE_DOMAIN, CAYENNE_PORT)) != 0) {
00152         printf("TCP connect failed, error: %d\n", error);
00153         wait(2);
00154     }
00155 
00156     if ((error = mqttClient.connect()) != MQTT::SUCCESS) {
00157         printf("MQTT connect failed, error: %d\n", error);
00158         return error;
00159     }
00160     printf("Connected\n");
00161 
00162     // Subscribe to required topics.
00163     if ((error = mqttClient.subscribe(COMMAND_TOPIC, CAYENNE_ALL_CHANNELS)) != CAYENNE_SUCCESS) {
00164         printf("Subscription to Command topic failed, error: %d\n", error);
00165     }
00166     if ((error = mqttClient.subscribe(CONFIG_TOPIC, CAYENNE_ALL_CHANNELS)) != CAYENNE_SUCCESS) {
00167         printf("Subscription to Config topic failed, error:%d\n", error);
00168     }
00169 
00170     // 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.
00171     mqttClient.publishData(SYS_VERSION_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, CAYENNE_VERSION);
00172     mqttClient.publishData(SYS_MODEL_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "mbedDevice");
00173     //mqttClient.publishData(SYS_CPU_MODEL_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "CPU Model");
00174     //mqttClient.publishData(SYS_CPU_SPEED_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "1000000000");
00175 
00176     return CAYENNE_SUCCESS;
00177 }
00178 
00179 /* Simple main function */
00180 int main() {
00181     uint8_t id;
00182     float value1, value2, value3, value4;
00183     char buffer1[32], buffer2[32], buffer3[32], buffer4[32];
00184     int32_t axes[3];
00185   
00186     /* Enable all sensors */
00187     hum_temp->enable();
00188     press_temp->enable();
00189     magnetometer->enable();
00190     accelerometer->enable();
00191     acc_gyro->enable_x();
00192     acc_gyro->enable_g();
00193   
00194     printf("\r\n--- Starting new run ---\r\n");
00195 
00196     hum_temp->read_id(&id);
00197     printf("HTS221  humidity & temperature    = 0x%X\r\n", id);
00198     press_temp->read_id(&id);
00199     printf("LPS22HB  pressure & temperature   = 0x%X\r\n", id);
00200     magnetometer->read_id(&id);
00201     printf("LSM303AGR magnetometer            = 0x%X\r\n", id);
00202     accelerometer->read_id(&id);
00203     printf("LSM303AGR accelerometer           = 0x%X\r\n", id);
00204     acc_gyro->read_id(&id);
00205     printf("LSM6DSL accelerometer & gyroscope = 0x%X\r\n", id);
00206  
00207     // Initialize the network interface.
00208     printf("Initializing interface\n");
00209     interface.connect(ssid, wifiPassword, NSAPI_SECURITY_WPA2);
00210 
00211     // Set the default function that receives Cayenne messages.
00212     mqttClient.setDefaultMessageHandler(messageArrived);
00213 
00214     // Connect to Cayenne.
00215     if (connectClient() == CAYENNE_SUCCESS) {
00216         // Start the countdown timer for publishing data every 5 seconds. Change the timeout parameter to publish at a different interval.
00217         MQTTTimer timer(5000);
00218 
00219         while (true) {
00220                        
00221             // Yield to allow MQTT message processing.
00222             mqttClient.yield(1000);
00223 
00224             // Check that we are still connected, if not, reconnect.
00225             if (!network.connected() || !mqttClient.connected()) {
00226                 network.disconnect();
00227                 mqttClient.disconnect();
00228                 printf("Reconnecting\n");
00229                 while (connectClient() != CAYENNE_SUCCESS) {
00230                     wait(2);
00231                     printf("Reconnect failed, retrying\n");
00232                 }
00233             }
00234         
00235             printf("\r\n");
00236 
00237             hum_temp->get_temperature(&value1);
00238             hum_temp->get_humidity(&value2);
00239             printf("HTS221: [temp] %7s C,   [hum] %s%%\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
00240     
00241             press_temp->get_temperature(&value3);
00242             press_temp->get_pressure(&value4);
00243             printf("LPS22HB: [temp] %7s C, [press] %s mbar\r\n", print_double(buffer1, value3), print_double(buffer2, value4));
00244 
00245             printf("---\r\n");
00246 
00247             magnetometer->get_m_axes(axes);
00248             printf("LSM303AGR [mag/mgauss]:  %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
00249     
00250             acc_gyro->get_x_axes(axes);
00251             printf("LSM6DSL [acc/mg]:      %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
00252 
00253             accelerometer->get_x_axes(axes);
00254             printf("LSM303AGR [acc/mg]:  %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
00255     
00256             acc_gyro->get_g_axes(axes);
00257             printf("LSM6DSL [gyro/mdps]:   %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
00258     
00259             wait(1.5);
00260 
00261             
00262             // Publish some example data every few seconds. This should be changed to send your actual data to Cayenne.
00263             if (timer.expired()) {
00264                 int error = 0;                                                                                                      /************************/
00265                 if ((error = mqttClient.publishData(DATA_TOPIC, 1, TYPE_TEMPERATURE, UNIT_CELSIUS, value1)) != CAYENNE_SUCCESS) {   /* duplicate the if {}  */
00266                     printf("Publish temperature failed, error: %d\n", error);                                                       /* for more channel     */
00267                 }                                                                                                                   /************************/
00268                 if ((error = mqttClient.publishData(DATA_TOPIC, 2, TYPE_BAROMETRIC_PRESSURE, UNIT_PASCAL, value4)) != CAYENNE_SUCCESS) {
00269                     printf("Publish barometric pressure failed, error: %d\n", error);
00270                 }
00271                 if ((error = mqttClient.publishData(DATA_TOPIC, 3, TYPE_PROXIMITY, UNIT_METER, axes[1])) != CAYENNE_SUCCESS) {
00272                     printf("Publish proximity failed, error: %d\n", error);
00273                 }
00274                 // Restart the countdown timer for publishing data every 5 seconds. Change the timeout parameter to publish at a different interval.
00275                 timer.countdown_ms(5000);
00276             }
00277         }    
00278     }
00279     else {
00280         printf("Connection failed, exiting\n");
00281     }
00282 
00283     if (mqttClient.connected())
00284         mqttClient.disconnect();
00285     if (network.connected())
00286         network.disconnect();
00287 }