3 @page OCHowTo How To... Guides
\r
5 @ref Guide_Representative_Devices "Sample representative devices used in these tutorials"
\r
7 @ref Guide_Stack_Init "How to initialize the stack"
\r
9 @ref Guide_Register_Resource "How to register a resource"
\r
11 @ref Guide_Find_Resource "How to find a resource"
\r
13 @ref Guide_PUT "How to set resource state [PUT]"
\r
15 @ref Guide_GET "How to query resource state [GET]"
\r
17 @ref Guide_Observe "How to observe resource state [Observe]"
\r
21 ********************************************************************
\r
24 @page Guide_Representative_Devices Representative Devices
\r
26 The best way to understand the concepts for IoTivity is through following an example and understanding the use case. The following devices are referred to throughout this document for use cases and basic operations. The details are listed here for reference so that implementers can compare the responses from these devices with their configuration to develop an understanding of what the responses mean.
\r
28 @section Rep_Light_Device Light devices (192.168.1.11-13)
\r
30 A lighting device that can handle up to two light bulbs with dimmers. Each light bulb resource has two attributes:
\r
31 \li Power: controls power and can have a value of 0 (off) or 1 (on)
\r
32 \li Level: current dimmer level with a value from 1 (low) to 10 (full)
\r
34 The separation of the attributes allows the light to return to the previous light level when the power is toggled.
\r
36 @subsection Rep_Light_Device_Description Description of resources on this device type
\r
38 <table cellspacing="0" cellpadding="0" border=1 >
\r
41 <td valign="top" ><b>Resource</b></td>
\r
42 <td valign="top" ><b>Description</b></td>
\r
46 <td valign="top" ><p>/oc/core</p></td>
\r
47 <td valign="top" ><p>Standard resource listing in JSON format.</p></td>
\r
51 <td valign="top" ><p>/oc/core/d</p></td>
\r
52 <td valign="top" ><p>Virtual (hidden) resource that describes the device. It is searchable and supports the JSON attributes listed in the appendix.</p></td>
\r
56 <td valign="top" ><p>/lights</p></td>
\r
57 <td valign="top" ><p>The resource collection that contains light resources</p>
\r
59 <p>rt=alpha.light</p>
\r
61 <p>if=oc.mi.ll (linked-list)</p></td>
\r
65 <td valign="top" ><p>/light/1</p></td>
\r
66 <td valign="top" ><p>The resource associated with the first light bulb attached to this device </p>
\r
68 <p>rt=alpha.light</p>
\r
70 <p>if=oc.mi.def (default)</p></td>
\r
74 <td valign="top" ><p>/light/2</p></td>
\r
75 <td valign="top" ><p>The resource associated with the second light bulb attached to this device</p>
\r
77 <p>rt=alpha.light</p>
\r
79 <p>if=oc.mi.def (default)</p></td>
\r
86 @subsection Rep_Light_Device_Resource_11 Resource(s) at 192.168.1.11
\r
88 This device contains a single light resource. The following lists the valid resources and their typical state:
\r
90 <table cellspacing="0" cellpadding="0" border=1>
\r
93 <td valign="top" ><b>Resource</b></td>
\r
94 <td valign="top" ><b>Representation</b></td>
\r
98 <td valign="top" ><p>/oc/core</p></td>
\r
99 <td valign="top" ><p>[</p>
\r
101 <p>{ "href" : "/lights", "rt" : ["alpha.light"], "if" : ["oc.mi.ll"]},</p>
\r
103 <p>{ "href" : "/light/1", "rt" : ["alpha.light"], "if" : ["oc.mi.def"], "obs" : 1}</p>
\r
109 <td valign="top" ><p>/oc/core/d</p></td>
\r
110 <td valign="top" ><p>{</p>
\r
112 <p>"di" : "12345678-1234-1234-0000000000000011",</p>
\r
114 <p>"dn" : "Alpha Light Controller",</p>
\r
116 <p>"dd" : "A Light Controller"</p>
\r
122 <td valign="top" ><p>/light/1</p></td>
\r
123 <td valign="top" ><p>{ "power" : 0, "level" : 4 }</p></td>
\r
131 @subsection Rep_Light_Device_Resource_12 Resource(s) at 192.168.1.12
\r
133 This device contains a single light resource. The following lists the valid resources and their typical state:
\r
135 <table cellspacing="0" cellpadding="0" border=1>
\r
138 <td valign="top" ><b>Resource</b></td>
\r
139 <td valign="top" ><b>Representation</b></td>
\r
143 <td valign="top" ><p>/oc/core</p></td>
\r
144 <td valign="top" ><p>[</p>
\r
146 <p>{ "href" : "/lights", "rt" : ["alpha.light"], "if" : ["oc.mi.ll"]},</p>
\r
148 <p>{ "href" : "/light/2", "rt" : ["alpha.light"], "if" : ["oc.mi.def"], "obs":1}</p>
\r
154 <td valign="top" ><p>/oc/core/d</p></td>
\r
155 <td valign="top" ><p>{</p>
\r
157 <p>"di" : "12345678-1234-1234-0000000000000012",</p>
\r
159 <p>"dn" : "Alpha Light Controller",</p>
\r
161 <p>"dd" : "A Light Controller"</p>
\r
167 <td valign="top" ><p>/light/2</p></td>
\r
168 <td valign="top" ><p>{ "power" : 1, "level" : 6 }</p></td>
\r
175 @subsection Rep_Light_Device_Resource_13 Resource(s) at 192.168.1.13
\r
177 This device contains two light resources. The following lists the valid resources and their typical state:
\r
179 <table cellspacing="0" cellpadding="0" border=1>
\r
182 <td valign="top" ><p>Resource</p></td>
\r
183 <td valign="top" ><p>Representation</p></td>
\r
187 <td valign="top" ><p>/oc/core</p></td>
\r
188 <td valign="top" ><p>[</p>
\r
190 <p>{ "href" : "/lights", "rt" : ["alpha.light"], "if" : ["oc.mi.ll"]},</p>
\r
192 <p>{ "href" : "/light/1", "rt" : ["alpha.light"], "if" : ["oc.mi.def"], "obs":1},</p>
\r
194 <p>{ "href" : "/light/2", "rt" : ["alpha.light"], "if" : ["oc.mi.def"], "obs":1}</p>
\r
200 <td valign="top" ><p>/oc/core/d</p></td>
\r
201 <td valign="top" ><p>{</p>
\r
203 <p>"di" : "12345678-1234-1234-0000000000000013",</p>
\r
205 <p>"dn" : "Alpha Light Controller",</p>
\r
207 <p>"dd" : "A Light Controller"</p>
\r
213 <td valign="top" ><p>/light/1</p></td>
\r
214 <td valign="top" ><p>{ "power" : 0, "level" : 8 }</p></td>
\r
218 <td valign="top" ><p>/light/2</p></td>
\r
219 <td valign="top" ><p>{ "power" : 1, "level" : 10 }</p></td>
\r
226 @page Guide_Stack_Init Stack Initialization
\r
228 @section Stack_Init_SD Sequence Diagram
\r
230 @image html seq_stack_init.png
\r
232 @note API calls take only important parameters. We omitted some of the parameters for clarity.
\r
234 The asynchronous processing block handles incoming network traffic including packet processing, scheduled tasks including communication timeouts and callbacks to the application resulting from these activities.
\r
236 @section Stack_Init_CPP Stack Initialization in C++
\r
239 // Create PlatformConfig object
\r
240 PlatformConfig cfg;
\r
241 cfg.ipAddress = "134.134.161.33";
\r
243 cfg.mode = ModeType::Client;
\r
244 cfg.serviceType = ServiceType::InProc;
\r
246 // Create a OCPlatform instance.
\r
247 // Note: Platform creation is synchronous call.
\r
250 OCPlatform platform(cfg);
\r
251 }catch(OCException& e)
\r
257 Stack initialization in C++ consists of:
\r
258 @li Creating a OCPlatform object with Platform configuration which allows definition of role operation (server or client), stack operation (in-process or out-of-process), etc.
\r
260 @li This is a synchronous call. The application will receive an exception if platform object creation fails.
\r
261 @li The C++ SDK handles all of the memory allocation and collection. Therefore, the application need not worry about memory management related to the stack.
\r
262 @li Platform creation happens on the main thread while the message pump happens on a worker thread.
\r
268 ********************************************************************
\r
270 @page Guide_Register_Resource Registering A Resource
\r
272 Registering a resource requires two basic items:
\r
273 \li A handler to process requests from the stack, and
\r
274 \li A URI path to register the resource.
\r
275 The URI path should be rooted (in other words, start with a slash). The stack will construct the fully qualified URI by adding the URI authority to the provided URI path. For example, given a service running on port 5683 in a device at IP address 192.168.1.1, if the application registers a resource with a URI path "/light/1", the resulting fully qualified URI is "oc://192.168.1.1:5683/light/1", which uniquely identifies the resource's location (IP address port and path).
\r
276 @note Only one resource can be registered at a given URI.
\r
278 @image HTML seq_register_resource_2.png
\r
280 @section Register_Resource_SD Sequence Diagram
\r
281 The following call sequence diagram outlines the operations performed in the stack when a resource is registered:
\r
283 @image HTML seq_register_resource.png
\r
286 Assuming the application has created a valid OCPlatform object, the application registers a new resource with the stack by calling OCPlatform::registerResource(...).
\r
288 In this example, the call would take the form:
\r
290 platform.registerResource(&handle, "/light/1", "light", "oc.mi.def", handler, OC_DISCOVERABLE)
\r
292 The handle is a reference to the resource that is used on other APIs. The URI path ("/light/1") is where on this server that the resource can be located. The URI path is unique; this call will fail if the application attempts to register another resource using an existing URI. The resource type ("light") and interface ("oc.mi.def") are properties of the resource used in the discovery process. The handler is a function called from the stack to process requests. The flags control how the stack should handle the resource. The OC_DISCOVERABLE flag indicates that the resource should be reported if a client performs a resource discovery on this server.
\r
296 The OCPlatform::registerResource(...) method delegates the call to the appropriate instance of the stack (in-process or out-of-process via IPC).
\r
299 The internal registerResource(...) method constructs a C++ entity handler and registers it with the C SDK using OCCreateResource(...).
\r
301 In this example, the call would take the form:
\r
303 OCCreateResource(&handle, "light", "oc.mi.def", "/light/1", handler, OC_ DISCOVERABLE)
\r
305 Many of these parameters are passed through to the C SDK directly. However, the entity handler is a proxy function for the handler passed from OCPlatform::registerResource(...).
\r
307 @section Register_Resource_CPP Register Resource in C++ [Server]
\r
310 OCResourceHandle resourceHandle;
\r
311 std::string resourceURI = "/light/1";
\r
312 std::string resourceTypeName = "alpha.light
\r
313 std::string resourceInterface = DEFAULT_INTERFACE;
\r
314 uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
\r
316 OCStackResult result = platform.registerResource(resourceHandle,
\r
323 if (OC_STACK_OK == result)
\r
333 ********************************************************************
\r
335 @page Guide_Find_Resource Finding A Resource
\r
337 This operation returns all resources of given type on the network service. This operation is sent via multicast to all services. However, the filter limits the responders to just those that support the resource type in the query. Currently only exact matches are supported.
\r
339 @image HTML seq_find_resource_2.png
\r
341 @section Find_Resource_SD Sequence Diagram
\r
343 The following sequence diagram illustrates the resource discovery process over the network when using CoAP. The mechanism is different for Bluetooth, SSDP/HTTP, etc. In the case of CoAP, a 'get' request is sent via multicast to all IoTivity devices. Each device processes the query and responds if the request filter is satisfied.
\r
345 In the following example, the client requests all of the light resources with a resource type (rt). Both lights respond to the request, but the fan does not.
\r
347 @image HTML seq_find_resource_3.png
\r
350 The following sequence diagram describes the call sequence for discovery from the client side.
\r
351 @image HTML seq_find_resource.png
\r
354 \li Assuming that the client has a properly initialized OCPlatform object, a C++ SDK client can discover resources by calling OCPlatform::findResources(...).
\r
356 In this example, the call would take the form:
\r
358 platform.findResources("", "/oc/core?rt=alpha.light", findHandler)
\r
360 The first parameter is the URI authority (target host), which, when empty, indicates that this is for all nodes. The second parameter ("/oc/core?rt=alpha.light") is the URI path and URI query. The URI path ("/oc/core") indicates the resource and the URI query ("rt=alpha.light") is the filter.
\r
362 \li The SDK call findResources(...) internally delegates the call directly to the in-process or to the out-of process stack via IPC based on the stack configuration.
\r
363 \li Within the stack, findResource(...) calls the C API function OCDoResource(...). In this example, the call is OCDoResource(&handle, OC_REST_GET, "/oc/core?rt=alpha.light", 0, 0, OC_NON_CONFIRMABLE, ...)
\r
364 \li OCDoResource determines which transport is needed to dispatch the request and delegates the call. In the case of CoAP, the following calls are made:
\r
365 - Calls OCDoCoapResource(OC_REST_GET, OC_NON_CONFIRMABLE, token, "/oc/core?rt=alpha.light", 0). The token in this example is a nonce that ties a CoAP response back to the CoAP request. Internally, this method creates the CoAP PDU for dispatching.
\r
366 - Calls coap_send(context, host, pdu), which is a wrapper for the implementation below.
\r
367 - Calls coap_send_impl(context, host, packet), which dispatches the packet to the socket and does the appropriate CoAP bookkeeping.
\r
368 - Calls OCSend(socket, buffer, size...), which is a wrapper for the socket implementation as the functions for dispatching a UDP packet can vary in the embedded systems.
\r
369 \li Servers that offer the resource on the network will reply to the query. The message pump that is evoked from the OCProcess(...) function in the C SDK receives these response packets and dispatches them to the callback associated with the original request based on the CoAP message ID. These responses will come back at the timing defined by their servers. The client stack has timeouts for these responses that are listed in the appendices.
\r
370 \li As previously mentioned, the stack matches the response to the original request using the message ID and send the results to the callback associated with the request. At this level, the raw payload is presented in JSON format. It is the responsibility of the callback passed to OCDoResource(...) to parse this result.
\r
371 \li The C++ SDK provides a callback to OCDoResource(...) that will parse the results, construct collections of OCResource objects from the response, and pass them to a C++ client using the handler passed to the platform.findResource(...) method. The handler will be called once for each resource server that responds to the query.
\r
374 \li Some of the API call parameters have been omitted for brevity.
\r
375 \li The findResource() method can be used in the following ways:
\r
376 - Find all resources on the network that match the provided criteria
\r
377 - Query a specific (single) server for the resources that it provides matching the provided criteria
\r
378 \li The findResource() method may be used multiple times to find a resource
\r
379 \li The findResource() callback is called from the message pump thread in multithreaded environments
\r
380 \li Blocking in the findResource() callback will block other stack processing including servicing the network I/O which can cause delays and missed packets.
\r
382 <b>Detailed server call sequence diagram</b>
\r
383 The following sequence diagram illustrates the call sequence for discovery from the server side.
\r
385 @note When the request is sent to all nodes, all nodes will run through this sequence.
\r
387 @image HTML seq_find_resource_4.png
\r
390 \li The discovery request under CoAP is handled like any other resource GET request. The request can be received via unicast or multicast, but the response, if any, is always sent via unicast.
\r
391 \li The stack dispatches the request to an entity handler that is defined by the stack.
\r
392 \li The handler for "/oc/core", processes the URI query, if any, and builds a list of resources that match the criteria and returns the result in JSON to the network transport.
\r
393 \li In the case of CoAP, if the request is made to all nodes (multicast) and the resource list is empty, no response is sent to the clients. If the request is directed (unicast) or the resource list has results, the response is sent unicast back the client.
\r
396 @section Find_Resource_CPP Register Resource in C++ [Client]
\r
399 // Callback to found resources
\r
400 void foundResource(std::shared_ptr<OCResource> resource)
\r
403 std::string resourceURI;
\r
404 std::string hostAddress;
\r
407 // Do some operations with resource object.
\r
410 std::cout<<"DISCOVERED Resource:"<<std::endl;
\r
411 // Get the resource URI
\r
412 resourceURI = resource->uri();
\r
413 std::cout << "\tURI of the resource: " << resourceURI << std::endl;
\r
415 // Get the resource host address
\r
416 hostAddress = resource->host();
\r
417 std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
\r
419 // Get the resource types
\r
420 std::cout << "\tList of resource types: " << std::endl;
\r
421 for(auto &resourceTypes : resource->getResourceTypes())
\r
423 std::cout << "\t\t" << resourceTypes << std::endl;
\r
426 // Get the resource interfaces
\r
427 std::cout << "\tList of resource interfaces: " << std::endl;
\r
428 for(auto &resourceInterfaces : resource->getResourceInterfaces())
\r
430 std::cout << "\t\t" << resourceInterfaces << std::endl;
\r
433 if(resourceURI == "/a/light1")
\r
435 // Found interested resource
\r
440 // Resource is invalid
\r
441 std::cout << "Resource is invalid" << std::endl;
\r
445 catch(std::exception& e)
\r
455 OCPlatform platform(cfg);
\r
457 // Find all resources
\r
458 platform.findResource("", "coap://224.0.1.187/oc/core?rt=alpha.light", &foundResource);
\r
460 }catch(OCException& e)
\r
468 @section Find_Resource_OTA_Request Over the air Request
\r
470 The request is sent to all nodes on the network:
\r
472 <table cellspacing="0" cellpadding="0" border=1>
\r
475 <td valign="top" ><p>Field</p></td>
\r
476 <td valign="top" ><p>Value</p></td>
\r
477 <td valign="top" ><p>Note(s)</p></td>
\r
481 <td valign="top" ><p>Address</p></td>
\r
482 <td valign="top" ><p>224.0.1.187:5683</p></td>
\r
483 <td valign="top" ><p>Multicast packet</p></td>
\r
487 <td valign="top" ><p>Header</p></td>
\r
488 <td valign="top" ><p>NON, GET, MID=0x7d40</p></td>
\r
489 <td valign="top" ><p>Multicast discovery request should be non-confirmable</p></td>
\r
493 <td valign="top" ><p>URI-Path</p></td>
\r
494 <td valign="top" ><p>oc</p></td>
\r
495 <td rowspan="3" valign="top" ><p>"/oc/core?rt=alpha.light"</p></td>
\r
499 <td valign="top" ><p>URI-Path</p></td>
\r
500 <td valign="top" ><p>core</p></td>
\r
504 <td valign="top" ><p>URI-Query</p></td>
\r
505 <td valign="top" ><p>rt=alpha.light</p></td>
\r
506 <td valign="middle" ><p><br />
\r
511 <td valign="top" ><p>Accept</p></td>
\r
512 <td valign="top" ><p>application/json</p></td>
\r
513 <td valign="top" ><p><br />
\r
522 @section Find_Resource_OTA_Response Over the air Response(s)
\r
524 Assuming that all of the representative devices (see @ref Guide_Representative_Devices "Representative Devices") are online, three responses are expected. Only the three devices with light resources respond; the list of resources has been filtered to contain just the resources that match the criteria.
\r
526 <b>From 192.168.1.11</b>:
\r
528 <table cellspacing="0" cellpadding="0" border=1>
\r
530 <td valign="top" ><p>Field</p></td>
\r
531 <td valign="top" ><p>Value</p></td>
\r
532 <td valign="top" ><p>Explanation</p></td>
\r
536 <td valign="top" ><p>Address</p></td>
\r
537 <td valign="top" ><p>192.168.1.1:5683</p></td>
\r
538 <td valign="top" ><p>Client Address</p></td>
\r
542 <td valign="top" ><p>Header</p></td>
\r
543 <td valign="top" ><p>ACK, CONTENT, MID=0x7d40</p></td>
\r
544 <td valign="top" ><p>Success w/content</p></td>
\r
548 <td valign="top" ><p>Content</p>
\r
551 <td valign="top" ><p>application/json</p></td>
\r
552 <td valign="top" ><p><br />
\r
557 <td valign="top" ><p>Payload</p></td>
\r
558 <td valign="top" ><p>[</p>
\r
560 <p>{ "href" : "/light/1", "rt":["alpha.light"], "if":["oc.mi.def"], "obs":1}</p>
\r
563 <td valign="top" ><p><br />
\r
569 <b>From 192.168.1.12</b>:
\r
571 <table cellspacing="0" cellpadding="0" border=1>
\r
574 <td valign="top" ><p>Field</p></td>
\r
575 <td valign="top" ><p>Value</p></td>
\r
576 <td valign="top" ><p>Explanation</p></td>
\r
580 <td valign="top" ><p>Address</p></td>
\r
581 <td valign="top" ><p>192.168.1.1:5683</p></td>
\r
582 <td valign="top" ><p>Client Address</p></td>
\r
586 <td valign="top" ><p>Header</p></td>
\r
587 <td valign="top" ><p>ACK, CONTENT, MID=0x7d40</p></td>
\r
588 <td valign="top" ><p>Success w/content</p></td>
\r
592 <td valign="top" ><p>Content</p>
\r
595 <td valign="top" ><p>application/json</p></td>
\r
596 <td valign="top" ><p><br />
\r
601 <td valign="top" ><p>Payload</p></td>
\r
602 <td valign="top" ><p>[</p>
\r
604 <p>{ "href" : "/light/2", "rt":["alpha.light"], "if":["oc.mi.def"], "obs":1}</p>
\r
607 <td valign="top" ><p><br />
\r
615 <b>From 192.168.1.13</b>:
\r
617 <table cellspacing="0" cellpadding="0" border=1>
\r
619 <td valign="top" ><p>Field</p></td>
\r
620 <td valign="top" ><p>Value</p></td>
\r
621 <td valign="top" ><p>Explanation</p></td>
\r
625 <td valign="top" ><p>Address</p></td>
\r
626 <td valign="top" ><p>192.168.1.1:5683</p></td>
\r
627 <td valign="top" ><p>Client Address</p></td>
\r
631 <td valign="top" ><p>Header</p></td>
\r
632 <td valign="top" ><p>ACK, CONTENT, MID=0x7d40</p></td>
\r
633 <td valign="top" ><p>Success w/content</p></td>
\r
637 <td valign="top" ><p>Content</p>
\r
640 <td valign="top" ><p>application/json</p></td>
\r
641 <td valign="top" ><p><br />
\r
646 <td valign="top" ><p>Payload</p></td>
\r
647 <td valign="top" ><p>[</p>
\r
649 <p>{ "href" : "/light/1", "rt":["alpha.light"], "if":["oc.mi.def"], "obs":1},</p>
\r
651 <p>{ "href" : "/light/2", "rt":["alpha.light"], "if":["oc.mi.def"], "obs":1}</p>
\r
654 <td valign="top" ><p><br />
\r
662 ********************************************************************
\r
664 @page Guide_PUT Setting a resource state [PUT]
\r
666 This operation sets the value of a simple resource. In this example, we turn on a light resource and set the brightness to 50%.
\r
668 @section PUT_SD Sequence Diagram
\r
670 @image HTML seq_put.png
\r
673 1. The client application calls resource.put(...) to set representation of resource.
\r
675 resource.put(attributeMap, queryParamsMap, &onPut);
\r
676 2. Client SDK internally calls the setResourceAttributes function of the client wrapper.
\r
678 OCDoResource(OC_REST_PUT, "//192.168.1.11/light/1, 0, 0, OC_CONFIRMABLE, callback);
\r
679 3. Send PUT request to remote device
\r
680 4. The OCProcess() service function (server-side message pump) reads the packet from the socket and dispatches the request to the entity handler for the provided URI.
\r
681 5. The entity handler, which was provided by an upper layer when the resource was registered, parses the representation and in the case of the C++ API passes the results to the upper layer handler. In a C only environment, the results would also be processed in the entity handler.
\r
682 6. The upper layer entity handler written by the app developer/vendor is invoked, and response is formed accordingly.
\r
683 7. The upper layer entity handler returns success or failure with a response.
\r
684 8. Returns success or failure to lower layer for transmission to client.
\r
685 9. Returns success or failure to lower layer for transmission to client.
\r
686 10. Returns success or failure to lower layer for transmission to client.
\r
687 11. Result is formatted and sent over network to client
\r
688 12. The OCProcess() service function (client-side message pump) reads results and passes the results back to the client application via the callback passed to OCDoResource
\r
691 @section PUT__Client_CPP Set Resource's State [PUT] in C++ [Client]
\r
694 void putLightRepresentation(std::shared_ptr<OCResource> resource)
\r
698 OCRepresentation rep;
\r
700 std::cout << "Putting light representation..."<<std::endl;
\r
701 // Create AttributeMap
\r
702 AttributeMap attributeMap;
\r
703 // Add the attribute name and values in the attribute map
\r
704 AttributeValues stateVal;
\r
705 stateVal.push_back("true");
\r
707 AttributeValues powerVal;
\r
708 powerVal.push_back("10");
\r
710 attributeMap["state"] = stateVal;
\r
711 attributeMap["power"] = powerVal;
\r
713 // Create QueryParameters Map and add query params (if any)
\r
714 QueryParamsMap queryParamsMap;
\r
716 rep.setAttributeMap(attributeMap);
\r
718 // Invoke resource's put API with attribute map, query map and the callback parameter
\r
719 resource->put(rep, queryParamsMap, &onPut);
\r
723 // callback handler on PUT request
\r
724 void onPut(const OCRepresentation& rep, const int eCode)
\r
726 if(eCode == SUCCESS_RESPONSE)
\r
728 std::cout << "PUT request was successful" << std::endl;
\r
730 AttributeMap attributeMap = rep.getAttributeMap();
\r
732 for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
\r
734 std::cout << "\tAttribute name: "<< it->first << " value: ";
\r
735 for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
\r
737 std::cout <<"\t"<< *valueItr << " ";
\r
740 std::cout << std::endl;
\r
743 std::vector<OCRepresentation> children = rep.getChildren();
\r
745 for(auto oit = children.begin(); oit != children.end(); ++oit)
\r
747 attributeMap = oit->getAttributeMap();
\r
749 for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
\r
751 std::cout << "\tAttribute name: "<< it->first << " value: ";
\r
752 for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
\r
754 std::cout <<"\t"<< *valueItr << " ";
\r
757 std::cout << std::endl;
\r
764 std::cout << "onPut Response error: " << eCode << std::endl;
\r
771 @section PUT_Server_CPP Set Resource's State [PUT] in C++ [Server]
\r
774 //Entity handle sample for PUT
\r
775 if(requestType == "PUT")
\r
777 cout << "\t\t\trequestType : PUT\n";
\r
779 // Check for query params (if any)
\r
780 QueryParamsMap queryParamsMap = request->getQueryParameters();
\r
782 cout << "\t\t\tquery params: \n";
\r
783 for(auto it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
\r
785 cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
\r
788 // Get the representation from the request
\r
789 OCRepresentation rep = request->getResourceRepresentation();
\r
791 myLightResource.setRepresentation(rep); // See code snippet below
\r
793 // Do related operations related to PUT request // See code snippet below
\r
794 rep = myLightResource.getRepresentation();
\r
799 response->setErrorCode(200);
\r
801 auto findRes = queryParamsMap.find("if");
\r
803 if(findRes != queryParamsMap.end())
\r
805 response->setResourceRepresentation(rep, findRes->second);
\r
809 response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
\r
814 void setRepresentation(OCRepresentation& light)
\r
816 AttributeMap attributeMap = light.getAttributeMap();
\r
818 if(attributeMap.find("state") != attributeMap.end() && attributeMap.find("power") != attributeMap.end())
\r
820 cout << "\t\t\t" << "Received representation: " << endl;
\r
821 cout << "\t\t\t\t" << "power: " << attributeMap["power"][0] << endl;
\r
822 cout << "\t\t\t\t" << "state: " << attributeMap["state"][0] << endl;
\r
824 m_state = attributeMap["state"][0].compare("true") == 0;
\r
825 m_power= std::stoi(attributeMap["power"][0]);
\r
829 OCRepresentation getRepresentation()
\r
831 OCRepresentation light;
\r
833 light.setUri(m_lightUri);
\r
835 std::vector<std::string> interfaces;
\r
836 //interfaces.push_back(m_lightInterface);
\r
838 light.setResourceInterfaces(interfaces);
\r
840 std::vector<std::string> types;
\r
841 //types.push_back(m_lightType);
\r
843 light.setResourceTypes(types);
\r
845 AttributeMap attributeMap;
\r
846 AttributeValues stateVal;
\r
849 stateVal.push_back("true");
\r
853 stateVal.push_back("false");
\r
856 AttributeValues powerVal;
\r
857 powerVal.push_back(to_string(m_power));
\r
859 attributeMap["state"] = stateVal;
\r
860 attributeMap["power"] = powerVal;
\r
862 light.setAttributeMap(attributeMap);
\r
870 @section PUT_OTA_Response Over the air request
\r
872 In this example, we are pushing state to one of the lights. At this point, the resource was discovered by its type, and we understand its interface and the attributes exposed by the resource.
\r
874 <table cellspacing="0" cellpadding="0" border=1>
\r
877 <td valign="top" ><p>Field</p></td>
\r
878 <td valign="top" ><p>Value</p></td>
\r
879 <td valign="top" ><p>Note(s)</p></td>
\r
883 <td valign="top" ><p>Address</p></td>
\r
884 <td valign="top" ><p>192.168.1.13:5683</p></td>
\r
885 <td valign="top" ><p>Unicast packet</p></td>
\r
889 <td valign="top" ><p>Header</p></td>
\r
890 <td valign="top" ><p>CON, PUT, MID=0x7d41</p></td>
\r
891 <td valign="top" ><p>Confirmation is requested</p></td>
\r
895 <td valign="top" ><p>URI-Path</p></td>
\r
896 <td valign="top" ><p>light</p></td>
\r
897 <td rowspan="2" valign="top" ><p>"/light/1"</p></td>
\r
901 <td valign="top" ><p>URI-Path</p></td>
\r
902 <td valign="top" ><p>1</p></td>
\r
906 <td valign="top" ><p>Content-Type</p></td>
\r
907 <td valign="top" ><p>application/json</p></td>
\r
908 <td valign="top" ><p><br />
\r
913 <td valign="top" ><p>Payload</p></td>
\r
914 <td valign="top" ><p>{</p>
\r
916 <p>"power" : 1,</p>
\r
921 <td valign="top" ><p><br />
\r
928 @section PUT_OTA_Response Over the air response(s)
\r
930 Assuming that the request is valid and the resource is able to complete the transition, the following represents a successful change in state.
\r
932 <b>From 192.168.1.13</b>:
\r
934 <table cellspacing="0" cellpadding="0" border=1>
\r
937 <td valign="top" ><p>Field</p></td>
\r
938 <td valign="top" ><p>Value</p></td>
\r
939 <td valign="top" ><p>Explanation</p></td>
\r
943 <td valign="top" ><p>Address</p></td>
\r
944 <td valign="top" ><p>192.168.1.1:5683</p></td>
\r
945 <td valign="top" ><p>Client Address</p></td>
\r
949 <td valign="top" ><p>Header</p></td>
\r
950 <td valign="top" ><p>ACK, CHANGED, MID=0x7d41</p></td>
\r
951 <td valign="top" ><p>Success (changed)</p></td>
\r
958 **********************************************************************
\r
960 @page Guide_GET Querying resource State [GET]
\r
962 This operation fetches the value of a simple resource. In this example, we fetch the state from the light resource.
\r
964 @section GET_SD Sequence Diagram
\r
965 @image HTML seq_get.png
\r
968 1. The client application calls resource.get(...) to retrieve a representation from the resources.
\r
969 2. The call is marshalled to the stack which is either running in-process or out-of-process (daemon).
\r
970 3. The C API is called to dispatch the request. The call may look like the following:
\r
971 OCDoResource(OC_REST_GET, "//192.168.1.11/light/1, 0, 0, OC_CONFIRMABLE, callback);
\r
972 4. Where CoAP is used as a transport, the lower stack will send a GET request to the target server.
\r
973 5. On the server side, the OCProcess() function (message pump) receives and parses the request from the socket, then dispatches it to the correct entity handler based on the URI of the request.
\r
974 6. Where the C++ API is used, the C++ entity handler parses the payload and marshals it to the client application depending on if the server stack is running in-process or out-of-process (daemon).
\r
975 7. The C++ SDK passes it up the C++ handler associated with the OCResource.
\r
976 8. The handler returns the result code and representation to the SDK.
\r
977 9. The SDK marshals the result code and representation to the C++ entity handler.
\r
978 10. The entity handler returns the result code and representation to the CoAP protocol.
\r
979 11. The CoAP protocol transports the results to the client device.
\r
980 12. The results are returned the OCDoResource callback.
\r
981 13. The results are returned to the C++ client application's asyncResultCallback.
\r
983 @section GET_Client_CPP Querying resource State [GET] in C++ [Client]
\r
985 // Local function to get representation of light resource
\r
986 void getLightRepresentation(std::shared_ptr<OCResource> resource)
\r
990 std::cout << "Getting Light Representation..."<<std::endl;
\r
991 // Invoke resource's get API with the callback parameter
\r
993 QueryParamsMap test;
\r
994 resource->get(test, &onGet);
\r
998 // callback handler on GET request
\r
999 void onGet(const OCRepresentation& rep, const int eCode)
\r
1001 if(eCode == SUCCESS_RESPONSE)
\r
1003 std::cout << "GET request was successful" << std::endl;
\r
1005 AttributeMap attributeMap = rep.getAttributeMap();
\r
1007 std::cout << "Resource URI: " << rep.getUri() << std::endl;
\r
1009 for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
\r
1011 std::cout << "\tAttribute name: "<< it->first << " value: ";
\r
1012 for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
\r
1014 std::cout <<"\t"<< *valueItr << " ";
\r
1017 std::cout << std::endl;
\r
1020 std::vector<OCRepresentation> children = rep.getChildren();
\r
1022 for(auto oit = children.begin(); oit != children.end(); ++oit)
\r
1024 std::cout << "Child Resource URI: " << oit->getUri() << std::endl;
\r
1026 attributeMap = oit->getAttributeMap();
\r
1028 for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
\r
1030 std::cout << "\tAttribute name: "<< it->first << " value: ";
\r
1031 for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
\r
1033 std::cout <<"\t"<< *valueItr << " ";
\r
1036 std::cout << std::endl;
\r
1040 putLightRepresentation(curResource);
\r
1044 std::cout << "onGET Response error: " << eCode << std::endl;
\r
1052 @section GET_Server_CPP Querying resource State [GET] in C++ [Server]
\r
1055 // Handling GET request in Entity handler
\r
1056 if(requestType == "GET")
\r
1058 cout << "\t\t\trequestType : GET\n";
\r
1060 // Check for query params (if any)
\r
1061 QueryParamsMap queryParamsMap = request->getQueryParameters();
\r
1063 cout << "\t\t\tquery params: \n";
\r
1064 for(QueryParamsMap::iterator it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
\r
1066 cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
\r
1069 // Process query params and do required operations ..
\r
1071 // Get the representation of this resource at this point and send it as response
\r
1072 // AttributeMap attributeMap;
\r
1073 OCRepresentation rep;
\r
1074 rep = myLightResource.getRepresentation();
\r
1078 // TODO Error Code
\r
1079 response->setErrorCode(200);
\r
1081 auto findRes = queryParamsMap.find("if");
\r
1083 if(findRes != queryParamsMap.end())
\r
1085 response->setResourceRepresentation(rep, findRes->second);
\r
1089 response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
\r
1098 @section GET_OTA_Response Over the air request
\r
1100 In this example, we are querying state from one of the lights. At this point, the resource was discovered by its type, and we understand its interface and the attributes that the resource exposes.
\r
1102 <table cellspacing="0" cellpadding="0" border=1>
\r
1105 <td valign="top" ><p>Field</p></td>
\r
1106 <td valign="top" ><p>Value</p></td>
\r
1107 <td valign="top" ><p>Note(s)</p></td>
\r
1111 <td valign="top" ><p>Address</p></td>
\r
1112 <td valign="top" ><p>192.168.1.11:5683</p></td>
\r
1113 <td valign="top" ><p>Unicast packet</p></td>
\r
1117 <td valign="top" ><p>Header</p></td>
\r
1118 <td valign="top" ><p>CON, GET, MID=0x7d42</p></td>
\r
1119 <td valign="top" ><p>Confirmation is requested</p></td>
\r
1123 <td valign="top" ><p>URI-Path</p></td>
\r
1124 <td valign="top" ><p>light</p></td>
\r
1125 <td rowspan="2" valign="top" ><p>"/light/1"</p></td>
\r
1129 <td valign="top" ><p>URI-Path</p></td>
\r
1130 <td valign="top" ><p>1</p></td>
\r
1134 <td valign="top" ><p>Accept</p></td>
\r
1135 <td valign="top" ><p>application/json</p></td>
\r
1136 <td valign="top" ><p><br />
\r
1144 @section GET_OTA_Response Over the air response(s)
\r
1146 Assuming that the request is valid, we expect the following reply from the resource.
\r
1148 <b>From 192.168.1.11</b>:
\r
1150 <table cellspacing="0" cellpadding="0" border=1>
\r
1152 <td valign="top" ><p>Field</p></td>
\r
1153 <td valign="top" ><p>Value</p></td>
\r
1154 <td valign="top" ><p>Explanation</p></td>
\r
1158 <td valign="top" ><p>Address</p></td>
\r
1159 <td valign="top" ><p>192.168.1.1:5683</p></td>
\r
1160 <td valign="top" ><p>Client Address</p></td>
\r
1164 <td valign="top" ><p>Header</p></td>
\r
1165 <td valign="top" ><p>ACK, CONTENT, MID=0x7d42</p></td>
\r
1166 <td valign="top" ><p>Success w/Content</p></td>
\r
1170 <td valign="top" ><p>Content</p>
\r
1173 <td valign="top" ><p>application/json</p></td>
\r
1174 <td valign="top" ><p><br />
\r
1179 <td valign="top" ><p>Payload</p></td>
\r
1180 <td valign="top" ><p>{</p>
\r
1182 <p>"power" : 0,</p>
\r
1184 <p>"level" : 10</p>
\r
1187 <td valign="top" ><p><br />
\r
1196 **********************************************************************
\r
1198 @page Guide_Observe Observing resource state [Observe]
\r
1200 This operation fetches and registers as an observer for the value of a simple resource. In this example, we fetch the state of the light resource. For more implementation details, see "Observing Resources in CoAP" listed in the referenced documents. (https://datatracker.ietf.org/doc/draft-ietf-core-observe/?include_text=1)
\r
1202 The handling of observation registration is application specific. It should not be assumed that a resource is observable, or a resource can handle any specific number of observers. If the server responds with a success (2.xx) code, the registration is considered successful.
\r
1204 Notifications from the server to the client may be confirmable or non-confirmable. If the client returns a RST message, the observation registration should be dropped immediately. If the client fails to acknowledge a number of confirmable requests, the server should assume that the client has abandoned the observation and drop the registration.
\r
1206 If the observed resource is removed, the server sends a NOTFOUND status to all observers.
\r
1208 If an observed resource fails to notify a client before the max-age of a resource value update, the client should attempt to re-register the observation.
\r
1211 @section Observe_SD Sequence Diagram
\r
1212 @image HTML seq_observe.png
\r
1215 1. The client application calls resource.observe(...) to retrieve a representation from the resources.
\r
1216 2. The call is marshalled to the stack which is either running in-process or out-of-process (daemon).
\r
1217 3. The C API is called to dispatch the request. The call may look like this:
\r
1218 OCDoResource(OC_REST_GET | OC_REST_OBSERVE, "//192.168.1.11/light/1, 0, 0, OC_CONFIRMABLE, callback);
\r
1219 4. Where CoAP is used as a transport, the lower stack will send a GET request to the target server. The primary difference between a GET request and an observe request is that the observe request contains an observe option indicating that, in addition to querying this resource, the client wishes to get notifications if/when the resource state changes.
\r
1220 5. On the server side, the OCProcess() function (message pump) receives and parses the request from the socket, then dispatches it to the correct entity handler based on the URI of the request. The request to the entity handler will indicate that the request is both a query and subscription request. The entity handler MAY take note of this, but it is not responsible to tracking the observers. The stack tracks the observers of record.
\r
1221 6. Where the C++ API is used the C++ entity handler parses the payload and marshals it to the client application depending on if the server stack is running in-process or out-of-process (daemon).
\r
1222 7. The C++ SDK passes it up the C++ handler associated with the OCResource.
\r
1223 8. The handler returns the result code and representation to the SDK.
\r
1224 9. The SDK marshals the result code and representation to the C++ entity handler.
\r
1225 10. The entity handler returns the result code and representation to the CoAP protocol.
\r
1226 11. The CoAP protocol transport the results to the client device.
\r
1227 12. The results are returned to the OCDoResource callback.
\r
1228 13. The results are returned to the C++ client application's asyncResultCallback.
\r
1229 14. If the entity handler has registered observers, it will periodically be called with the observe flag set so that it may sample or poll underlying hardware to determine if the state has changes.
\r
1230 15. When the application has deemed that the resource state has changed either via polling (entity handler observe) or via external signal, the application should call OCNotifyObservers(). This tells the stack the observers need updating.
\r
1231 16. For each observer of a changed resource, the entity handler is called to generate a representation that is transmitted to the observing clients.
\r
1232 17. Where CoAP is used as a transport, a packet with content is sent to the devices that have observing clients. The packets may be confirmable or non-confirmable based on application needs.
\r
1233 18. The client-side OCProcess function (message pump) receives the message and matches it to the original request based on the CoAP token ID and dispatches the appropriate
\r
1235 19. The C API callback passes the final results to the C++ client application's asyncResultCallback.
\r
1236 20. When the C++ client no longer desires to receive notifications from the server, it calls observation cancellation method cancelObserve().
\r
1237 21. The C++ cancellation method calls the OCCancel() function from the C API.
\r
1238 22. OCCancel() finds the observation that is associated with the operation and sends an observe deregistration request to the server.
\r
1241 @section Observe_Client_CPP Observing resource state [Observe] in C++ [Client]
\r
1243 if (OBSERVE_TYPE_TO_USE == ObserveType::Observe)
\r
1244 std::cout << endl << "Observe is used." << endl << endl;
\r
1245 else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
\r
1246 std::cout << endl << "ObserveAll is used." << endl << endl;
\r
1248 QueryParamsMap test;
\r
1250 curResource->observe(OBSERVE_TYPE_TO_USE, test, &onObserve);
\r
1253 void onObserve(const OCRepresentation& rep, const int& eCode, const int& sequenceNumber)
\r
1255 if(eCode == SUCCESS_RESPONSE)
\r
1257 AttributeMap attributeMap = rep.getAttributeMap();
\r
1259 std::cout << "OBSERVE RESULT:"<<std::endl;
\r
1260 std::cout << "\tSequenceNumber: "<< sequenceNumber << endl;
\r
1261 for(auto it = attributeMap.begin(); it != attributeMap.end(); ++it)
\r
1263 std::cout << "\tAttribute name: "<< it->first << " value: ";
\r
1264 for(auto valueItr = it->second.begin(); valueItr != it->second.end(); ++valueItr)
\r
1266 std::cout <<"\t"<< *valueItr << " ";
\r
1269 std::cout << std::endl;
\r
1272 if(observe_count() > 30)
\r
1274 std::cout<<"Cancelling Observe..."<<std::endl;
\r
1275 OCStackResult result = curResource->cancelObserve();
\r
1277 std::cout << "Cancel result: "<< result <<std::endl;
\r
1279 std::cout << "DONE"<<std::endl;
\r
1285 std::cout << "onObserve Response error: " << eCode << std::endl;
\r
1295 @section Observe_Server_CPP Observing resource state [Observe] in C++ [Server]
\r
1297 // Handling observe in server's entity handler
\r
1298 if(requestFlag == RequestHandlerFlag::ObserverFlag)
\r
1300 pthread_t threadId;
\r
1302 cout << "\t\trequestFlag : Observer\n";
\r
1305 static int startedThread = 0;
\r
1307 // Observation happens on a different thread in ChangeLightRepresentation function.
\r
1308 // If we have not created the thread already, we will create one here.
\r
1309 if(!startedThread)
\r
1311 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
\r
1312 startedThread = 1;
\r
1315 // ChangeLightRepresentaion is an observation function,
\r
1316 // which notifies any changes to the resource to stack
\r
1317 // via notifyObservers
\r
1318 void * ChangeLightRepresentation (void *param)
\r
1320 // This function continuously monitors for the changes
\r
1327 // If under observation if there are any changes to the light resource
\r
1328 // we call notifyObservors
\r
1330 // For demostration we are changing the power value and notifying.
\r
1331 myLightResource.m_power += 10;
\r
1333 cout << "\nPower updated to : " << myLightResource.m_power << endl;
\r
1334 cout << "Notifying observers with resource handle: " << myLightResource.getHandle() << endl;
\r
1336 OCStackResult result = OCPlatform::notifyObservers(myLightResource.getHandle());
\r
1338 if(OC_STACK_NO_OBSERVERS == result)
\r
1340 cout << "No More observers, stopping notifications" << endl;
\r
1355 @section Oberve_OTA_Response Over the air request
\r
1357 The following observation request is basically a GET request with the observation option set.
\r
1359 <table cellspacing="0" cellpadding="0" border=1>
\r
1361 <td valign="top" ><p>Fields</p></td>
\r
1362 <td valign="top" ><p>Value</p></td>
\r
1363 <td valign="top" ><p>Notes</p></td>
\r
1367 <td valign="top" ><p>Address</p></td>
\r
1368 <td valign="top" ><p>192.168.1.11:5683</p></td>
\r
1369 <td valign="top" ><p>Unicast packet</p></td>
\r
1373 <td valign="top" ><p>Header</p></td>
\r
1374 <td valign="top" ><p>CON, GET, MID=0x7d44, TOK=0x3f</p></td>
\r
1375 <td valign="top" ><p>Confirmation requested</p></td>
\r
1379 <td valign="top" ><p>Observe</p></td>
\r
1380 <td valign="top" ><p>Register (0)</p></td>
\r
1381 <td valign="top" ><p>This indicates registration</p></td>
\r
1385 <td valign="top" ><p>URI-Path</p></td>
\r
1386 <td valign="top" ><p>Light</p></td>
\r
1387 <td valign="top" ><p>"/light/1 "</p></td>
\r
1391 <td valign="top" ><p>URI-Path</p></td>
\r
1392 <td valign="top" ><p>1</p></td>
\r
1393 <td valign="top" ><p><br />
\r
1398 <td valign="top" ><p>Accept</p></td>
\r
1399 <td valign="top" ><p>application/json</p></td>
\r
1400 <td valign="top" ><p>Requesting result in JSON</p></td>
\r
1407 @section Observe_OTA_Response Over the air response(s)
\r
1409 A successful observe request would be similar to the following:
\r
1411 <table cellspacing="0" cellpadding="0" border=1>
\r
1413 <td valign="top" ><p>Field</p></td>
\r
1414 <td valign="top" ><p>Value</p></td>
\r
1415 <td valign="top" ><p>Explanation</p></td>
\r
1419 <td valign="top" ><p>Address</p></td>
\r
1420 <td valign="top" ><p>192.168.1.1:5683</p></td>
\r
1421 <td valign="top" ><p>Client Address</p></td>
\r
1425 <td valign="top" ><p>Header</p></td>
\r
1426 <td valign="top" ><p>ACK, CONTENT, MID=0x7d44, TOK=0x3f</p></td>
\r
1427 <td valign="top" ><p>Success w/content</p></td>
\r
1431 <td valign="top" ><p>Observe</p></td>
\r
1432 <td valign="top" ><p>12</p></td>
\r
1433 <td valign="top" ><p>Sequence number for ordering</p></td>
\r
1437 <td valign="top" ><p>Max-Age</p></td>
\r
1438 <td valign="top" ><p>30</p></td>
\r
1439 <td valign="top" ><p>Indicates that the value is fresh for 30 seconds.</p>
\r
1441 <p>It also indicates that the server should send an</p>
\r
1443 <p>update within this time period.</p></td>
\r
1447 <td valign="top" ><p>Content</p>
\r
1450 <td valign="top" ><p>application/json</p></td>
\r
1451 <td valign="top" ><p><br />
\r
1456 <td valign="top" ><p>Payload</p></td>
\r
1457 <td valign="top" ><p>{</p>
\r
1459 <p>"power" : 0,</p>
\r
1461 <p>"level" : 10</p>
\r
1464 <td valign="top" ><p><br />
\r
1470 <b>Subsequent Notifications from 192.168.1.1 </b>
\r
1472 If the light resource is being observed and the light transitions from an off state to an on state, a notification is sent to the client from the server. The following is an example of such a notification:
\r
1475 <table cellspacing="0" cellpadding="0" border=1>
\r
1477 <td valign="top" ><p>Field</p></td>
\r
1478 <td valign="top" ><p>Value</p></td>
\r
1479 <td valign="top" ><p>Explanation</p></td>
\r
1483 <td valign="top" ><p>Address</p></td>
\r
1484 <td valign="top" ><p>192.168.1.1:5683</p></td>
\r
1485 <td valign="top" ><p>Client Address</p></td>
\r
1489 <td valign="top" ><p>Header</p></td>
\r
1490 <td valign="top" ><p>CON, CONTENT, MID=0x7D45, TOK=0x3f</p></td>
\r
1491 <td valign="top" ><p>Content, Can be confirmable or non-confirmable</p></td>
\r
1495 <td valign="top" ><p>Observe</p></td>
\r
1496 <td valign="top" ><p>15</p></td>
\r
1497 <td valign="top" ><p>Monotonically increasing until overflow</p></td>
\r
1501 <td valign="top" ><p>Max-Age</p></td>
\r
1502 <td valign="top" ><p>30</p></td>
\r
1503 <td valign="top" ><p>Indicates that the value is fresh for 30 seconds.</p>
\r
1505 <p>It also indicates that the server should send an</p>
\r
1507 <p>update within this time period.</p></td>
\r
1511 <td valign="top" ><p>Payload</p></td>
\r
1512 <td valign="top" ><p>{</p>
\r
1514 <p>"power" : 1,</p>
\r
1516 <p>"level" : 10</p>
\r
1519 <td valign="top" ><p><br />
\r
1525 Since the above notification was marked confirmable, the client should acknowledge the notification with a packet such as the following:
\r
1527 <table cellspacing="0" cellpadding="0" border=1>
\r
1530 <td valign="top" ><p>Field</p></td>
\r
1531 <td valign="top" ><p>Value</p></td>
\r
1532 <td valign="top" ><p>Explanation</p></td>
\r
1536 <td valign="top" ><p>Address</p></td>
\r
1537 <td valign="top" ><p>192.168.1.11:5683</p></td>
\r
1538 <td valign="top" ><p>Unicast packet</p></td>
\r
1542 <td valign="top" ><p>Header</p></td>
\r
1543 <td valign="top" ><p>ACK, MID=0x7D45, TOK=0x3f</p></td>
\r
1544 <td valign="top" ><p>Success</p></td>
\r
1553 **********************************************************************
\r