FRDM K64F Metronome

Committer:
ram54288
Date:
Sun May 14 18:35:07 2017 +0000
Revision:
0:a2cb7295a1f7
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ram54288 0:a2cb7295a1f7 1 # The Device Management and Service Enabler feature
ram54288 0:a2cb7295a1f7 2
ram54288 0:a2cb7295a1f7 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:
ram54288 0:a2cb7295a1f7 4
ram54288 0:a2cb7295a1f7 5 - [Create](#the-create-operation)
ram54288 0:a2cb7295a1f7 6 - Delete
ram54288 0:a2cb7295a1f7 7 - [Read](#the-read-operation)
ram54288 0:a2cb7295a1f7 8 - [Write](#the-write-operation)
ram54288 0:a2cb7295a1f7 9 - [Write Attributes](#the-write-attributes-operation)
ram54288 0:a2cb7295a1f7 10 - [Execute](#the-execute-operation)
ram54288 0:a2cb7295a1f7 11
ram54288 0:a2cb7295a1f7 12 Currently, support for the Create and Delete actions is limited to Object Instances.
ram54288 0:a2cb7295a1f7 13
ram54288 0:a2cb7295a1f7 14 The Device Management and Service Enabler Interface supports the following data types:
ram54288 0:a2cb7295a1f7 15
ram54288 0:a2cb7295a1f7 16 - Text: for Resources.
ram54288 0:a2cb7295a1f7 17 - TLV: for Object and Object Instances.
ram54288 0:a2cb7295a1f7 18
ram54288 0:a2cb7295a1f7 19 ## The Create operation
ram54288 0:a2cb7295a1f7 20
ram54288 0:a2cb7295a1f7 21 There are two types of resources you can create:
ram54288 0:a2cb7295a1f7 22
ram54288 0:a2cb7295a1f7 23 - Static: you set the value of the resource once and it does not change during the course of operations.
ram54288 0:a2cb7295a1f7 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.
ram54288 0:a2cb7295a1f7 25
ram54288 0:a2cb7295a1f7 26 Here is an example of creating a custom static Resource:
ram54288 0:a2cb7295a1f7 27
ram54288 0:a2cb7295a1f7 28 ```
ram54288 0:a2cb7295a1f7 29 #include "mbed-client/m2mobject.h"
ram54288 0:a2cb7295a1f7 30 #include "mbed-client/m2mobjectinstance.h"
ram54288 0:a2cb7295a1f7 31 #include "mbed-client/m2mresource.h"
ram54288 0:a2cb7295a1f7 32 _object = M2MInterfaceFactory::create_object("Test");
ram54288 0:a2cb7295a1f7 33 if(_object) {
ram54288 0:a2cb7295a1f7 34 M2MObjectInstance* inst = _object->create_object_instance();
ram54288 0:a2cb7295a1f7 35 if(inst) {
ram54288 0:a2cb7295a1f7 36 inst->create_static_resource("S",
ram54288 0:a2cb7295a1f7 37 "ResourceTest",
ram54288 0:a2cb7295a1f7 38 STATIC_VALUE,
ram54288 0:a2cb7295a1f7 39 sizeof(STATIC_VALUE)-1);
ram54288 0:a2cb7295a1f7 40 ```
ram54288 0:a2cb7295a1f7 41
ram54288 0:a2cb7295a1f7 42 And here is an example of creating a custom dynamic Resource:
ram54288 0:a2cb7295a1f7 43
ram54288 0:a2cb7295a1f7 44 ```
ram54288 0:a2cb7295a1f7 45 #include "mbed-client/m2mobject.h"
ram54288 0:a2cb7295a1f7 46 #include "mbed-client/m2mobjectinstance.h"
ram54288 0:a2cb7295a1f7 47 #include "mbed-client/m2mresource.h"
ram54288 0:a2cb7295a1f7 48 _object = M2MInterfaceFactory::create_object("Test");
ram54288 0:a2cb7295a1f7 49 if(_object) {
ram54288 0:a2cb7295a1f7 50 M2MObjectInstance* inst = _object->create_object_instance();
ram54288 0:a2cb7295a1f7 51 if(inst) {
ram54288 0:a2cb7295a1f7 52 M2MResource* res = inst->create_dynamic_resource("D","ResourceTest",true);
ram54288 0:a2cb7295a1f7 53 char buffer[20];
ram54288 0:a2cb7295a1f7 54 int size = sprintf(buffer,"%d",_value);
ram54288 0:a2cb7295a1f7 55 res->set_operation(M2MBase::GET_PUT_ALLOWED);
ram54288 0:a2cb7295a1f7 56 res->set_value((const uint8_t*)buffer,
ram54288 0:a2cb7295a1f7 57 (const uint32_t)size);
ram54288 0:a2cb7295a1f7 58 ```
ram54288 0:a2cb7295a1f7 59
ram54288 0:a2cb7295a1f7 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.
ram54288 0:a2cb7295a1f7 61
ram54288 0:a2cb7295a1f7 62 ## The Read operation
ram54288 0:a2cb7295a1f7 63
ram54288 0:a2cb7295a1f7 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.
ram54288 0:a2cb7295a1f7 65
ram54288 0:a2cb7295a1f7 66 ## The Write operation
ram54288 0:a2cb7295a1f7 67
ram54288 0:a2cb7295a1f7 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.
ram54288 0:a2cb7295a1f7 69
ram54288 0:a2cb7295a1f7 70 Whenever there is a valid `PUT` operation for any of the resources, the application will receive a callback:
ram54288 0:a2cb7295a1f7 71
ram54288 0:a2cb7295a1f7 72 ```
ram54288 0:a2cb7295a1f7 73 void value_updated(M2MBase *base, M2MBase::BaseType type)
ram54288 0:a2cb7295a1f7 74 ```
ram54288 0:a2cb7295a1f7 75 Where `M2MBase` is the Object whose value has been updated and `M2MBase::BaseType` is the object type.
ram54288 0:a2cb7295a1f7 76
ram54288 0:a2cb7295a1f7 77 Check the code snippet below for usage.
ram54288 0:a2cb7295a1f7 78 ```
ram54288 0:a2cb7295a1f7 79 void value_updated(M2MBase *base, M2MBase::BaseType type) {
ram54288 0:a2cb7295a1f7 80 M2MResource* resource = NULL;
ram54288 0:a2cb7295a1f7 81 M2MResourceInstance* res_instance = NULL;
ram54288 0:a2cb7295a1f7 82 M2MObjectInstance* obj_instance = NULL;
ram54288 0:a2cb7295a1f7 83 M2MObject* obj = NULL;
ram54288 0:a2cb7295a1f7 84 String object_name = "";
ram54288 0:a2cb7295a1f7 85 String resource_name = "";
ram54288 0:a2cb7295a1f7 86 uint16_t object_instance_id = 0;
ram54288 0:a2cb7295a1f7 87 uint16_t resource_instance_id = 0;
ram54288 0:a2cb7295a1f7 88 if(base) {
ram54288 0:a2cb7295a1f7 89 switch(base->base_type()) {
ram54288 0:a2cb7295a1f7 90 case M2MBase::Object:
ram54288 0:a2cb7295a1f7 91 obj = (M2MObject *)base;
ram54288 0:a2cb7295a1f7 92 object_name = obj->name();
ram54288 0:a2cb7295a1f7 93 break;
ram54288 0:a2cb7295a1f7 94 case M2MBase::ObjectInstance:
ram54288 0:a2cb7295a1f7 95 obj_instance = (M2MObjectInstance *)base;
ram54288 0:a2cb7295a1f7 96 object_name = obj_instance->name();
ram54288 0:a2cb7295a1f7 97 object_instance_id = obj_instance->instance_id();
ram54288 0:a2cb7295a1f7 98 break;
ram54288 0:a2cb7295a1f7 99 case M2MBase::Resource: {
ram54288 0:a2cb7295a1f7 100 resource = (M2MResource*)base;
ram54288 0:a2cb7295a1f7 101 object_name = resource->object_name();
ram54288 0:a2cb7295a1f7 102 object_instance_id = resource->object_instance_id();
ram54288 0:a2cb7295a1f7 103 resource_name = resource->name();
ram54288 0:a2cb7295a1f7 104 printf("Value updated, object name %s, object instance id %d, resource name %s\r\n",
ram54288 0:a2cb7295a1f7 105 resource->object_name().c_str(), resource->object_instance_id(), resource->name().c_str());
ram54288 0:a2cb7295a1f7 106 }
ram54288 0:a2cb7295a1f7 107 break;
ram54288 0:a2cb7295a1f7 108 case M2MBase::ResourceInstance: {
ram54288 0:a2cb7295a1f7 109 res_instance = (M2MResourceInstance*)base;
ram54288 0:a2cb7295a1f7 110 object_name = res_instance->object_name();
ram54288 0:a2cb7295a1f7 111 object_instance_id = res_instance->object_instance_id();
ram54288 0:a2cb7295a1f7 112 resource_name = res_instance->name();
ram54288 0:a2cb7295a1f7 113 resource_instance_id = res_instance->instance_id();
ram54288 0:a2cb7295a1f7 114 }
ram54288 0:a2cb7295a1f7 115 break;
ram54288 0:a2cb7295a1f7 116 default:
ram54288 0:a2cb7295a1f7 117 break;
ram54288 0:a2cb7295a1f7 118 }
ram54288 0:a2cb7295a1f7 119 }
ram54288 0:a2cb7295a1f7 120 }
ram54288 0:a2cb7295a1f7 121 ```
ram54288 0:a2cb7295a1f7 122 By default, callbacks are handled in the `value_updated()` function but the application can also define a callback function for an individual resource.
ram54288 0:a2cb7295a1f7 123
ram54288 0:a2cb7295a1f7 124 Check the code snippet below for usage.
ram54288 0:a2cb7295a1f7 125
ram54288 0:a2cb7295a1f7 126 ```
ram54288 0:a2cb7295a1f7 127 static void value_updated_global(const char *name) {
ram54288 0:a2cb7295a1f7 128 if(name) {
ram54288 0:a2cb7295a1f7 129 ...
ram54288 0:a2cb7295a1f7 130 }
ram54288 0:a2cb7295a1f7 131 }
ram54288 0:a2cb7295a1f7 132
ram54288 0:a2cb7295a1f7 133 void M2MLWClient::value_updated_function(const char* name) {
ram54288 0:a2cb7295a1f7 134 if (name) {
ram54288 0:a2cb7295a1f7 135 ...
ram54288 0:a2cb7295a1f7 136 }
ram54288 0:a2cb7295a1f7 137 }
ram54288 0:a2cb7295a1f7 138
ram54288 0:a2cb7295a1f7 139 M2MResource* res = inst->create_dynamic_resource("D", "ResourceTest", true);
ram54288 0:a2cb7295a1f7 140 char buffer[20];
ram54288 0:a2cb7295a1f7 141 int size = sprintf(buffer,"%d",_value);
ram54288 0:a2cb7295a1f7 142 res->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED);
ram54288 0:a2cb7295a1f7 143 res->set_value((const uint8_t*)buffer, (const uint32_t)size);
ram54288 0:a2cb7295a1f7 144 res->set_value_updated_function(value_updated_callback(this,&MbedClient::value_updated_function));
ram54288 0:a2cb7295a1f7 145 /* Overloaded function can be used If callback function is not in class scope.
ram54288 0:a2cb7295a1f7 146 res2->set_value_updated_function(value_updated_callback2(&value_updated_global));
ram54288 0:a2cb7295a1f7 147 */
ram54288 0:a2cb7295a1f7 148
ram54288 0:a2cb7295a1f7 149 ```
ram54288 0:a2cb7295a1f7 150
ram54288 0:a2cb7295a1f7 151 ## The Write Attributes operation
ram54288 0:a2cb7295a1f7 152
ram54288 0:a2cb7295a1f7 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:
ram54288 0:a2cb7295a1f7 154
ram54288 0:a2cb7295a1f7 155 - Minimum Period (pmin)
ram54288 0:a2cb7295a1f7 156 - Maximum Period (pmax)
ram54288 0:a2cb7295a1f7 157 - Greater Than (gt)
ram54288 0:a2cb7295a1f7 158 - Less Than (lt)
ram54288 0:a2cb7295a1f7 159 - Step (st)
ram54288 0:a2cb7295a1f7 160
ram54288 0:a2cb7295a1f7 161 mbed Device Server sets the endpoint attribute values that are used to determine when the endpoint sends the Resource value to the server.
ram54288 0:a2cb7295a1f7 162
ram54288 0:a2cb7295a1f7 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.
ram54288 0:a2cb7295a1f7 164
ram54288 0:a2cb7295a1f7 165 ## The Execute operation
ram54288 0:a2cb7295a1f7 166
ram54288 0:a2cb7295a1f7 167 mbed Device Server uses the **Execute** operation to perform an action. This operation can only be performed on individual Resources.
ram54288 0:a2cb7295a1f7 168
ram54288 0:a2cb7295a1f7 169 <span class="notes">**Note:** mbed Client returns an error when the **Execute** operation is received for Object Instances or Resource Instances.</span>
ram54288 0:a2cb7295a1f7 170
ram54288 0:a2cb7295a1f7 171 If you want to execute a piece of code in your application, you can pass a `POST` request from mbed Device Server.
ram54288 0:a2cb7295a1f7 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.
ram54288 0:a2cb7295a1f7 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.
ram54288 0:a2cb7295a1f7 174
ram54288 0:a2cb7295a1f7 175 Check the code snippet below for usage.
ram54288 0:a2cb7295a1f7 176
ram54288 0:a2cb7295a1f7 177 ```
ram54288 0:a2cb7295a1f7 178 #include "mbed-client/m2mobject.h"
ram54288 0:a2cb7295a1f7 179 #include "mbed-client/m2mobjectinstance.h"
ram54288 0:a2cb7295a1f7 180 #include "mbed-client/m2mresource.h"
ram54288 0:a2cb7295a1f7 181 static void execute_function_2(void *argument) {
ram54288 0:a2cb7295a1f7 182 if(argument) {
ram54288 0:a2cb7295a1f7 183 M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument;
ram54288 0:a2cb7295a1f7 184 int payload_length = param->get_argument_value_length();
ram54288 0:a2cb7295a1f7 185 uint8_t* payload = param->get_argument_value();
ram54288 0:a2cb7295a1f7 186 String object_name = param->get_argument_object_name();
ram54288 0:a2cb7295a1f7 187 uint16_t object_instance_id = param->get_argument_object_instance_id();
ram54288 0:a2cb7295a1f7 188 String resource_name = param->get_argument_resource_name();
ram54288 0:a2cb7295a1f7 189 }
ram54288 0:a2cb7295a1f7 190
ram54288 0:a2cb7295a1f7 191 void M2MLWClient::execute_function(void *argument) {
ram54288 0:a2cb7295a1f7 192 if(argument) {
ram54288 0:a2cb7295a1f7 193 M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument;
ram54288 0:a2cb7295a1f7 194 int payload_length = param->get_argument_value_length();
ram54288 0:a2cb7295a1f7 195 uint8_t* payload = param->get_argument_value();
ram54288 0:a2cb7295a1f7 196 String object_name = param->get_argument_object_name();
ram54288 0:a2cb7295a1f7 197 uint16_t object_instance_id = param->get_argument_object_instance_id();
ram54288 0:a2cb7295a1f7 198 String resource_name = param->get_argument_resource_name();
ram54288 0:a2cb7295a1f7 199 }
ram54288 0:a2cb7295a1f7 200
ram54288 0:a2cb7295a1f7 201 _object = M2MInterfaceFactory::create_object("Test");
ram54288 0:a2cb7295a1f7 202 if(_object) {
ram54288 0:a2cb7295a1f7 203 M2MObjectInstance* inst = _object->create_object_instance();
ram54288 0:a2cb7295a1f7 204 if(inst) {
ram54288 0:a2cb7295a1f7 205 M2MResource* res = inst->create_dynamic_resource("D","ResourceTest",true);
ram54288 0:a2cb7295a1f7 206 char buffer[20];
ram54288 0:a2cb7295a1f7 207 int size = sprintf(buffer,"%d",_value);
ram54288 0:a2cb7295a1f7 208 res->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
ram54288 0:a2cb7295a1f7 209 res->set_value((const uint8_t*)buffer,
ram54288 0:a2cb7295a1f7 210 (const uint32_t)size);
ram54288 0:a2cb7295a1f7 211 res->set_execute_function(execute_callback(this,&M2MLWClient::execute_function));
ram54288 0:a2cb7295a1f7 212 /* Overloaded function can be used If callback function is not in class scope.
ram54288 0:a2cb7295a1f7 213 res->set_execute_function(execute_callback_2(&execute_function_2));
ram54288 0:a2cb7295a1f7 214 */
ram54288 0:a2cb7295a1f7 215 ```
ram54288 0:a2cb7295a1f7 216
ram54288 0:a2cb7295a1f7 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.
ram54288 0:a2cb7295a1f7 218
ram54288 0:a2cb7295a1f7 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.