An mbed BLE-to-Cloud Gateway using Nucleo-F429ZI+X-Nucleo-IDB05A1 or Nucleo-L476RG+X-Nucleo-IDB05A1+X-Nucleo-IDW01M1.

Information

Nucleo- F429ZI configuration requires two hardware patches:

  1. on Nucleo-F429ZI open SB121 and close SB122
  2. on X-Nucleo-IDB05A1 move R4 to R6

The BLE client searches for and connects to a MotEnv node.

Revision:
1:d9c0c4889bd2
Parent:
0:c7083010ae49
Child:
3:39c8d17bed52
--- a/main.cpp	Thu Oct 12 13:58:45 2017 +0200
+++ b/main.cpp	Thu Oct 12 17:28:58 2017 +0200
@@ -21,6 +21,10 @@
 #include <vector>
 #include "mbed-trace/mbed_trace.h"
 #include "mbedtls/entropy_poll.h"
+#include "ble\BLE.h"
+#include "ble\DiscoveredCharacteristic.h"
+#include "ble\DiscoveredService.h"
+
 
 #include "security.h"
 
@@ -29,6 +33,8 @@
 // easy-connect compliancy, it has 2 sets of wifi pins we have only one
 #define MBED_CONF_APP_ESP8266_TX MBED_CONF_APP_WIFI_TX
 #define MBED_CONF_APP_ESP8266_RX MBED_CONF_APP_WIFI_RX
+#define MBED_CFG_SPWF01SA_TX MBED_CONF_APP_WIFI_TX
+#define MBED_CFG_SPWF01SA_RX MBED_CONF_APP_WIFI_RX
 #include "easy-connect/easy-connect.h"
 
 #ifdef TARGET_STM
@@ -49,11 +55,221 @@
 DigitalOut green_led(GREEN_LED);
 DigitalOut blue_led(BLUE_LED);
 
-Ticker status_ticker;
-void blinky() {
-    green_led = !green_led;
+
+/************************************************************BLE Stuff from here *********************************/
+
+BLE &ble = BLE::Instance();
+static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
+Thread BLE_thread;
+static bool triggerEnvCharacteristic;
+static bool envDataAvailable = false;
+static DiscoveredCharacteristic envCharacteristic;
+uint16_t payload_length = 0;
+uint8_t dataforClient[12];
+
+void BLEConnect(BLEProtocol::AddressBytes_t address) {
+	BLE::Instance().gap().connect(address, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+}
+
+
+void advertisementCallback(const Gap::AdvertisementCallbackParams_t *params) {
+    // parse the advertising payload, looking for data type MANUFACTURER_SPECIFIC_DATA
+    // The advertising payload is a collection of key/value records where
+    // byte 0: length of the record excluding this byte
+    // byte 1: The key, it is the type of the data
+    // byte [2..N] The value. N is equal to byte0 - 1
+	
+	//printf("Starting advertisementCallback...\r\n");
+	
+    for (uint8_t i = 0; i < params->advertisingDataLen; ++i) {
+
+        const uint8_t record_length = params->advertisingData[i];
+        if (record_length == 0) {
+            continue;
+        }
+        const uint8_t type = params->advertisingData[i + 1];
+        const uint8_t* value = params->advertisingData + i + 2;
+        const uint8_t value_length = record_length - 1;
+		
+		if(type == GapAdvertisingData::COMPLETE_LOCAL_NAME) {
+			char devName[16];
+			int strLength = value_length > 15 ? 15 : value_length;
+			memcpy (devName, value, strLength);
+			devName[strLength] = '\0';
+			printf("Found a device with name: %s\n\r", devName);
+			
+			if (memcmp(value, "BlueMbedOS", value_length) == 0) {
+				printf("Found an mbed device node\n");
+				BLEProtocol::AddressBytes_t devAddress;
+			    memcpy (devAddress, params->peerAddr,BLEProtocol::ADDR_LEN);
+				eventQueue.call(BLEConnect,devAddress);
+				break;
+			}
+		}
+/*
+        if(type == GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA) {
+			printf("length: %d - mask: 0x%x\n\r", value_length, *((uint32_t*)(value+2)));
+            if (((value_length == 6) || (value_length == 12)) && (*((uint32_t*)(value+2)) & 0x00001C00) == 0x00001C00) {
+                printf("Found an ST device with environmental data\n");
+                //BLE::Instance().gap().connect(params->peerAddr, Gap::ADDR_TYPE_RANDOM_STATIC, NULL, NULL);
+				BLEProtocol::AddressBytes_t devAddress;
+			    memcpy (devAddress, params->peerAddr,BLEProtocol::ADDR_LEN);
+				eventQueue.call(BLEConnect,devAddress);
+                break;
+            } 
+        }
+*/
+        i += record_length;
+    } 
+}
+
+void serviceDiscoveryCallback(const DiscoveredService *service) {
+	
+    if (service->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) {
+        printf("S UUID-%x attrs[%u %u]\r\n", service->getUUID().getShortUUID(), service->getStartHandle(), service->getEndHandle());
+    } else {
+        printf("S UUID-");
+        const uint8_t *longUUIDBytes = service->getUUID().getBaseUUID();
+        for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
+            printf("%02x", longUUIDBytes[i]);
+        }
+        printf(" attrs[%u %u]\r\n", service->getStartHandle(), service->getEndHandle());
+    }
+}
+
+//read data from BLE
+void updateEnvCharacteristic(void) {
+	if (!BLE::Instance().gattClient().isServiceDiscoveryActive()) {
+		//printf("Reading environmental data\n\n");
+        envCharacteristic.read();
+		envDataAvailable = true;
+    } else {
+		envDataAvailable = false;
+	}
+	
+}
+
+
+void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
+	/*
+    printf("  C UUID-%x valueAttr[%u] props[%x]\r\n", characteristicP->getUUID().getShortUUID(), characteristicP->getValueHandle(), (uint8_t)characteristicP->getProperties().broadcast());
+    if (characteristicP->getUUID().getShortUUID() == 0xA001) { /* !ALERT! Alter this filter to suit your device. */
+    /*    optCharacteristic        = *characteristicP;
+        triggerLedCharacteristic = true;
+	}*/
+	printf("Found environmental data\n");
+	envCharacteristic        = *characteristicP;
+	triggerEnvCharacteristic = true;
 }
 
