BG96 Module MQTT client example using X-NUCLEO-IKS01A2
Dependencies: mbed X_NUCLEO_IKS01A2 NetworkSocketAPI MQTT
main.cpp
00001 /* BG96 NetworkSocketAPI Example Program 00002 * Copyright (c) 2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "mbed.h" 00018 #include "BG96Interface.h" 00019 #include "TCPSocket.h" 00020 #include "MQTTClient.h" 00021 #include "MQTT_GSM.h" 00022 #include <ctype.h> 00023 //#include "x_nucleo_iks01a1.h" 00024 #include "XNucleoIKS01A2.h" 00025 00026 #include "BG96.h" 00027 00028 #include "SLG46824Interface.h" 00029 #include "SLG46824_driver.h" 00030 00031 //------------------------------------ 00032 // Hyperterminal default configuration 00033 // 9600 bauds, 8-bit data, no parity 00034 //------------------------------------ 00035 Serial pc(SERIAL_TX, SERIAL_RX); 00036 DigitalOut myled(LED1); 00037 bool quickstartMode = true; 00038 00039 #define MQTT_MAX_PACKET_SIZE 300 00040 #define MQTT_MAX_PAYLOAD_SIZE 500 00041 00042 00043 #define ORG_QUICKSTART // comment to connect to play.internetofthings.ibmcloud.com 00044 //#define SUBSCRIBE // uncomment to subscribe to broker msgs (not to be used with IBM broker) 00045 00046 // Configuration values needed to connect to IBM IoT Cloud 00047 #define BROKER_URL ".messaging.internetofthings.ibmcloud.com"; 00048 #ifdef ORG_QUICKSTART 00049 #define ORG "quickstart" // connect to quickstart.internetofthings.ibmcloud.com/ For a registered connection, replace with your org 00050 #define ID "" 00051 #define AUTH_TOKEN "" 00052 #define DEFAULT_TYPE_NAME "iotsample-mbed-Nucleo" 00053 #define TOPIC "iot-2/evt/status/fmt/json" 00054 #else // not def ORG_QUICKSTART 00055 #define ORG "pvko17" // connect to play.internetofthings.ibmcloud.com/ For a registered connection, replace with your org 00056 #define ID "testtype_112233445566" // For a registered connection, replace with your id 00057 #define AUTH_TOKEN "testtype_112233445566" // For a registered connection, replace with your auth-token 00058 #define DEFAULT_TYPE_NAME "TestType" 00059 #define TOPIC "iot-2/type/TestType/id/testtype_112233445566/evt/status/fmt/json" 00060 #endif 00061 00062 // network credential 00063 #define APN "web.omnitel.it" //VODAFONE apn definition's 00064 //#define APN "internet.wind" //WIND apn definition's 00065 #define PASSW "" 00066 #define USNAME "" 00067 00068 #define TYPE DEFAULT_TYPE_NAME // For a registered connection, replace with your type 00069 #define MQTT_PORT 1883 00070 #define MQTT_TLS_PORT 8883 00071 #define IBM_IOT_PORT MQTT_PORT 00072 00073 char id[30] = ID; // mac without colons 00074 char org[12] = ORG; 00075 int connack_rc = 0; // MQTT connack return code 00076 //const char* ip_addr = "11.12.13.14"; 00077 //char* host_addr = "11.12.13.14"; 00078 char sensor_id[50]; 00079 char type[30] = TYPE; 00080 char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode 00081 bool netConnecting = false; 00082 int connectTimeout = 1000; 00083 bool mqttConnecting = false; 00084 bool netConnected = false; 00085 bool connected = false; 00086 int retryAttempt = 0; 00087 char subscription_url[MQTT_MAX_PAYLOAD_SIZE]; 00088 00089 #define SENSOR_ENABLED 1 00090 #define SENSOR_MODEL 2 00091 00092 #define FW_REV "1.0a" 00093 00094 PressureSensor *pressure_sensor; 00095 HumiditySensor *humidity_sensor; 00096 TempSensor *temp_sensor1; 00097 00098 MQTT::Message message; 00099 MQTTString TopicName={TOPIC}; 00100 MQTT::MessageData MsgData(TopicName, message); 00101 00102 /* Instantiate the expansion board */ 00103 static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5); 00104 00105 /* Retrieve the composing elements of the expansion board */ 00106 static LSM303AGRMagSensor *magnetometer = mems_expansion_board->magnetometer; 00107 static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor; 00108 static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor; 00109 static LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro; 00110 static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer; 00111 00112 void subscribe_cb(MQTT::MessageData & msgMQTT) { 00113 char msg[MQTT_MAX_PAYLOAD_SIZE]; 00114 msg[0]='\0'; 00115 strncat (msg, (char*)msgMQTT.message.payload, msgMQTT.message.payloadlen); 00116 printf ("--->>> subscribe_cb msg: %s\n\r", msg); 00117 } 00118 00119 int subscribe(MQTT::Client<MQTT_GSM, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTT_GSM* ipstack) 00120 { 00121 char* pubTopic = TOPIC; 00122 return client->subscribe(pubTopic, MQTT::QOS1, subscribe_cb); 00123 } 00124 00125 int connect(MQTT::Client<MQTT_GSM, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTT_GSM* ipstack) 00126 { 00127 const char* iot_ibm = BROKER_URL; 00128 00129 00130 char hostname[strlen(org) + strlen(iot_ibm) + 1]; 00131 sprintf(hostname, "%s%s", org, iot_ibm); 00132 00133 00134 // Construct clientId - d:org:type:id 00135 char clientId[strlen(org) + strlen(type) + strlen(id) + 5]; 00136 00137 #ifdef ORG_QUICKSTART 00138 sprintf(clientId, "d:%s:%s:%s", org, type, id); //@@ 00139 #else 00140 sprintf(clientId, "g:%s:%s:%s", org, type, id); //@@ 00141 #endif 00142 00143 sprintf(subscription_url, "%s.%s/#/device/%s/sensor/", org, "internetofthings.ibmcloud.com",id); 00144 00145 netConnecting = true; 00146 ipstack->open(&ipstack->getGSM()); 00147 int rc = ipstack->connect(hostname, IBM_IOT_PORT, connectTimeout); 00148 if (rc != 0) 00149 { 00150 //WARN("IP Stack connect returned: %d\n", rc); 00151 return rc; 00152 } 00153 pc.printf ("--->TCP Connected\n\r"); 00154 netConnected = true; 00155 netConnecting = false; 00156 00157 // MQTT Connect 00158 mqttConnecting = true; 00159 MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 00160 data.MQTTVersion = 3; 00161 data.struct_version=0; 00162 data.clientID.cstring = clientId; 00163 00164 if (!quickstartMode) 00165 { 00166 data.username.cstring = "use-token-auth"; 00167 data.password.cstring = auth_token; 00168 } 00169 if ((rc = client->connect(data)) == 0) 00170 { 00171 connected = true; 00172 pc.printf ("--->MQTT Connected\n\r"); 00173 #ifdef SUBSCRIBE 00174 if (!subscribe(client, ipstack)) printf ("--->>>MQTT subscribed to: %s\n\r",TOPIC); 00175 #endif 00176 } 00177 else { 00178 //WARN("MQTT connect returned %d\n", rc); 00179 } 00180 if (rc >= 0) 00181 connack_rc = rc; 00182 mqttConnecting = false; 00183 return rc; 00184 } 00185 00186 int getConnTimeout(int attemptNumber) 00187 { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute 00188 // after 20 attempts, retry every 10 minutes 00189 return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600; 00190 } 00191 00192 void attemptConnect(MQTT::Client<MQTT_GSM, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTT_GSM* ipstack) 00193 { 00194 connected = false; 00195 00196 while (connect(client, ipstack) != MQTT_CONNECTION_ACCEPTED) 00197 { 00198 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) { 00199 printf ("File: %s, Line: %d Error: %d\n\r",__FILE__,__LINE__, connack_rc); 00200 return; // don't reattempt to connect if credentials are wrong 00201 } 00202 int timeout = getConnTimeout(++retryAttempt); 00203 //WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout); 00204 00205 // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed 00206 // or maybe just add the proper members to do this disconnect and call attemptConnect(...) 00207 // this works - reset the system when the retry count gets to a threshold 00208 if (retryAttempt == 5){ 00209 pc.printf ("\n\n\rFAIL!! system reset!!\n\n\r"); 00210 NVIC_SystemReset(); 00211 } 00212 else 00213 wait(timeout); 00214 } 00215 } 00216 float hum_global = 50.0; 00217 uint32_t n_msg = 0; 00218 00219 int publish(MQTT::Client<MQTT_GSM, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTT_GSM* ipstack) 00220 { 00221 MQTT::Message message; 00222 char* pubTopic = TOPIC; 00223 00224 char buf[MQTT_MAX_PAYLOAD_SIZE]; 00225 float temp, temp1, temp2, press, hum; 00226 00227 #if SENSOR_ENABLED 00228 pc.printf("A02 reading sensors..."); 00229 00230 hum_temp->get_temperature(&temp1); 00231 hum_temp->get_humidity(&hum); 00232 00233 press_temp->get_temperature(&temp2); 00234 press_temp->get_pressure(&press); 00235 temp = (temp1+temp2)/2; 00236 00237 pc.printf(" DONE\r\n"); 00238 #else 00239 temp=25.5; 00240 hum_global +=0.1; 00241 if (hum_global>99.0) 00242 hum_global = 50.0; 00243 hum=hum_global; 00244 press=999; 00245 #endif 00246 00247 #ifdef ORG_QUICKSTART 00248 sprintf(buf, 00249 "{\"d\":{\"ST\":\"Nucleo-IoT-mbed\",\"Temp\":%0.4f,\"Pressure\":%0.4f,\"Humidity\":%0.4f}}", 00250 temp, press, hum); 00251 #else 00252 sprintf (buf, 00253 "{\"%s\": {\"temp\":%0.4f,\"humidity\":%0.4f,\"pressure\":%0.4f,\"ambient\":0,\"uv\":0,\"accel_X\":0,\"accel_Y\":0,\"accel_Z\":0}}", 00254 sensor_id, temp, hum, press); 00255 #endif 00256 00257 message.qos = MQTT::QOS0; 00258 message.retained = false; 00259 message.dup = false; 00260 message.payload = (void*)buf; 00261 message.payloadlen = strlen(buf); 00262 00263 //LOG("Publishing %s\n\r", buf); 00264 n_msg++; 00265 pc.printf("Publishing V%s #%d %s\n\r", FW_REV, n_msg, buf); 00266 return client->publish(pubTopic, message); 00267 } 00268 00269 00270 int loop_count = 0; 00271 void test_sens(void); 00272 bool slg_active = false; 00273 00274 int main() 00275 { 00276 uint8_t SL46824_I2C_addr = 0; 00277 const char * apn = APN; // Network must be visible otherwise it can't connect 00278 const char * username = USNAME; 00279 const char * password = PASSW; 00280 SLG46824Interface sl_if(A4, A5); 00281 BG96Interface bg96_if(D8, D2, false); 00282 //sprintf(sensor_id,"%s",bg96_if.get_mac_address()); 00283 //Timer tyeld; 00284 00285 //change serial baud to 115200 00286 pc.baud(115200); 00287 //wait(0.1); 00288 00289 wait(0.5); 00290 00291 slg_active = sl_if.get_i2c_address(&SL46824_I2C_addr); 00292 00293 if(slg_active == true) 00294 { 00295 //sl_if.startup(); //only for debug.. 00296 sl_if.hw_set(); //not needed if SLG46824 already programmed 00297 00298 } 00299 00300 myled=1; 00301 //wait(0.5); 00302 pc.printf("\r\n*************************************************"); 00303 wait( 0.1 ); 00304 pc.printf("\r\nAvnet Silica NbIotBG96 A02 mbed-os application\r\n"); 00305 wait( 0.1 ); 00306 pc.printf("MBED online version %s\r\n", FW_REV); 00307 wait( 0.1 ); 00308 //pc.printf("\r\nwait for APN ready ...\r\n"); 00309 //wait( 0.1 ); 00310 00311 #if SENSOR_ENABLED 00312 /* Enable all sensors */ 00313 hum_temp->enable(); 00314 press_temp->enable(); 00315 //magnetometer->enable(); 00316 //accelerometer->enable(); 00317 //acc_gyro->enable_x(); 00318 //acc_gyro->enable_g(); 00319 #endif 00320 00321 00322 quickstartMode=false; 00323 if (strcmp(org, "quickstart") == 0){quickstartMode = true;} 00324 MQTT_GSM ipstack(bg96_if, apn, username, password); 00325 MQTT::Client<MQTT_GSM, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack); 00326 if (quickstartMode){ 00327 char mac[50]; // remove all : from mac 00328 char *digit=NULL; 00329 sprintf (id,"%s", ""); 00330 sprintf (mac,"%s",ipstack.getGSM().get_mac_address()); 00331 digit = strtok (mac,":"); 00332 while (digit != NULL) 00333 { 00334 strcat (id, digit); 00335 digit = strtok (NULL, ":"); 00336 } 00337 } 00338 attemptConnect(&client, &ipstack); 00339 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) 00340 { 00341 while (true) 00342 wait(1.0); // Permanent failures - don't retry 00343 } 00344 myled=0; 00345 sprintf(sensor_id,"%s",bg96_if.get_mac_address()); 00346 00347 while (true) 00348 { 00349 if (++loop_count == 60) 00350 { 00351 // Publish a message every 30 second 00352 pc.printf("\n"); 00353 myled=1; 00354 if (publish(&client, &ipstack) != 0) { 00355 myled=0; 00356 attemptConnect(&client, &ipstack); // if we have lost the connection 00357 } 00358 //else 00359 myled=0; 00360 loop_count = 0; 00361 } 00362 // int start = tyeld.read_ms(); 00363 client.yield(500); // allow the MQTT client to receive messages 00364 pc.printf ("loop %d\r", (loop_count+1)); //: %d\n\r",tyeld.read_ms()-start); 00365 00366 } 00367 00368 } 00369 00370 00371 00372 00373 /* Helper function for printing floats & doubles */ 00374 static char *print_double(char* str, double v, int decimalDigits=2) 00375 { 00376 int i = 1; 00377 int intPart, fractPart; 00378 int len; 00379 char *ptr; 00380 00381 /* prepare decimal digits multiplicator */ 00382 for (;decimalDigits!=0; i*=10, decimalDigits--); 00383 00384 /* calculate integer & fractinal parts */ 00385 intPart = (int)v; 00386 fractPart = (int)((v-(double)(int)v)*i); 00387 00388 /* fill in integer part */ 00389 sprintf(str, "%i.", intPart); 00390 00391 /* prepare fill in of fractional part */ 00392 len = strlen(str); 00393 ptr = &str[len]; 00394 00395 /* fill in leading fractional zeros */ 00396 for (i/=10;i>1; i/=10, ptr++) { 00397 if (fractPart >= i) { 00398 break; 00399 } 00400 *ptr = '0'; 00401 } 00402 00403 /* fill in (rest of) fractional part */ 00404 sprintf(ptr, "%i", fractPart); 00405 00406 return str; 00407 } 00408 00409 00410 //for testing sensor board ... 00411 void test_sens(void) 00412 { 00413 while(1) 00414 { 00415 00416 float value1, value2; 00417 char buffer1[32], buffer2[32]; 00418 printf("\r\n"); 00419 00420 hum_temp->get_temperature(&value1); 00421 hum_temp->get_humidity(&value2); 00422 printf("HTS221: [temp] %7s C, [hum] %s%%\r\n", print_double(buffer1, value1), print_double(buffer2, value2)); 00423 00424 press_temp->get_temperature(&value1); 00425 press_temp->get_pressure(&value2); 00426 printf("LPS22HB: [temp] %7s C, [press] %s mbar\r\n", print_double(buffer1, value1), print_double(buffer2, value2)); 00427 00428 wait(2); 00429 00430 } 00431 } 00432
Generated on Sat Jul 16 2022 01:36:15 by 1.7.2