Template coding for ST IoT Challenge 2019

Dependencies:   Cayenne-MQTT-mbed mbed X_NUCLEO_IKS01A2 X_NUCLEO_IDW01M1v2 NetworkSocketAPI

Committer:
stiotchallenge
Date:
Tue Mar 12 03:46:52 2019 +0000
Revision:
22:22570ebcc4f2
Parent:
21:101560c87a89
Coding template for STIoTChallenge2019

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cparata 0:69566eea0fba 1 /* Includes */
cparata 0:69566eea0fba 2 #include "mbed.h"
davide.aliprandi@st.com 13:fc873da5b445 3 #include "XNucleoIKS01A2.h"
stiotchallenge 18:aedf981aa752 4 #include "MQTTTimer.h"
stiotchallenge 18:aedf981aa752 5 #include "CayenneMQTTClient.h"
stiotchallenge 18:aedf981aa752 6 #include "MQTTNetworkIDW01M1.h"
stiotchallenge 18:aedf981aa752 7 #include "SpwfInterface.h"
cparata 0:69566eea0fba 8
cparata 0:69566eea0fba 9 /* Instantiate the expansion board */
davide.aliprandi@st.com 13:fc873da5b445 10 static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);
cparata 0:69566eea0fba 11
cparata 0:69566eea0fba 12 /* Retrieve the composing elements of the expansion board */
davide.aliprandi@st.com 13:fc873da5b445 13 static LSM303AGRMagSensor *magnetometer = mems_expansion_board->magnetometer;
cparata 0:69566eea0fba 14 static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
cparata 0:69566eea0fba 15 static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor;
cparata 0:69566eea0fba 16 static LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro;
davide.aliprandi@st.com 13:fc873da5b445 17 static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer;
cparata 0:69566eea0fba 18
stiotchallenge 18:aedf981aa752 19 // WiFi network info.
stiotchallenge 22:22570ebcc4f2 20 char* ssid = "iPhone";
stiotchallenge 22:22570ebcc4f2 21 char* wifiPassword = "abcd1234";
stiotchallenge 18:aedf981aa752 22
stiotchallenge 18:aedf981aa752 23 // Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
stiotchallenge 18:aedf981aa752 24 char* username = "4f3fbcb0-3796-11e9-ad96-c15442ccb423";
stiotchallenge 18:aedf981aa752 25 char* password = "9e099f3d9aaedd7b76ca94044c6bb488c3999e3c";
stiotchallenge 20:51804ecf98a1 26 char* clientID = "4fb9dca0-3f13-11e9-a6b5-e30ec853fbf2";
stiotchallenge 18:aedf981aa752 27
stiotchallenge 18:aedf981aa752 28 SpwfSAInterface interface(D8, D2); // TX, RX
stiotchallenge 18:aedf981aa752 29 MQTTNetwork<SpwfSAInterface> network(interface);
stiotchallenge 18:aedf981aa752 30 CayenneMQTT::MQTTClient<MQTTNetwork<SpwfSAInterface>, MQTTTimer> mqttClient(network, username, password, clientID);
stiotchallenge 18:aedf981aa752 31
stiotchallenge 20:51804ecf98a1 32 /***********************************************************/
stiotchallenge 20:51804ecf98a1 33 /* External sensor and output/actuators declared here */
stiotchallenge 20:51804ecf98a1 34 /***********************************************************/
stiotchallenge 18:aedf981aa752 35 DigitalOut led1(LED1);
stiotchallenge 22:22570ebcc4f2 36 //DigitalOut ledy(D1);
stiotchallenge 18:aedf981aa752 37
cparata 0:69566eea0fba 38 /* Helper function for printing floats & doubles */
davide.aliprandi@st.com 13:fc873da5b445 39 static char *print_double(char* str, double v, int decimalDigits=2)
cparata 0:69566eea0fba 40 {
cparata 0:69566eea0fba 41 int i = 1;
cparata 0:69566eea0fba 42 int intPart, fractPart;
cparata 0:69566eea0fba 43 int len;
cparata 0:69566eea0fba 44 char *ptr;
cparata 0:69566eea0fba 45
cparata 0:69566eea0fba 46 /* prepare decimal digits multiplicator */
cparata 0:69566eea0fba 47 for (;decimalDigits!=0; i*=10, decimalDigits--);
cparata 0:69566eea0fba 48
cparata 0:69566eea0fba 49 /* calculate integer & fractinal parts */
cparata 0:69566eea0fba 50 intPart = (int)v;
cparata 0:69566eea0fba 51 fractPart = (int)((v-(double)(int)v)*i);
cparata 0:69566eea0fba 52
cparata 0:69566eea0fba 53 /* fill in integer part */
cparata 0:69566eea0fba 54 sprintf(str, "%i.", intPart);
cparata 0:69566eea0fba 55
cparata 0:69566eea0fba 56 /* prepare fill in of fractional part */
cparata 0:69566eea0fba 57 len = strlen(str);
cparata 0:69566eea0fba 58 ptr = &str[len];
cparata 0:69566eea0fba 59
cparata 0:69566eea0fba 60 /* fill in leading fractional zeros */
cparata 0:69566eea0fba 61 for (i/=10;i>1; i/=10, ptr++) {
davide.aliprandi@st.com 13:fc873da5b445 62 if (fractPart >= i) {
davide.aliprandi@st.com 13:fc873da5b445 63 break;
davide.aliprandi@st.com 13:fc873da5b445 64 }
cparata 0:69566eea0fba 65 *ptr = '0';
cparata 0:69566eea0fba 66 }
cparata 0:69566eea0fba 67
cparata 0:69566eea0fba 68 /* fill in (rest of) fractional part */
cparata 0:69566eea0fba 69 sprintf(ptr, "%i", fractPart);
cparata 0:69566eea0fba 70
cparata 0:69566eea0fba 71 return str;
cparata 0:69566eea0fba 72 }
cparata 0:69566eea0fba 73
stiotchallenge 18:aedf981aa752 74 /**
stiotchallenge 18:aedf981aa752 75 * Print the message info.
stiotchallenge 18:aedf981aa752 76 * @param[in] message The message received from the Cayenne server.
stiotchallenge 18:aedf981aa752 77 */
stiotchallenge 18:aedf981aa752 78 void outputMessage(CayenneMQTT::MessageData& message)
stiotchallenge 18:aedf981aa752 79 {
stiotchallenge 18:aedf981aa752 80 switch (message.topic) {
stiotchallenge 18:aedf981aa752 81 case COMMAND_TOPIC:
stiotchallenge 18:aedf981aa752 82 printf("topic=Command");
stiotchallenge 18:aedf981aa752 83 break;
stiotchallenge 18:aedf981aa752 84 case CONFIG_TOPIC:
stiotchallenge 18:aedf981aa752 85 printf("topic=Config");
stiotchallenge 18:aedf981aa752 86 break;
stiotchallenge 18:aedf981aa752 87 default:
stiotchallenge 18:aedf981aa752 88 printf("topic=%d", message.topic);
stiotchallenge 18:aedf981aa752 89 break;
stiotchallenge 18:aedf981aa752 90 }
stiotchallenge 18:aedf981aa752 91 printf(" channel=%d", message.channel);
stiotchallenge 18:aedf981aa752 92 if (message.clientID) {
stiotchallenge 18:aedf981aa752 93 printf(" clientID=%s", message.clientID);
stiotchallenge 18:aedf981aa752 94 }
stiotchallenge 18:aedf981aa752 95 if (message.type) {
stiotchallenge 18:aedf981aa752 96 printf(" type=%s", message.type);
stiotchallenge 18:aedf981aa752 97 }
stiotchallenge 18:aedf981aa752 98 for (size_t i = 0; i < message.valueCount; ++i) {
stiotchallenge 18:aedf981aa752 99 if (message.getValue(i)) {
stiotchallenge 18:aedf981aa752 100 printf(" value=%s", message.getValue(i));
stiotchallenge 18:aedf981aa752 101 }
stiotchallenge 18:aedf981aa752 102 if (message.getUnit(i)) {
stiotchallenge 18:aedf981aa752 103 printf(" unit=%s", message.getUnit(i));
stiotchallenge 18:aedf981aa752 104 }
stiotchallenge 18:aedf981aa752 105 }
stiotchallenge 18:aedf981aa752 106 if (message.id) {
stiotchallenge 18:aedf981aa752 107 printf(" id=%s", message.id);
stiotchallenge 18:aedf981aa752 108 }
stiotchallenge 18:aedf981aa752 109 printf("\n");
stiotchallenge 18:aedf981aa752 110 }
stiotchallenge 18:aedf981aa752 111
stiotchallenge 18:aedf981aa752 112 /**
stiotchallenge 18:aedf981aa752 113 * Handle messages received from the Cayenne server.
stiotchallenge 18:aedf981aa752 114 * @param[in] message The message received from the Cayenne server.
stiotchallenge 18:aedf981aa752 115 */
stiotchallenge 18:aedf981aa752 116 void messageArrived(CayenneMQTT::MessageData& message)
stiotchallenge 18:aedf981aa752 117 {
stiotchallenge 18:aedf981aa752 118 int error = 0;
stiotchallenge 18:aedf981aa752 119 // Add code to process the message. Here we just ouput the message data.
stiotchallenge 18:aedf981aa752 120 outputMessage(message);
stiotchallenge 18:aedf981aa752 121
stiotchallenge 18:aedf981aa752 122 if (message.topic == COMMAND_TOPIC) {
stiotchallenge 20:51804ecf98a1 123 switch(message.channel) { /****************************************************/
stiotchallenge 20:51804ecf98a1 124 case 0: /* the channel number for input */
stiotchallenge 20:51804ecf98a1 125 // Set the onboard LED state /* */
stiotchallenge 20:51804ecf98a1 126 led1 = atoi(message.getValue()); /*can add other function after received input signal*/
stiotchallenge 20:51804ecf98a1 127 // Publish the updated LED state /****************************************************/
stiotchallenge 18:aedf981aa752 128 if ((error = mqttClient.publishData(DATA_TOPIC, message.channel, NULL, NULL, message.getValue())) != CAYENNE_SUCCESS) {
stiotchallenge 18:aedf981aa752 129 printf("Publish LED state failure, error: %d\n", error);
stiotchallenge 18:aedf981aa752 130 }
stiotchallenge 18:aedf981aa752 131 break;
stiotchallenge 18:aedf981aa752 132 }
stiotchallenge 18:aedf981aa752 133
stiotchallenge 18:aedf981aa752 134 // If this is a command message we publish a response. Here we are just sending a default 'OK' response.
stiotchallenge 18:aedf981aa752 135 // An error response should be sent if there are issues processing the message.
stiotchallenge 18:aedf981aa752 136 if ((error = mqttClient.publishResponse(message.id, NULL, message.clientID)) != CAYENNE_SUCCESS) {
stiotchallenge 18:aedf981aa752 137 printf("Response failure, error: %d\n", error);
stiotchallenge 18:aedf981aa752 138 }
stiotchallenge 18:aedf981aa752 139 }
stiotchallenge 18:aedf981aa752 140 }
stiotchallenge 18:aedf981aa752 141
stiotchallenge 18:aedf981aa752 142 /**
stiotchallenge 18:aedf981aa752 143 * Connect to the Cayenne server.
stiotchallenge 18:aedf981aa752 144 * @return Returns CAYENNE_SUCCESS if the connection succeeds, or an error code otherwise.
stiotchallenge 18:aedf981aa752 145 */
stiotchallenge 18:aedf981aa752 146 int connectClient(void)
stiotchallenge 18:aedf981aa752 147 {
stiotchallenge 18:aedf981aa752 148 int error = 0;
stiotchallenge 18:aedf981aa752 149 // Connect to the server.
stiotchallenge 18:aedf981aa752 150 printf("Connecting to %s:%d\n", CAYENNE_DOMAIN, CAYENNE_PORT);
stiotchallenge 18:aedf981aa752 151 while ((error = network.connect(CAYENNE_DOMAIN, CAYENNE_PORT)) != 0) {
stiotchallenge 18:aedf981aa752 152 printf("TCP connect failed, error: %d\n", error);
stiotchallenge 18:aedf981aa752 153 wait(2);
stiotchallenge 18:aedf981aa752 154 }
stiotchallenge 18:aedf981aa752 155
stiotchallenge 18:aedf981aa752 156 if ((error = mqttClient.connect()) != MQTT::SUCCESS) {
stiotchallenge 18:aedf981aa752 157 printf("MQTT connect failed, error: %d\n", error);
stiotchallenge 18:aedf981aa752 158 return error;
stiotchallenge 18:aedf981aa752 159 }
stiotchallenge 18:aedf981aa752 160 printf("Connected\n");
stiotchallenge 18:aedf981aa752 161
stiotchallenge 18:aedf981aa752 162 // Subscribe to required topics.
stiotchallenge 18:aedf981aa752 163 if ((error = mqttClient.subscribe(COMMAND_TOPIC, CAYENNE_ALL_CHANNELS)) != CAYENNE_SUCCESS) {
stiotchallenge 18:aedf981aa752 164 printf("Subscription to Command topic failed, error: %d\n", error);
stiotchallenge 18:aedf981aa752 165 }
stiotchallenge 18:aedf981aa752 166 if ((error = mqttClient.subscribe(CONFIG_TOPIC, CAYENNE_ALL_CHANNELS)) != CAYENNE_SUCCESS) {
stiotchallenge 18:aedf981aa752 167 printf("Subscription to Config topic failed, error:%d\n", error);
stiotchallenge 18:aedf981aa752 168 }
stiotchallenge 18:aedf981aa752 169
stiotchallenge 18:aedf981aa752 170 // 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.
stiotchallenge 18:aedf981aa752 171 mqttClient.publishData(SYS_VERSION_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, CAYENNE_VERSION);
stiotchallenge 18:aedf981aa752 172 mqttClient.publishData(SYS_MODEL_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "mbedDevice");
stiotchallenge 18:aedf981aa752 173 //mqttClient.publishData(SYS_CPU_MODEL_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "CPU Model");
stiotchallenge 18:aedf981aa752 174 //mqttClient.publishData(SYS_CPU_SPEED_TOPIC, CAYENNE_NO_CHANNEL, NULL, NULL, "1000000000");
stiotchallenge 18:aedf981aa752 175
stiotchallenge 18:aedf981aa752 176 return CAYENNE_SUCCESS;
stiotchallenge 18:aedf981aa752 177 }
stiotchallenge 18:aedf981aa752 178
cparata 0:69566eea0fba 179 /* Simple main function */
cparata 0:69566eea0fba 180 int main() {
stiotchallenge 18:aedf981aa752 181 uint8_t id;
stiotchallenge 18:aedf981aa752 182 float value1, value2, value3, value4;
stiotchallenge 18:aedf981aa752 183 char buffer1[32], buffer2[32], buffer3[32], buffer4[32];
stiotchallenge 18:aedf981aa752 184 int32_t axes[3];
cparata 0:69566eea0fba 185
stiotchallenge 18:aedf981aa752 186 /* Enable all sensors */
stiotchallenge 18:aedf981aa752 187 hum_temp->enable();
stiotchallenge 18:aedf981aa752 188 press_temp->enable();
stiotchallenge 18:aedf981aa752 189 magnetometer->enable();
stiotchallenge 18:aedf981aa752 190 accelerometer->enable();
stiotchallenge 18:aedf981aa752 191 acc_gyro->enable_x();
stiotchallenge 18:aedf981aa752 192 acc_gyro->enable_g();
cparata 0:69566eea0fba 193
stiotchallenge 18:aedf981aa752 194 printf("\r\n--- Starting new run ---\r\n");
cparata 0:69566eea0fba 195
stiotchallenge 18:aedf981aa752 196 hum_temp->read_id(&id);
stiotchallenge 18:aedf981aa752 197 printf("HTS221 humidity & temperature = 0x%X\r\n", id);
stiotchallenge 18:aedf981aa752 198 press_temp->read_id(&id);
stiotchallenge 18:aedf981aa752 199 printf("LPS22HB pressure & temperature = 0x%X\r\n", id);
stiotchallenge 18:aedf981aa752 200 magnetometer->read_id(&id);
stiotchallenge 18:aedf981aa752 201 printf("LSM303AGR magnetometer = 0x%X\r\n", id);
stiotchallenge 18:aedf981aa752 202 accelerometer->read_id(&id);
stiotchallenge 18:aedf981aa752 203 printf("LSM303AGR accelerometer = 0x%X\r\n", id);
stiotchallenge 18:aedf981aa752 204 acc_gyro->read_id(&id);
stiotchallenge 18:aedf981aa752 205 printf("LSM6DSL accelerometer & gyroscope = 0x%X\r\n", id);
cparata 0:69566eea0fba 206
stiotchallenge 18:aedf981aa752 207 // Initialize the network interface.
stiotchallenge 18:aedf981aa752 208 printf("Initializing interface\n");
stiotchallenge 18:aedf981aa752 209 interface.connect(ssid, wifiPassword, NSAPI_SECURITY_WPA2);
stiotchallenge 18:aedf981aa752 210
stiotchallenge 18:aedf981aa752 211 // Set the default function that receives Cayenne messages.
stiotchallenge 18:aedf981aa752 212 mqttClient.setDefaultMessageHandler(messageArrived);
stiotchallenge 18:aedf981aa752 213
stiotchallenge 18:aedf981aa752 214 // Connect to Cayenne.
stiotchallenge 18:aedf981aa752 215 if (connectClient() == CAYENNE_SUCCESS) {
stiotchallenge 18:aedf981aa752 216 // Start the countdown timer for publishing data every 5 seconds. Change the timeout parameter to publish at a different interval.
stiotchallenge 18:aedf981aa752 217 MQTTTimer timer(5000);
stiotchallenge 18:aedf981aa752 218
stiotchallenge 18:aedf981aa752 219 while (true) {
stiotchallenge 22:22570ebcc4f2 220
stiotchallenge 18:aedf981aa752 221 // Yield to allow MQTT message processing.
stiotchallenge 18:aedf981aa752 222 mqttClient.yield(1000);
cparata 0:69566eea0fba 223
stiotchallenge 18:aedf981aa752 224 // Check that we are still connected, if not, reconnect.
stiotchallenge 18:aedf981aa752 225 if (!network.connected() || !mqttClient.connected()) {
stiotchallenge 18:aedf981aa752 226 network.disconnect();
stiotchallenge 18:aedf981aa752 227 mqttClient.disconnect();
stiotchallenge 18:aedf981aa752 228 printf("Reconnecting\n");
stiotchallenge 18:aedf981aa752 229 while (connectClient() != CAYENNE_SUCCESS) {
stiotchallenge 18:aedf981aa752 230 wait(2);
stiotchallenge 18:aedf981aa752 231 printf("Reconnect failed, retrying\n");
stiotchallenge 18:aedf981aa752 232 }
stiotchallenge 18:aedf981aa752 233 }
stiotchallenge 18:aedf981aa752 234
stiotchallenge 18:aedf981aa752 235 printf("\r\n");
stiotchallenge 18:aedf981aa752 236
stiotchallenge 18:aedf981aa752 237 hum_temp->get_temperature(&value1);
stiotchallenge 18:aedf981aa752 238 hum_temp->get_humidity(&value2);
stiotchallenge 18:aedf981aa752 239 printf("HTS221: [temp] %7s C, [hum] %s%%\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
cparata 0:69566eea0fba 240
stiotchallenge 18:aedf981aa752 241 press_temp->get_temperature(&value3);
stiotchallenge 18:aedf981aa752 242 press_temp->get_pressure(&value4);
stiotchallenge 18:aedf981aa752 243 printf("LPS22HB: [temp] %7s C, [press] %s mbar\r\n", print_double(buffer1, value3), print_double(buffer2, value4));
cparata 0:69566eea0fba 244
stiotchallenge 18:aedf981aa752 245 printf("---\r\n");
cparata 0:69566eea0fba 246
stiotchallenge 18:aedf981aa752 247 magnetometer->get_m_axes(axes);
stiotchallenge 18:aedf981aa752 248 printf("LSM303AGR [mag/mgauss]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
cparata 0:69566eea0fba 249
stiotchallenge 18:aedf981aa752 250 acc_gyro->get_x_axes(axes);
stiotchallenge 18:aedf981aa752 251 printf("LSM6DSL [acc/mg]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
cparata 0:69566eea0fba 252
stiotchallenge 18:aedf981aa752 253 accelerometer->get_x_axes(axes);
stiotchallenge 18:aedf981aa752 254 printf("LSM303AGR [acc/mg]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
stiotchallenge 18:aedf981aa752 255
stiotchallenge 18:aedf981aa752 256 acc_gyro->get_g_axes(axes);
stiotchallenge 18:aedf981aa752 257 printf("LSM6DSL [gyro/mdps]: %6ld, %6ld, %6ld\r\n", axes[0], axes[1], axes[2]);
stiotchallenge 18:aedf981aa752 258
stiotchallenge 18:aedf981aa752 259 wait(1.5);
stiotchallenge 20:51804ecf98a1 260
stiotchallenge 18:aedf981aa752 261
stiotchallenge 18:aedf981aa752 262 // Publish some example data every few seconds. This should be changed to send your actual data to Cayenne.
stiotchallenge 18:aedf981aa752 263 if (timer.expired()) {
stiotchallenge 20:51804ecf98a1 264 int error = 0; /************************/
stiotchallenge 20:51804ecf98a1 265 if ((error = mqttClient.publishData(DATA_TOPIC, 1, TYPE_TEMPERATURE, UNIT_CELSIUS, value1)) != CAYENNE_SUCCESS) { /* duplicate the if {} */
stiotchallenge 20:51804ecf98a1 266 printf("Publish temperature failed, error: %d\n", error); /* for more channel */
stiotchallenge 20:51804ecf98a1 267 } /************************/
stiotchallenge 18:aedf981aa752 268 if ((error = mqttClient.publishData(DATA_TOPIC, 2, TYPE_BAROMETRIC_PRESSURE, UNIT_PASCAL, value4)) != CAYENNE_SUCCESS) {
stiotchallenge 20:51804ecf98a1 269 printf("Publish barometric pressure failed, error: %d\n", error);
stiotchallenge 18:aedf981aa752 270 }
stiotchallenge 18:aedf981aa752 271 if ((error = mqttClient.publishData(DATA_TOPIC, 3, TYPE_PROXIMITY, UNIT_METER, axes[1])) != CAYENNE_SUCCESS) {
stiotchallenge 20:51804ecf98a1 272 printf("Publish proximity failed, error: %d\n", error);
stiotchallenge 18:aedf981aa752 273 }
stiotchallenge 18:aedf981aa752 274 // Restart the countdown timer for publishing data every 5 seconds. Change the timeout parameter to publish at a different interval.
stiotchallenge 18:aedf981aa752 275 timer.countdown_ms(5000);
stiotchallenge 18:aedf981aa752 276 }
stiotchallenge 18:aedf981aa752 277 }
stiotchallenge 18:aedf981aa752 278 }
stiotchallenge 18:aedf981aa752 279 else {
stiotchallenge 18:aedf981aa752 280 printf("Connection failed, exiting\n");
stiotchallenge 18:aedf981aa752 281 }
cparata 0:69566eea0fba 282
stiotchallenge 18:aedf981aa752 283 if (mqttClient.connected())
stiotchallenge 18:aedf981aa752 284 mqttClient.disconnect();
stiotchallenge 18:aedf981aa752 285 if (network.connected())
stiotchallenge 18:aedf981aa752 286 network.disconnect();
cparata 0:69566eea0fba 287 }