Published project at https://os.mbed.com/users/vlasov01/code/Watson-IoT-MQTT-WiFi-MEMS/
Dependencies: Watson-IoT-MQTT-WiFi-MEMS NDefLib NetworkSocketAPI X_NUCLEO_IDW01M1v2 X_NUCLEO_IKS01A2 mbed
main.cpp
- Committer:
- vlasov01
- Date:
- 2017-11-07
- Revision:
- 1:cc2d7fc65713
- Parent:
- 0:a17fde465867
File content as of revision 1:cc2d7fc65713:
/* SpwfInterface 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 "SpwfInterface.h" #include "TCPSocket.h" #include "MQTTClient.h" #include "MQTTWiFi.h" #include <ctype.h> #include "XNucleoIKS01A2.h" //#include "x_nucleo_iks01a1.h" //#include "X_NUCLEO_NFC01A1.h" #include "NDefLib/NDefNfcTag.h" #include "NDefLib/RecordType/RecordURI.h" //------------------------------------ // Hyperterminal configuration // 9600 bauds, 8-bit data, no parity //------------------------------------ Serial pc(SERIAL_TX, SERIAL_RX); DigitalOut myled(LED1); bool quickstartMode = true; #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) //#define X_NUCLEO_NFC01A1_PRESENT // uncomment to add NFC support #define MQTT_MAX_PACKET_SIZE 250 #define MQTT_MAX_PAYLOAD_SIZE 300 // 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" #else // not def ORG_QUICKSTART #define ORG "play" // connect to play.internetofthings.ibmcloud.com/ For a registered connection, replace with your org #define ID "" // For a registered connection, replace with your id #define AUTH_TOKEN ""// For a registered connection, replace with your auth-token #define DEFAULT_TYPE_NAME "sensor" #endif #define TOPIC "iot-2/evt/status/fmt/json" #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 // WiFi network credential #define SSID "" // Network must be visible otherwise it can't connect #define PASSW "" #warning "Wifi SSID & password empty" char id[30] = ID; // mac without colons char org[12] = ORG; int connack_rc = 0; // MQTT connack return code const char* ip_addr = ""; char* host_addr = ""; 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]; /* PressureSensor *pressure_sensor; HumiditySensor *humidity_sensor; TempSensor *temp_sensor1; */ /* 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; InterruptIn mybutton(USER_BUTTON); volatile int mems_event = 0; volatile int toggle_hw_event_enable = 0; static int hw_event_is_enabled = 1; uint16_t step_count = 0; /* User button callback. */ void pressed_cb() { toggle_hw_event_enable = 1; } /* Interrupt 1 callback. */ void int1_cb() { mems_event = 1; } /* Interrupt 2 callback. */ void int2_cb() { mems_event = 1; } /* Print the orientation. */ void send_orientation() { uint8_t xl = 0; uint8_t xh = 0; uint8_t yl = 0; uint8_t yh = 0; uint8_t zl = 0; uint8_t zh = 0; acc_gyro->get_6d_orientation_xl(&xl); acc_gyro->get_6d_orientation_xh(&xh); acc_gyro->get_6d_orientation_yl(&yl); acc_gyro->get_6d_orientation_yh(&yh); acc_gyro->get_6d_orientation_zl(&zl); acc_gyro->get_6d_orientation_zh(&zh); if ( xl == 0 && yl == 0 && zl == 0 && xh == 0 && yh == 1 && zh == 0 ) { printf( "\r\n ________________ " \ "\r\n | | " \ "\r\n | * | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n |________________| \r\n" ); } else if ( xl == 1 && yl == 0 && zl == 0 && xh == 0 && yh == 0 && zh == 0 ) { printf( "\r\n ________________ " \ "\r\n | | " \ "\r\n | * | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 0 && zl == 0 && xh == 1 && yh == 0 && zh == 0 ) { printf( "\r\n ________________ " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | * | " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 1 && zl == 0 && xh == 0 && yh == 0 && zh == 0 ) { printf( "\r\n ________________ " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | | " \ "\r\n | * | " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 0 && zl == 0 && xh == 0 && yh == 0 && zh == 1 ) { printf( "\r\n __*_____________ " \ "\r\n |________________| \r\n" ); } else if ( xl == 0 && yl == 0 && zl == 1 && xh == 0 && yh == 0 && zh == 0 ) { printf( "\r\n ________________ " \ "\r\n |________________| " \ "\r\n * \r\n" ); } else { printf( "None of the 6D orientation axes is set in LSM6DSL - accelerometer.\r\n" ); } } MQTT::Message message; MQTTString TopicName={TOPIC}; MQTT::MessageData MsgData(TopicName, message); 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<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack) { char* pubTopic = TOPIC; return client->subscribe(pubTopic, MQTT::QOS1, subscribe_cb); } int connect(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack) { const char* iot_ibm = BROKER_URL; char hostname[strlen(org) + strlen(iot_ibm) + 1]; sprintf(hostname, "%s%s", org, iot_ibm); SpwfSAInterface& WiFi = ipstack->getWiFi(); // ip_addr = WiFi.get_ip_address(); // Construct clientId - d:org:type:id char clientId[strlen(org) + strlen(type) + strlen(id) + 5]; sprintf(clientId, "d:%s:%s:%s", org, type, id); sprintf(subscription_url, "%s.%s/#/device/%s/sensor/", org, "internetofthings.ibmcloud.com",id); // Network debug statements LOG("=====================================\n\r"); LOG("Connecting WiFi.\n\r"); LOG("Nucleo IP ADDRESS: %s\n\r", WiFi.get_ip_address()); LOG("Nucleo MAC ADDRESS: %s\n\r", WiFi.get_mac_address()); LOG("Server Hostname: %s port: %d\n\r", hostname, IBM_IOT_PORT); // for(int i = 0; clientId[i]; i++){ // set lowercase mac // clientId[i] = tolower(clientId[i]); // } LOG("Client ID: %s\n\r", clientId); LOG("Topic: %s\n\r",TOPIC); LOG("Subscription URL: %s\n\r", subscription_url); LOG("=====================================\n\r"); netConnecting = true; ipstack->open(&ipstack->getWiFi()); int rc = ipstack->connect(hostname, IBM_IOT_PORT, connectTimeout); if (rc != 0) { WARN("IP Stack connect returned: %d\n", rc); return rc; } printf ("--->TCP Connected\n\r"); netConnected = true; netConnecting = false; // MQTT Connect mqttConnecting = true; MQTTPacket_connectData data = MQTTPacket_connectData_initializer; data.MQTTVersion = 4; 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; 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<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* 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) NVIC_SystemReset(); else wait(timeout); } } int publish(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack) { MQTT::Message message; char* pubTopic = TOPIC; char buf[MQTT_MAX_PAYLOAD_SIZE]; float temp, press, hum; LSM6DSL_Event_Status_t status; if (mems_event) { mems_event = 0; acc_gyro->get_event_status(&status); if (status.StepStatus) { /* New step detected, so print the step counter */ acc_gyro->get_step_counter(&step_count); printf("Step counter: %d\r\n", step_count); } if (status.FreeFallStatus) { /* Output data. */ printf("Free Fall Detected!\r\n"); } if (status.TapStatus) { /* Output data. */ printf("Single Tap Detected!\r\n"); } if (status.DoubleTapStatus) { /* Output data. */ printf("Double Tap Detected!\r\n"); } if (status.D6DOrientationStatus) { /* Send 6D Orientation */ send_orientation(); } if (status.TiltStatus) { /* Output data. */ printf("Tilt Detected!\r\n"); } if (status.WakeUpStatus) { /* Output data. */ printf("Wake Up Detected!\r\n"); } } if (toggle_hw_event_enable) { toggle_hw_event_enable = 0; if (hw_event_is_enabled == 0) { /* Enable HW events. */ acc_gyro->enable_pedometer(); acc_gyro->enable_tilt_detection(); acc_gyro->enable_free_fall_detection(); acc_gyro->enable_single_tap_detection(); acc_gyro->enable_double_tap_detection(); acc_gyro->enable_6d_orientation(); acc_gyro->enable_wake_up_detection(); hw_event_is_enabled = 1; } else { acc_gyro->disable_pedometer(); acc_gyro->disable_tilt_detection(); acc_gyro->disable_free_fall_detection(); acc_gyro->disable_single_tap_detection(); acc_gyro->disable_double_tap_detection(); acc_gyro->disable_6d_orientation(); acc_gyro->disable_wake_up_detection(); hw_event_is_enabled = 0; } } hum_temp->get_temperature(&temp); //press_temp->get_temperature(&temp); hum_temp->get_humidity(&hum); press_temp->get_pressure(&press); sprintf(buf, "{\"d\":{\"ST\":\"Nucleo-IoT-mbed\",\"Temp\":%0.4f,\"Pressure\":%0.4f,\"Humidity\":%0.4f,\"FreeFall\":%i,\"DoubleTap\":%i,\"TiltStatus\":%i}}", temp, press, hum, status.FreeFallStatus, status.DoubleTapStatus, status.TiltStatus); message.qos = MQTT::QOS0; message.retained = false; message.dup = false; message.payload = (void*)buf; message.payloadlen = strlen(buf); // LOG("Publishing %s\n\r", buf); printf("Publishing %s\n\r", buf); return client->publish(pubTopic, message); } void initSensors(){ // A2 start uint8_t id; //float value1, value2; //char buffer1[32], buffer2[32]; //int32_t axes[3]; /* Enable all sensors */ hum_temp->enable(); press_temp->enable(); magnetometer->enable(); accelerometer->enable(); acc_gyro->enable_x(); acc_gyro->enable_g(); printf("\r\n--- Starting new run ---\r\n"); hum_temp->read_id(&id); printf("HTS221 humidity & temperature = 0x%X\r\n", id); press_temp->read_id(&id); printf("LPS22HB pressure & temperature = 0x%X\r\n", id); magnetometer->read_id(&id); printf("LSM303AGR magnetometer = 0x%X\r\n", id); accelerometer->read_id(&id); printf("LSM303AGR accelerometer = 0x%X\r\n", id); acc_gyro->read_id(&id); printf("LSM6DSL accelerometer & gyroscope = 0x%X\r\n", id); // A2 end } int main() { /* Attach callback to User button press */ mybutton.fall(&pressed_cb); /* Attach callback to LSM6DSL INT1 */ acc_gyro->attach_int1_irq(&int1_cb); /* Attach callback to LSM6DSL INT2 */ acc_gyro->attach_int2_irq(&int2_cb); /* Enable LSM6DSL accelerometer */ acc_gyro->enable_x(); /* Enable HW events. */ acc_gyro->enable_pedometer(); acc_gyro->enable_tilt_detection(); acc_gyro->enable_free_fall_detection(); acc_gyro->enable_single_tap_detection(); acc_gyro->enable_double_tap_detection(); acc_gyro->enable_6d_orientation(); acc_gyro->enable_wake_up_detection(); const char * ssid = SSID; // Network must be visible otherwise it can't connect const char * seckey = PASSW; SpwfSAInterface spwf(D8, D2, false); // Timer tyeld; myled=0; DevI2C *i2c = new DevI2C(I2C_SDA, I2C_SCL); i2c->frequency(400000); //X_NUCLEO_IKS01A2 initSensors(); /* X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(i2c); pressure_sensor = mems_expansion_board->pt_sensor; temp_sensor1 = mems_expansion_board->ht_sensor; humidity_sensor = mems_expansion_board->ht_sensor; */ pc.printf("\r\nX-NUCLEO-IDW01M1 mbed Application\r\n"); pc.printf("\r\nconnecting to AP\r\n"); quickstartMode=false; if (strcmp(org, "quickstart") == 0){quickstartMode = true;} MQTTWiFi ipstack(spwf, ssid, seckey, NSAPI_SECURITY_WPA2); MQTT::Client<MQTTWiFi, 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.getWiFi().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 } #ifdef X_NUCLEO_NFC01A1_PRESENT // program NFC with broker URL X_NUCLEO_NFC01A1 *nfcNucleo = X_NUCLEO_NFC01A1::Instance(*i2c, NULL, X_NUCLEO_NFC01A1::DEFAULT_GPO_PIN, X_NUCLEO_NFC01A1::DEFAULT_RF_DISABLE_PIN, NC,NC,NC); NDefLib::NDefNfcTag& tag = nfcNucleo->getM24SR().getNDefTag(); printf("NFC Init done: !\r\n"); //open the i2c session with the nfc chip if(tag.openSession()){ //create the NDef message and record NDefLib::Message msg; NDefLib::RecordURI rUri(NDefLib::RecordURI::HTTPS, subscription_url); msg.addRecord(&rUri); //write the tag if(tag.write(msg)){ printf("Tag writed \r\n"); } //close the i2c session if(!tag.closeSession()){ printf("Error Closing the session\r\n"); } }else printf("Error open Session\r\n"); #endif myled=1; int count = 0; // tyeld.start(); while (true) { if (++count == 100) { // Publish a message every second if (publish(&client, &ipstack) != 0) { myled=0; attemptConnect(&client, &ipstack); // if we have lost the connection } else myled=1; count = 0; } // int start = tyeld.read_ms(); client.yield(10); // allow the MQTT client to receive messages // printf ("tyeld: %d\n\r",tyeld.read_ms()-start); } }