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: MQTT NetworkSocketAPI X_NUCLEO_IKS01A2 mbed
Fork of Nucleo_NbIotBG96_A2_cloud_IBM by
main.cpp
- Committer:
- abci5961
- Date:
- 2017-11-20
- Revision:
- 2:b72797c38464
- Parent:
- 1:a622606a49fd
- Child:
- 3:04dbacb98e86
File content as of revision 2:b72797c38464:
/* BG96 NetworkSocketAPI Example Program
* Copyright (c) 2015 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed.h"
#include "BG96Interface.h"
#include "TCPSocket.h"
#include "MQTTClient.h"
#include "MQTT_GSM.h"
#include <ctype.h>
//#include "x_nucleo_iks01a1.h"
#include "XNucleoIKS01A2.h"
#include "BG96.h"
//------------------------------------
// Hyperterminal default configuration
// 9600 bauds, 8-bit data, no parity
//------------------------------------
Serial pc(SERIAL_TX, SERIAL_RX);
DigitalOut myled(LED1);
bool quickstartMode = true;
#define MQTT_MAX_PACKET_SIZE 300
#define MQTT_MAX_PAYLOAD_SIZE 500
#define ORG_QUICKSTART // comment to connect to play.internetofthings.ibmcloud.com
//#define SUBSCRIBE // uncomment to subscribe to broker msgs (not to be used with IBM broker)
// Configuration values needed to connect to IBM IoT Cloud
#define BROKER_URL ".messaging.internetofthings.ibmcloud.com";
#ifdef ORG_QUICKSTART
#define ORG "quickstart" // connect to quickstart.internetofthings.ibmcloud.com/ For a registered connection, replace with your org
#define ID ""
#define AUTH_TOKEN ""
#define DEFAULT_TYPE_NAME "iotsample-mbed-Nucleo"
#define TOPIC "iot-2/evt/status/fmt/json"
#else // not def ORG_QUICKSTART
#define ORG "pvko17" // connect to play.internetofthings.ibmcloud.com/ For a registered connection, replace with your org
#define ID "testtype_112233445566" // For a registered connection, replace with your id
#define AUTH_TOKEN "testtype_112233445566" // For a registered connection, replace with your auth-token
#define DEFAULT_TYPE_NAME "TestType"
#define TOPIC "iot-2/type/TestType/id/testtype_112233445566/evt/status/fmt/json"
#endif
// network credential
#define APN "web.omnitel.it" //VODAFONE apn definition's
//#define APN "internet.wind" //WIND apn definition's
#define PASSW ""
#define USNAME ""
#define TYPE DEFAULT_TYPE_NAME // For a registered connection, replace with your type
#define MQTT_PORT 1883
#define MQTT_TLS_PORT 8883
#define IBM_IOT_PORT MQTT_PORT
char id[30] = ID; // mac without colons
char org[12] = ORG;
int connack_rc = 0; // MQTT connack return code
//const char* ip_addr = "11.12.13.14";
//char* host_addr = "11.12.13.14";
char sensor_id[50];
char type[30] = TYPE;
char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode
bool netConnecting = false;
int connectTimeout = 1000;
bool mqttConnecting = false;
bool netConnected = false;
bool connected = false;
int retryAttempt = 0;
char subscription_url[MQTT_MAX_PAYLOAD_SIZE];
#define SENSOR_ENABLED 1
#define SENSOR_MODEL 2
#define FW_REV "1.0a"
PressureSensor *pressure_sensor;
HumiditySensor *humidity_sensor;
TempSensor *temp_sensor1;
MQTT::Message message;
MQTTString TopicName={TOPIC};
MQTT::MessageData MsgData(TopicName, message);
/* Instantiate the expansion board */
static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);
/* Retrieve the composing elements of the expansion board */
static LSM303AGRMagSensor *magnetometer = mems_expansion_board->magnetometer;
static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
static LPS22HBSensor *press_temp = mems_expansion_board->pt_sensor;
static LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro;
static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer;
void subscribe_cb(MQTT::MessageData & msgMQTT) {
char msg[MQTT_MAX_PAYLOAD_SIZE];
msg[0]='\0';
strncat (msg, (char*)msgMQTT.message.payload, msgMQTT.message.payloadlen);
printf ("--->>> subscribe_cb msg: %s\n\r", msg);
}
int subscribe(MQTT::Client<MQTT_GSM, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTT_GSM* ipstack)
{
char* pubTopic = TOPIC;
return client->subscribe(pubTopic, MQTT::QOS1, subscribe_cb);
}
int connect(MQTT::Client<MQTT_GSM, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTT_GSM* ipstack)
{
const char* iot_ibm = BROKER_URL;
char hostname[strlen(org) + strlen(iot_ibm) + 1];
sprintf(hostname, "%s%s", org, iot_ibm);
// Construct clientId - d:org:type:id
char clientId[strlen(org) + strlen(type) + strlen(id) + 5];
#ifdef ORG_QUICKSTART
sprintf(clientId, "d:%s:%s:%s", org, type, id); //@@
#else
sprintf(clientId, "g:%s:%s:%s", org, type, id); //@@
#endif
sprintf(subscription_url, "%s.%s/#/device/%s/sensor/", org, "internetofthings.ibmcloud.com",id);
netConnecting = true;
ipstack->open(&ipstack->getGSM());
int rc = ipstack->connect(hostname, IBM_IOT_PORT, connectTimeout);
if (rc != 0)
{
//WARN("IP Stack connect returned: %d\n", rc);
return rc;
}
pc.printf ("--->TCP Connected\n\r");
netConnected = true;
netConnecting = false;
// MQTT Connect
mqttConnecting = true;
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.MQTTVersion = 3;
data.struct_version=0;
data.clientID.cstring = clientId;
if (!quickstartMode)
{
data.username.cstring = "use-token-auth";
data.password.cstring = auth_token;
}
if ((rc = client->connect(data)) == 0)
{
connected = true;
pc.printf ("--->MQTT Connected\n\r");
#ifdef SUBSCRIBE
if (!subscribe(client, ipstack)) printf ("--->>>MQTT subscribed to: %s\n\r",TOPIC);
#endif
}
else {
//WARN("MQTT connect returned %d\n", rc);
}
if (rc >= 0)
connack_rc = rc;
mqttConnecting = false;
return rc;
}
int getConnTimeout(int attemptNumber)
{ // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
// after 20 attempts, retry every 10 minutes
return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
}
void attemptConnect(MQTT::Client<MQTT_GSM, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTT_GSM* ipstack)
{
connected = false;
while (connect(client, ipstack) != MQTT_CONNECTION_ACCEPTED)
{
if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
printf ("File: %s, Line: %d Error: %d\n\r",__FILE__,__LINE__, connack_rc);
return; // don't reattempt to connect if credentials are wrong
}
int timeout = getConnTimeout(++retryAttempt);
//WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
// if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
// or maybe just add the proper members to do this disconnect and call attemptConnect(...)
// this works - reset the system when the retry count gets to a threshold
if (retryAttempt == 5){
pc.printf ("\n\n\rFAIL!! system reset!!\n\n\r");
NVIC_SystemReset();
}
else
wait(timeout);
}
}
float hum_global = 50.0;
uint32_t n_msg = 0;
int publish(MQTT::Client<MQTT_GSM, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTT_GSM* ipstack)
{
MQTT::Message message;
char* pubTopic = TOPIC;
char buf[MQTT_MAX_PAYLOAD_SIZE];
float temp, temp1, temp2, press, hum;
#if SENSOR_ENABLED
pc.printf("A02 reading sensors...");
hum_temp->get_temperature(&temp1);
hum_temp->get_humidity(&hum);
press_temp->get_temperature(&temp2);
press_temp->get_pressure(&press);
temp = (temp1+temp2)/2;
pc.printf(" DONE\r\n");
#else
temp=25.5;
hum_global +=0.1;
if (hum_global>99.0)
hum_global = 50.0;
hum=hum_global;
press=999;
#endif
#ifdef ORG_QUICKSTART
sprintf(buf,
"{\"d\":{\"ST\":\"Nucleo-IoT-mbed\",\"Temp\":%0.4f,\"Pressure\":%0.4f,\"Humidity\":%0.4f}}",
temp, press, hum);
#else
sprintf (buf,
"{\"%s\": {\"temp\":%0.4f,\"humidity\":%0.4f,\"pressure\":%0.4f,\"ambient\":0,\"uv\":0,\"accel_X\":0,\"accel_Y\":0,\"accel_Z\":0}}",
sensor_id, temp, hum, press);
#endif
message.qos = MQTT::QOS0;
message.retained = false;
message.dup = false;
message.payload = (void*)buf;
message.payloadlen = strlen(buf);
//LOG("Publishing %s\n\r", buf);
n_msg++;
pc.printf("Publishing V%s #%d %s\n\r", FW_REV, n_msg, buf);
return client->publish(pubTopic, message);
}
int loop_count = 0;
void test_sens(void);
int main()
{
const char * apn = APN; // Network must be visible otherwise it can't connect
const char * username = USNAME;
const char * password = PASSW;
BG96Interface bg96_if(D8, D2, false);
//sprintf(sensor_id,"%s",bg96_if.get_mac_address());
//Timer tyeld;
//change serial baud to 115200
pc.baud(115200);
wait(0.1);
myled=1;
//wait(0.5);
pc.printf("\r\n*************************************************");
wait( 0.1 );
pc.printf("\r\nAvnet Silica NbIotBG96 A02 mbed-os application\r\n");
wait( 0.1 );
pc.printf("MBED online version %s\r\n", FW_REV);
wait( 0.1 );
//pc.printf("\r\nwait for APN ready ...\r\n");
//wait( 0.1 );
#if SENSOR_ENABLED
/* Enable all sensors */
hum_temp->enable();
press_temp->enable();
//magnetometer->enable();
//accelerometer->enable();
//acc_gyro->enable_x();
//acc_gyro->enable_g();
#endif
quickstartMode=false;
if (strcmp(org, "quickstart") == 0){quickstartMode = true;}
MQTT_GSM ipstack(bg96_if, apn, username, password);
MQTT::Client<MQTT_GSM, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);
if (quickstartMode){
char mac[50]; // remove all : from mac
char *digit=NULL;
sprintf (id,"%s", "");
sprintf (mac,"%s",ipstack.getGSM().get_mac_address());
digit = strtok (mac,":");
while (digit != NULL)
{
strcat (id, digit);
digit = strtok (NULL, ":");
}
}
attemptConnect(&client, &ipstack);
if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD)
{
while (true)
wait(1.0); // Permanent failures - don't retry
}
myled=0;
sprintf(sensor_id,"%s",bg96_if.get_mac_address());
while (true)
{
if (++loop_count == 60)
{
// Publish a message every 30 second
pc.printf("\n");
myled=1;
if (publish(&client, &ipstack) != 0) {
myled=0;
attemptConnect(&client, &ipstack); // if we have lost the connection
}
//else
myled=0;
loop_count = 0;
}
// int start = tyeld.read_ms();
client.yield(500); // allow the MQTT client to receive messages
pc.printf ("loop %d\r", (loop_count+1)); //: %d\n\r",tyeld.read_ms()-start);
}
}
/* Helper function for printing floats & doubles */
static char *print_double(char* str, double v, int decimalDigits=2)
{
int i = 1;
int intPart, fractPart;
int len;
char *ptr;
/* prepare decimal digits multiplicator */
for (;decimalDigits!=0; i*=10, decimalDigits--);
/* calculate integer & fractinal parts */
intPart = (int)v;
fractPart = (int)((v-(double)(int)v)*i);
/* fill in integer part */
sprintf(str, "%i.", intPart);
/* prepare fill in of fractional part */
len = strlen(str);
ptr = &str[len];
/* fill in leading fractional zeros */
for (i/=10;i>1; i/=10, ptr++) {
if (fractPart >= i) {
break;
}
*ptr = '0';
}
/* fill in (rest of) fractional part */
sprintf(ptr, "%i", fractPart);
return str;
}
//for testing sensor board ...
void test_sens(void)
{
while(1)
{
float value1, value2;
char buffer1[32], buffer2[32];
printf("\r\n");
hum_temp->get_temperature(&value1);
hum_temp->get_humidity(&value2);
printf("HTS221: [temp] %7s C, [hum] %s%%\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
press_temp->get_temperature(&value1);
press_temp->get_pressure(&value2);
printf("LPS22HB: [temp] %7s C, [press] %s mbar\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
wait(2);
}
}