+void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
+	
+    //printf("terminated SD for handle %u\r\n", connectionHandle);
+	
+    if (triggerEnvCharacteristic) {
+        triggerEnvCharacteristic = false;
+        eventQueue.call(updateEnvCharacteristic);
+    } 
+}
+
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
+	printf("Connected to ST Node now...\r\n");
+    if (params->role == Gap::CENTRAL) {
+        BLE &ble = BLE::Instance();
+        ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
+		const char *servUUIDString = "00000000-0001-11e1-9ab4-0002a5d5c51b";
+		UUID servUUID(servUUIDString);
+		const char *charUUIDString = "001c0000-0001-11e1-ac36-0002a5d5c51b";
+		UUID charUUID(charUUIDString);
+        ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, servUUID, charUUID);
+    }
+}
+
+
+void triggerRead(const GattReadCallbackParams *response) {
+	
+	if (response->handle == envCharacteristic.getValueHandle()) {
+		payload_length = response-> len;
+		for(int i=0; i< response-> len; i++) {
+//			printf("%02x", response->data[i]);
+			dataforClient[i] = response -> data[i];
+	//		printf("%d", dataforClient[i]);
+		}
+	
+		//printf("Temperature: %f\r\n", (uint32_t)((dataforClient[9]<<8) | dataforClient[8])/10.0);
+		//printf("Humidity: %f\r\n", (uint32_t)((dataforClient[7]<<8) | dataforClient[6])/10.0);
+		//printf("Pressure: %f\r\n\r\n\r\n", (uint32_t)((dataforClient[5]<<24) |(dataforClient[4]<<16) |(dataforClient[3]<<8) | dataforClient[2])/100.0);
+		
+		eventQueue.call(updateEnvCharacteristic);  // triggering BLE data read again
+    } 
+}
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *) {
+    printf("Got disconnected from the device!\r\n");
+    /* Start scanning and try to connect again */
+    BLE::Instance().gap().startScan(advertisementCallback);
+}
+
+void onBleInitError(BLE &ble, ble_error_t error)
+{
+   /* Initialization error handling should go here */
+	printf("BLE Error = %u\r\n", error);
+}
+
+void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
+{
+	//printf("I'm inside BLE init\r\n");
+    BLE&        ble   = params->ble;
+    ble_error_t error = params->error;
+	ble_error_t error1 = params->error;
+
+    if (error != BLE_ERROR_NONE) {
+        /* In case of error, forward the error handling to onBleInitError */
+        onBleInitError(ble, error);			
+        return;
+    }
+		
+   /* Ensure that it is the default instance of BLE */
+    if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
+			printf("Not the default instance\r\n");
+        return;
+    }
+
+	ble.gap().onDisconnection(disconnectionCallback);
+	ble.gap().onConnection(connectionCallback);
+
+// On reading data, call triggerRead function.
+    ble.gattClient().onDataRead(triggerRead);
+		
+		// scan interval: 400ms and scan window: 400ms.
+    // Every 400ms the device will scan for 400ms
+    // This means that the device will scan continuously.
+    ble.gap().setScanParams(400, 400);
+    error =   ble.gap().startScan(advertisementCallback);
+	if (error) {
+		printf("BLE Error startScan = %u\r\n", error);
+	}
+		
+}
+
+void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
+    BLE &ble = BLE::Instance();
+    eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
+}
+
+//BLE thread init and further calls to other BLE methods.
+void BLE_thread_init(void){
+	//printf("I'm inside BLE thread.....\r\n");
+
+//Schedule events before starting the thread since there might be some missed events while scanning / pairing.
+	ble.onEventsToProcess(scheduleBleEventsProcessing);
+	ble.init(bleInitComplete);
+//Loop forever the BLE thread
+	eventQueue.dispatch_forever();
+}
+
+/************************************************************BLE Stuff to here *********************************/
+
 // These are example resource values for the Device Object
 struct MbedClientDevice device = {
     "Manufacturer_String",      // Manufacturer
@@ -66,266 +282,109 @@
 MbedClient mbed_client(device);
 
 
-// In case of K64F board , there is button resource available
-// to change resource value and unregister
-#ifdef TARGET_K64F
-// Set up Hardware interrupt button.
-InterruptIn obs_button(SW2);
-InterruptIn unreg_button(SW3);
-#else
-//In non K64F boards , set up a timer to simulate updating resource,
-// there is no functionality to unregister.
-Ticker timer;
-#endif
+class EnvResource {
+public:
+	EnvResource() {
+		
+        temp_object = M2MInterfaceFactory::create_object("3303");
+        temp_inst = temp_object->create_object_instance();
+        temp_res = temp_inst->create_dynamic_resource("5700", "Temperature",
+            M2MResourceInstance::FLOAT, true);	// observable
+        // we can only read this value
+	    temp_res->set_operation(M2MBase::GET_ALLOWED);
+		temp_res->set_value((uint8_t*)"20.0", 4);
+		
+		hum_object = M2MInterfaceFactory::create_object("3304");
+        hum_inst = hum_object->create_object_instance();
+        hum_res = hum_inst->create_dynamic_resource("5700", "Humidity",
+            M2MResourceInstance::FLOAT, true);	// observable
+        // we can only read this value
+	    hum_res->set_operation(M2MBase::GET_ALLOWED);
+		hum_res->set_value((uint8_t*)"50.0", 4);
+		
+		press_object = M2MInterfaceFactory::create_object("3300");
+        press_inst = press_object->create_object_instance();
+        press_res = press_inst->create_dynamic_resource("5700", "Pressure",
+            M2MResourceInstance::FLOAT, true);	// observable
+        // we can only read this value
+	    press_res->set_operation(M2MBase::GET_ALLOWED);
+		press_res->set_value((uint8_t*)"1000", 4);
+		
+        timer_res = press_inst->create_dynamic_resource("5603", "PollingPeriodMs",  // one polling time for all env values, associated to humidity
+		    M2MResourceInstance::INTEGER, false);	// not observable
+        // we can read/wr this value
+	    timer_res->set_operation(M2MBase::GET_PUT_ALLOWED);
+        timer_res->set_value((uint8_t*)"1000",4); // default 1s polling
+		
+	}
+	
+	M2MObject* get_temp_object() {
+        return temp_object;
+	}
+	
+	M2MObject* get_hum_object() {
+        return hum_object;
+	}
+	
+	M2MObject* get_press_object() {
+        return press_object;
+	}
+	
+	int get_polling_period() {
+		return timer_res->get_value_int();
+	}
 
-/*
- * Arguments for running "blink" in it's own thread.
- */
-class BlinkArgs {
-public:
-    BlinkArgs() {
-        clear();
-    }
-    void clear() {
-        position = 0;
-        blink_pattern.clear();
-    }
-    uint16_t position;
-    std::vector<uint32_t> blink_pattern;
+	void update_resources() {
+	   float temp;
+	   float hum;
+	   float press;
+	  
+      if (!envDataAvailable) {
+		  return;
+	  }
+	  
+	  temp = (uint32_t)((dataforClient[9]<<8) | dataforClient[8])/10.0;
+	  hum = ((dataforClient[7]<<8) | dataforClient[6])/10.0;
+	  press = (uint32_t)((dataforClient[5]<<24) |(dataforClient[4]<<16) |(dataforClient[3]<<8) | dataforClient[2])/100.0;
+	  
+	  stringstream ss_temp;
+	  ss_temp << temp;
+      std::string stringified = ss_temp.str();
+      temp_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
+	  
+	  stringstream ss_hum;
+	  ss_hum << hum;
+      stringified = ss_hum.str();
+      hum_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
+	  
+	  stringstream ss_press;
+	  ss_press << press;
+      stringified = ss_press.str();
+      press_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
+	  
+   }
+	
+private:
+
+   M2MObject* temp_object;
+   M2MObjectInstance* temp_inst;
+   M2MResource* temp_res;
+   
+   M2MObject* hum_object;
+   M2MObjectInstance* hum_inst;
+   M2MResource* hum_res;
+   
+   M2MObject* press_object;
+   M2MObjectInstance* press_inst;
+   M2MResource* press_res;
+   
+   M2MResource* timer_res;
+	
 };
 
-/*
- * The Led contains one property (pattern) and a function (blink).
- * When the function blink is executed, the pattern is read, and the LED
- * will blink based on the pattern.
- */
-class LedResource {
-public:
-    LedResource() {
-        // create ObjectID with metadata tag of '3201', which is 'digital output'
-        led_object = M2MInterfaceFactory::create_object("3201");
-        M2MObjectInstance* led_inst = led_object->create_object_instance();
 
-        // 5853 = Multi-state output
-        M2MResource* pattern_res = led_inst->create_dynamic_resource("5853", "Pattern",
-            M2MResourceInstance::STRING, false);
-        // read and write
-        pattern_res->set_operation(M2MBase::GET_PUT_ALLOWED);
-        // set initial pattern (toggle every 200ms. 7 toggles in total)
-        pattern_res->set_value((const uint8_t*)"500:500:500:500:500:500:500", 27);
-
-        // there's not really an execute LWM2M ID that matches... hmm...
-        M2MResource* led_res = led_inst->create_dynamic_resource("5850", "Blink",
-            M2MResourceInstance::OPAQUE, false);
-        // we allow executing a function here...
-        led_res->set_operation(M2MBase::POST_ALLOWED);
-        // when a POST comes in, we want to execute the led_execute_callback
-        led_res->set_execute_function(execute_callback(this, &LedResource::blink));
-        // Completion of execute function can take a time, that's why delayed response is used
-        led_res->set_delayed_response(true);
-        blink_args = new BlinkArgs();
-    }
-
-    ~LedResource() {
-        delete blink_args;
-    }
-
-    M2MObject* get_object() {
-        return led_object;
-    }
-
-    void blink(void *argument) {
-        // read the value of 'Pattern'
-        status_ticker.detach();
-        green_led = LED_OFF;
-
-        M2MObjectInstance* inst = led_object->object_instance();
-        M2MResource* res = inst->resource("5853");
-        // Clear previous blink data
-        blink_args->clear();
-
-        // values in mbed Client are all buffers, and we need a vector of int's
-        uint8_t* buffIn = NULL;
-        uint32_t sizeIn;
-        res->get_value(buffIn, sizeIn);
-
-        // turn the buffer into a string, and initialize a vector<int> on the heap
-        std::string s((char*)buffIn, sizeIn);
-        free(buffIn);
-        printf("led_execute_callback pattern=%s\n", s.c_str());
-
-        // our pattern is something like 500:200:500, so parse that
-        std::size_t found = s.find_first_of(":");
-        while (found!=std::string::npos) {
-            blink_args->blink_pattern.push_back(atoi((const char*)s.substr(0,found).c_str()));
-            s = s.substr(found+1);
-            found=s.find_first_of(":");
-            if(found == std::string::npos) {
-                blink_args->blink_pattern.push_back(atoi((const char*)s.c_str()));
-            }
-        }
-        // check if POST contains payload
-        if (argument) {
-            M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument;
-            String object_name = param->get_argument_object_name();
-            uint16_t object_instance_id = param->get_argument_object_instance_id();
-            String resource_name = param->get_argument_resource_name();
-            int payload_length = param->get_argument_value_length();
-            uint8_t* payload = param->get_argument_value();
-            printf("Resource: %s/%d/%s executed\n", object_name.c_str(), object_instance_id, resource_name.c_str());
-            printf("Payload: %.*s\n", payload_length, payload);
-        }
-        // do_blink is called with the vector, and starting at -1
-        blinky_thread.start(callback(this, &LedResource::do_blink));
-    }
-
-private:
-    M2MObject* led_object;
-    Thread blinky_thread;
-    BlinkArgs *blink_args;
-    void do_blink() {
-        for (;;) {
-            // blink the LED
-            red_led = !red_led;
-            // up the position, if we reached the end of the vector
-            if (blink_args->position >= blink_args->blink_pattern.size()) {
-                // send delayed response after blink is done
-                M2MObjectInstance* inst = led_object->object_instance();
-                M2MResource* led_res = inst->resource("5850");
-                led_res->send_delayed_post_response();
-                red_led = LED_OFF;
-                status_ticker.attach_us(blinky, 250000);
-                return;
-            }
-            // Wait requested time, then continue prosessing the blink pattern from next position.
-            Thread::wait(blink_args->blink_pattern.at(blink_args->position));
-            blink_args->position++;
-        }
-    }
-};
-
-/*
- * The button contains one property (click count).
- * When `handle_button_click` is executed, the counter updates.
- */
-class ButtonResource {
-public:
-    ButtonResource(): counter(0) {
-        // create ObjectID with metadata tag of '3200', which is 'digital input'
-        btn_object = M2MInterfaceFactory::create_object("3200");
-        M2MObjectInstance* btn_inst = btn_object->create_object_instance();
-        // create resource with ID '5501', which is digital input counter
-        M2MResource* btn_res = btn_inst->create_dynamic_resource("5501", "Button",
-            M2MResourceInstance::INTEGER, true /* observable */);
-        // we can read this value
-        btn_res->set_operation(M2MBase::GET_ALLOWED);
-        // set initial value (all values in mbed Client are buffers)
-        // to be able to read this data easily in the Connector console, we'll use a string
-        btn_res->set_value((uint8_t*)"0", 1);
-    }
-
-    ~ButtonResource() {
-    }
-
-    M2MObject* get_object() {
-        return btn_object;
-    }
-
-    /*
-     * When you press the button, we read the current value of the click counter
-     * from mbed Device Connector, then up the value with one.
-     */
-    void handle_button_click() {
-        if (mbed_client.register_successful()) {
-            M2MObjectInstance* inst = btn_object->object_instance();
-            M2MResource* res = inst->resource("5501");
-
-            // up counter
-            counter++;
-    #ifdef TARGET_K64F
-            printf("handle_button_click, new value of counter is %d\n", counter);
-    #else
-            printf("simulate button_click, new value of counter is %d\n", counter);
-    #endif
-            // serialize the value of counter as a string, and tell connector
-            char buffer[20];
-            int size = sprintf(buffer,"%d",counter);
-            res->set_value((uint8_t*)buffer, size);
-        } else {
-            printf("simulate button_click, device not registered\n");
-        }
-    }
-
-private:
-    M2MObject* btn_object;
-    uint16_t counter;
-};
-
-class BigPayloadResource {
-public:
-    BigPayloadResource() {
-        big_payload = M2MInterfaceFactory::create_object("1000");
-        M2MObjectInstance* payload_inst = big_payload->create_object_instance();
-        M2MResource* payload_res = payload_inst->create_dynamic_resource("1", "BigData",
-            M2MResourceInstance::STRING, true /* observable */);
-        payload_res->set_operation(M2MBase::GET_PUT_ALLOWED);
-        payload_res->set_value((uint8_t*)"0", 1);
-        payload_res->set_incoming_block_message_callback(
-                    incoming_block_message_callback(this, &BigPayloadResource::block_message_received));
-        payload_res->set_outgoing_block_message_callback(
-                    outgoing_block_message_callback(this, &BigPayloadResource::block_message_requested));
-    }
-
-    M2MObject* get_object() {
-        return big_payload;
-    }
-
-    void block_message_received(M2MBlockMessage *argument) {
-        if (argument) {
-            if (M2MBlockMessage::ErrorNone == argument->error_code()) {
-                if (argument->is_last_block()) {
-                    printf("Last block received\n");
-                }
-                printf("Block number: %d\n", argument->block_number());
-                // First block received
-                if (argument->block_number() == 0) {
-                    // Store block
-                // More blocks coming
-                } else {
-                    // Store blocks
-                }
-            } else {
-                printf("Error when receiving block message!  - EntityTooLarge\n");
-            }
-            printf("Total message size: %" PRIu32 "\n", argument->total_message_size());
-        }
-    }
-
-    void block_message_requested(const String& resource, uint8_t *&/*data*/, uint32_t &/*len*/) {
-        printf("GET request received for resource: %s\n", resource.c_str());
-        // Copy data and length to coap response
-    }
-
-private:
-    M2MObject*  big_payload;
-};
-
-// Network interaction must be performed outside of interrupt context
-Semaphore updates(0);
-volatile bool registered = false;
-volatile bool clicked = false;
 osThreadId mainThread;
 
-void unregister() {
-    registered = false;
-    updates.release();
-}
-
-void button_clicked() {
-    clicked = true;
-    updates.release();
-}
-
 // Entry point to the program
 int main() {
 
@@ -354,37 +413,22 @@
     red_led = LED_OFF;
     blue_led = LED_OFF;
 
-    status_ticker.attach_us(blinky, 250000);
     // Keep track of the main thread
     mainThread = osThreadGetId();
 
     printf("\nStarting mbed Client example\n");
 
-    mbed_trace_init();
+    //mbed_trace_init();
 
     NetworkInterface* network = easy_connect(true);
     if(network == NULL) {
         printf("\nConnection to Network Failed - exiting application...\n");
         return -1;
     }
-
-    // we create our button and LED resources
-    ButtonResource button_resource;
-    LedResource led_resource;
-    BigPayloadResource big_payload_resource;
-
-#ifdef TARGET_K64F
-    // On press of SW3 button on K64F board, example application
-    // will call unregister API towards mbed Device Connector
-    //unreg_button.fall(&mbed_client,&MbedClient::test_unregister);
-    unreg_button.fall(&unregister);
-
-    // Observation Button (SW2) press will send update of endpoint resource values to connector
-    obs_button.fall(&button_clicked);
-#else
-    // Send update of endpoint resource values to connector every 15 seconds periodically
-    timer.attach(&button_clicked, 15.0);
-#endif
+	
+	// environmental data
+	EnvResource env_resource;
+	
 
     // Create endpoint interface to manage register and unregister
     mbed_client.create_interface(MBED_SERVER_ADDRESS, network);
@@ -398,32 +442,37 @@
 
     // Add objects to list
     object_list.push_back(device_object);
-    object_list.push_back(button_resource.get_object());
-    object_list.push_back(led_resource.get_object());
-    object_list.push_back(big_payload_resource.get_object());
-
+	object_list.push_back(env_resource.get_temp_object());
+	object_list.push_back(env_resource.get_hum_object());
+	object_list.push_back(env_resource.get_press_object());
+	
     // Set endpoint registration object
     mbed_client.set_register_object(register_object);
 
     // Register with mbed Device Connector
     mbed_client.test_register(register_object, object_list);
-    registered = true;
 
+	// wait for registration and BLE data started flushing
+	while (!mbed_client.register_successful())  {
+		Thread::wait(500);
+	}
+	
+	printf("\nNow starting BLE thread\n");
+	BLE_thread.start(BLE_thread_init);
+	
+	while (!envDataAvailable) {
+		Thread::wait(500);
+	}
+	
+	printf ("\nNow pushing data to the mbed device connector.\n");
+	
     while (true) {
-        updates.wait(25000);
-        if(registered) {
-            if(!clicked) {
-                mbed_client.test_update_register();
-            }
-        }else {
-            break;
-        }
-        if(clicked) {
-            clicked = false;
-            button_resource.handle_button_click();
-        }
+		
+          env_resource.update_resources();
+		  int timer_val = env_resource.get_polling_period();
+		  Thread::wait(timer_val);
     }
 
     mbed_client.test_unregister();
-    status_ticker.detach();
+
 }