This is an example of BLE GATT Client, which receives broadcast data from BLE_Server_BME280 ( a GATT server) , then transfers values up to mbed Device Connector (cloud).

Please refer details about BLEClient_mbedDevConn below. https://github.com/soramame21/BLEClient_mbedDevConn

The location of required BLE GATT server, BLE_Server_BME280, is at here. https://developer.mbed.org/users/edamame22/code/BLE_Server_BME280/

Committer:
Ren Boting
Date:
Tue Sep 05 11:56:13 2017 +0900
Revision:
2:b894b3508057
Parent:
0:29983394c6b6
Update all libraries and reform main.cpp

Who changed what in which revision?

UserRevisionLine numberNew contents of line
edamame22 0:29983394c6b6 1 # The Device Management and Service Enabler feature
edamame22 0:29983394c6b6 2
edamame22 0:29983394c6b6 3 mbed Device Server uses the Device Management and Service Enabler to access Object Instances and Resources available on the client. The interface provides this access through the following operations:
edamame22 0:29983394c6b6 4
edamame22 0:29983394c6b6 5 - [Create](#the-create-operation)
edamame22 0:29983394c6b6 6 - Delete
edamame22 0:29983394c6b6 7 - [Read](#the-read-operation)
edamame22 0:29983394c6b6 8 - [Write](#the-write-operation)
edamame22 0:29983394c6b6 9 - [Write Attributes](#the-write-attributes-operation)
edamame22 0:29983394c6b6 10 - [Execute](#the-execute-operation)
edamame22 0:29983394c6b6 11
edamame22 0:29983394c6b6 12 Currently, support for the Create and Delete actions is limited to Object Instances.
edamame22 0:29983394c6b6 13
edamame22 0:29983394c6b6 14 The Device Management and Service Enabler Interface supports the following data types:
edamame22 0:29983394c6b6 15
edamame22 0:29983394c6b6 16 - Text: for Resources.
edamame22 0:29983394c6b6 17 - TLV: for Object and Object Instances.
edamame22 0:29983394c6b6 18
edamame22 0:29983394c6b6 19 ## The Create operation
edamame22 0:29983394c6b6 20
edamame22 0:29983394c6b6 21 There are two types of resources you can create:
edamame22 0:29983394c6b6 22
edamame22 0:29983394c6b6 23 - Static: you set the value of the resource once and it does not change during the course of operations.
edamame22 0:29983394c6b6 24 - Dynamic: the value is expected to change during the course of operations. Therefore, the value is fetched from setter APIs every time the server requests a read operation.
edamame22 0:29983394c6b6 25
edamame22 0:29983394c6b6 26 Here is an example of creating a custom static Resource:
edamame22 0:29983394c6b6 27
edamame22 0:29983394c6b6 28 ```
edamame22 0:29983394c6b6 29 #include "mbed-client/m2mobject.h"
edamame22 0:29983394c6b6 30 #include "mbed-client/m2mobjectinstance.h"
edamame22 0:29983394c6b6 31 #include "mbed-client/m2mresource.h"
edamame22 0:29983394c6b6 32 _object = M2MInterfaceFactory::create_object("Test");
edamame22 0:29983394c6b6 33 if(_object) {
edamame22 0:29983394c6b6 34 M2MObjectInstance* inst = _object->create_object_instance();
edamame22 0:29983394c6b6 35 if(inst) {
edamame22 0:29983394c6b6 36 inst->create_static_resource("S",
edamame22 0:29983394c6b6 37 "ResourceTest",
edamame22 0:29983394c6b6 38 STATIC_VALUE,
edamame22 0:29983394c6b6 39 sizeof(STATIC_VALUE)-1);
edamame22 0:29983394c6b6 40 ```
edamame22 0:29983394c6b6 41
edamame22 0:29983394c6b6 42 And here is an example of creating a custom dynamic Resource:
edamame22 0:29983394c6b6 43
edamame22 0:29983394c6b6 44 ```
edamame22 0:29983394c6b6 45 #include "mbed-client/m2mobject.h"
edamame22 0:29983394c6b6 46 #include "mbed-client/m2mobjectinstance.h"
edamame22 0:29983394c6b6 47 #include "mbed-client/m2mresource.h"
edamame22 0:29983394c6b6 48 _object = M2MInterfaceFactory::create_object("Test");
edamame22 0:29983394c6b6 49 if(_object) {
edamame22 0:29983394c6b6 50 M2MObjectInstance* inst = _object->create_object_instance();
edamame22 0:29983394c6b6 51 if(inst) {
edamame22 0:29983394c6b6 52 M2MResource* res = inst->create_dynamic_resource("D","ResourceTest",true);
edamame22 0:29983394c6b6 53 char buffer[20];
edamame22 0:29983394c6b6 54 int size = sprintf(buffer,"%d",_value);
edamame22 0:29983394c6b6 55 res->set_operation(M2MBase::GET_PUT_ALLOWED);
edamame22 0:29983394c6b6 56 res->set_value((const uint8_t*)buffer,
edamame22 0:29983394c6b6 57 (const uint32_t)size);
edamame22 0:29983394c6b6 58 ```
edamame22 0:29983394c6b6 59
edamame22 0:29983394c6b6 60 For more information on different resource functionalities, please check the [API documentation](https://docs.mbed.com/docs/mbed-client-guide/en/latest/api/annotated.html) for the M2MObject, M2MObjectInstance and M2MResource classes.
edamame22 0:29983394c6b6 61
edamame22 0:29983394c6b6 62 ## The Read operation
edamame22 0:29983394c6b6 63
edamame22 0:29983394c6b6 64 The Client API allows setting values to Resources, an array of Resource Instances, an Object Instance or all the Object Instances of an Object (TLV format supported). mbed Device Server can then read these values using the **Read** operation.
edamame22 0:29983394c6b6 65
edamame22 0:29983394c6b6 66 ## The Write operation
edamame22 0:29983394c6b6 67
edamame22 0:29983394c6b6 68 The **Write** operation is used to overwrite the value of a Resource, an array of Resource Instances or multiple Resources from an Object Instance.
edamame22 0:29983394c6b6 69
edamame22 0:29983394c6b6 70 Whenever there is a valid `PUT` operation for any of the resources, the application will receive a callback:
edamame22 0:29983394c6b6 71
edamame22 0:29983394c6b6 72 ```
edamame22 0:29983394c6b6 73 void value_updated(M2MBase *base, M2MBase::BaseType type)
edamame22 0:29983394c6b6 74 ```
edamame22 0:29983394c6b6 75 Where `M2MBase` is the Object whose value has been updated and `M2MBase::BaseType` is the object type.
edamame22 0:29983394c6b6 76
edamame22 0:29983394c6b6 77 Check the code snippet below for usage.
edamame22 0:29983394c6b6 78 ```
edamame22 0:29983394c6b6 79 void value_updated(M2MBase *base, M2MBase::BaseType type) {
edamame22 0:29983394c6b6 80 M2MResource* resource = NULL;
edamame22 0:29983394c6b6 81 M2MResourceInstance* res_instance = NULL;
edamame22 0:29983394c6b6 82 M2MObjectInstance* obj_instance = NULL;
edamame22 0:29983394c6b6 83 M2MObject* obj = NULL;
edamame22 0:29983394c6b6 84 String object_name = "";
edamame22 0:29983394c6b6 85 String resource_name = "";
edamame22 0:29983394c6b6 86 uint16_t object_instance_id = 0;
edamame22 0:29983394c6b6 87 uint16_t resource_instance_id = 0;
edamame22 0:29983394c6b6 88 if(base) {
edamame22 0:29983394c6b6 89 switch(base->base_type()) {
edamame22 0:29983394c6b6 90 case M2MBase::Object:
edamame22 0:29983394c6b6 91 obj = (M2MObject *)base;
edamame22 0:29983394c6b6 92 object_name = obj->name();
edamame22 0:29983394c6b6 93 break;
edamame22 0:29983394c6b6 94 case M2MBase::ObjectInstance:
edamame22 0:29983394c6b6 95 obj_instance = (M2MObjectInstance *)base;
edamame22 0:29983394c6b6 96 object_name = obj_instance->name();
edamame22 0:29983394c6b6 97 object_instance_id = obj_instance->instance_id();
edamame22 0:29983394c6b6 98 break;
edamame22 0:29983394c6b6 99 case M2MBase::Resource: {
edamame22 0:29983394c6b6 100 resource = (M2MResource*)base;
edamame22 0:29983394c6b6 101 object_name = resource->object_name();
edamame22 0:29983394c6b6 102 object_instance_id = resource->object_instance_id();
edamame22 0:29983394c6b6 103 resource_name = resource->name();
edamame22 0:29983394c6b6 104 printf("Value updated, object name %s, object instance id %d, resource name %s\r\n",
edamame22 0:29983394c6b6 105 resource->object_name().c_str(), resource->object_instance_id(), resource->name().c_str());
edamame22 0:29983394c6b6 106 }
edamame22 0:29983394c6b6 107 break;
edamame22 0:29983394c6b6 108 case M2MBase::ResourceInstance: {
edamame22 0:29983394c6b6 109 res_instance = (M2MResourceInstance*)base;
edamame22 0:29983394c6b6 110 object_name = res_instance->object_name();
edamame22 0:29983394c6b6 111 object_instance_id = res_instance->object_instance_id();
edamame22 0:29983394c6b6 112 resource_name = res_instance->name();
edamame22 0:29983394c6b6 113 resource_instance_id = res_instance->instance_id();
edamame22 0:29983394c6b6 114 }
edamame22 0:29983394c6b6 115 break;
edamame22 0:29983394c6b6 116 default:
edamame22 0:29983394c6b6 117 break;
edamame22 0:29983394c6b6 118 }
edamame22 0:29983394c6b6 119 }
edamame22 0:29983394c6b6 120 }
edamame22 0:29983394c6b6 121 ```
edamame22 0:29983394c6b6 122 By default, callbacks are handled in the `value_updated()` function but the application can also define a callback function for an individual resource.
edamame22 0:29983394c6b6 123
edamame22 0:29983394c6b6 124 Check the code snippet below for usage.
edamame22 0:29983394c6b6 125
edamame22 0:29983394c6b6 126 ```
edamame22 0:29983394c6b6 127 static void value_updated_global(const char *name) {
edamame22 0:29983394c6b6 128 if(name) {
edamame22 0:29983394c6b6 129 ...
edamame22 0:29983394c6b6 130 }
edamame22 0:29983394c6b6 131 }
edamame22 0:29983394c6b6 132
edamame22 0:29983394c6b6 133 void M2MLWClient::value_updated_function(const char* name) {
edamame22 0:29983394c6b6 134 if (name) {
edamame22 0:29983394c6b6 135 ...
edamame22 0:29983394c6b6 136 }
edamame22 0:29983394c6b6 137 }
edamame22 0:29983394c6b6 138
edamame22 0:29983394c6b6 139 M2MResource* res = inst->create_dynamic_resource("D", "ResourceTest", true);
edamame22 0:29983394c6b6 140 char buffer[20];
edamame22 0:29983394c6b6 141 int size = sprintf(buffer,"%d",_value);
edamame22 0:29983394c6b6 142 res->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED);
edamame22 0:29983394c6b6 143 res->set_value((const uint8_t*)buffer, (const uint32_t)size);
edamame22 0:29983394c6b6 144 res->set_value_updated_function(value_updated_callback(this,&MbedClient::value_updated_function));
edamame22 0:29983394c6b6 145 /* Overloaded function can be used If callback function is not in class scope.
edamame22 0:29983394c6b6 146 res2->set_value_updated_function(value_updated_callback2(&value_updated_global));
edamame22 0:29983394c6b6 147 */
edamame22 0:29983394c6b6 148
edamame22 0:29983394c6b6 149 ```
edamame22 0:29983394c6b6 150
edamame22 0:29983394c6b6 151 ## The Write Attributes operation
edamame22 0:29983394c6b6 152
edamame22 0:29983394c6b6 153 Any readable Resource can have attributes that are considered during the [**Observe** operation](info_reporting.md#the-observe-feature). The following attributes are used:
edamame22 0:29983394c6b6 154
edamame22 0:29983394c6b6 155 - Minimum Period (pmin)
edamame22 0:29983394c6b6 156 - Maximum Period (pmax)
edamame22 0:29983394c6b6 157 - Greater Than (gt)
edamame22 0:29983394c6b6 158 - Less Than (lt)
edamame22 0:29983394c6b6 159 - Step (st)
edamame22 0:29983394c6b6 160
edamame22 0:29983394c6b6 161 mbed Device Server sets the endpoint attribute values that are used to determine when the endpoint sends the Resource value to the server.
edamame22 0:29983394c6b6 162
edamame22 0:29983394c6b6 163 Check the [LWM2M Specification](http://technical.openmobilealliance.org/Technical/technical-information/release-program/current-releases/oma-lightweightm2m-v1-0) for details of all the possible **Write Attributes** defined for different types of Objects and Resources.
edamame22 0:29983394c6b6 164
edamame22 0:29983394c6b6 165 ## The Execute operation
edamame22 0:29983394c6b6 166
edamame22 0:29983394c6b6 167 mbed Device Server uses the **Execute** operation to perform an action. This operation can only be performed on individual Resources.
edamame22 0:29983394c6b6 168
edamame22 0:29983394c6b6 169 <span class="notes">**Note:** mbed Client returns an error when the **Execute** operation is received for Object Instances or Resource Instances.</span>
edamame22 0:29983394c6b6 170
edamame22 0:29983394c6b6 171 If you want to execute a piece of code in your application, you can pass a `POST` request from mbed Device Server.
edamame22 0:29983394c6b6 172 When your Resource receives the `POST` request, mbed Client parses the payload from the request and wraps it in the `M2MResource::M2MExecuteParameter` class. The class object is passed through the execute callback function.
edamame22 0:29983394c6b6 173 You can then typecast the `void*` argument into the corresponding `M2MResource::M2MExecuteParameter` and access the passed payload and its length through the given API. M2MResource::M2MExecuteParameter contains also information which object and object instance resource belongs to. Make sure that the payload sent through POST request is in `plain/text` format and that the content-type is set as “plain/text” on the POST request call.
edamame22 0:29983394c6b6 174
edamame22 0:29983394c6b6 175 Check the code snippet below for usage.
edamame22 0:29983394c6b6 176
edamame22 0:29983394c6b6 177 ```
edamame22 0:29983394c6b6 178 #include "mbed-client/m2mobject.h"
edamame22 0:29983394c6b6 179 #include "mbed-client/m2mobjectinstance.h"
edamame22 0:29983394c6b6 180 #include "mbed-client/m2mresource.h"
edamame22 0:29983394c6b6 181 static void execute_function_2(void *argument) {
edamame22 0:29983394c6b6 182 if(argument) {
edamame22 0:29983394c6b6 183 M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument;
edamame22 0:29983394c6b6 184 int payload_length = param->get_argument_value_length();
edamame22 0:29983394c6b6 185 uint8_t* payload = param->get_argument_value();
edamame22 0:29983394c6b6 186 String object_name = param->get_argument_object_name();
edamame22 0:29983394c6b6 187 uint16_t object_instance_id = param->get_argument_object_instance_id();
edamame22 0:29983394c6b6 188 String resource_name = param->get_argument_resource_name();
edamame22 0:29983394c6b6 189 }
edamame22 0:29983394c6b6 190
edamame22 0:29983394c6b6 191 void M2MLWClient::execute_function(void *argument) {
edamame22 0:29983394c6b6 192 if(argument) {
edamame22 0:29983394c6b6 193 M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument;
edamame22 0:29983394c6b6 194 int payload_length = param->get_argument_value_length();
edamame22 0:29983394c6b6 195 uint8_t* payload = param->get_argument_value();
edamame22 0:29983394c6b6 196 String object_name = param->get_argument_object_name();
edamame22 0:29983394c6b6 197 uint16_t object_instance_id = param->get_argument_object_instance_id();
edamame22 0:29983394c6b6 198 String resource_name = param->get_argument_resource_name();
edamame22 0:29983394c6b6 199 }
edamame22 0:29983394c6b6 200
edamame22 0:29983394c6b6 201 _object = M2MInterfaceFactory::create_object("Test");
edamame22 0:29983394c6b6 202 if(_object) {
edamame22 0:29983394c6b6 203 M2MObjectInstance* inst = _object->create_object_instance();
edamame22 0:29983394c6b6 204 if(inst) {
edamame22 0:29983394c6b6 205 M2MResource* res = inst->create_dynamic_resource("D","ResourceTest",true);
edamame22 0:29983394c6b6 206 char buffer[20];
edamame22 0:29983394c6b6 207 int size = sprintf(buffer,"%d",_value);
edamame22 0:29983394c6b6 208 res->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
edamame22 0:29983394c6b6 209 res->set_value((const uint8_t*)buffer,
edamame22 0:29983394c6b6 210 (const uint32_t)size);
edamame22 0:29983394c6b6 211 res->set_execute_function(execute_callback(this,&M2MLWClient::execute_function));
edamame22 0:29983394c6b6 212 /* Overloaded function can be used If callback function is not in class scope.
edamame22 0:29983394c6b6 213 res->set_execute_function(execute_callback_2(&execute_function_2));
edamame22 0:29983394c6b6 214 */
edamame22 0:29983394c6b6 215 ```
edamame22 0:29983394c6b6 216
edamame22 0:29983394c6b6 217 The POST method allows the client to respond immediately with the updated payload value as a piggyback response. If you want to send the payload response to the server later (because the Execute operation may take longer time on device to complete), you can handle this through the API.
edamame22 0:29983394c6b6 218
edamame22 0:29983394c6b6 219 You can set the resource API `void set_delayed_response(bool)` to `true`. In this case, the POST request response to the server is an empty acknowledgment. When your resource is ready with the response, you can simply call `send_delayed_post_response()` on that resource and the client sends the latest resource value to the server as part of a separate response to the POST request. By default, `void set_delayed_response(bool)` is `false`, which means that the POST response returns the resource value as a piggyback payload immediately.