1c87c5fbaSopenharmony_ci// -*- mode:doc; -*- 2c87c5fbaSopenharmony_ci// vim: set syntax=asciidoc tw=0 3c87c5fbaSopenharmony_ci 4c87c5fbaSopenharmony_cicoap_observe(3) 5c87c5fbaSopenharmony_ci=============== 6c87c5fbaSopenharmony_ci:doctype: manpage 7c87c5fbaSopenharmony_ci:man source: coap_observe 8c87c5fbaSopenharmony_ci:man version: @PACKAGE_VERSION@ 9c87c5fbaSopenharmony_ci:man manual: libcoap Manual 10c87c5fbaSopenharmony_ci 11c87c5fbaSopenharmony_ciNAME 12c87c5fbaSopenharmony_ci---- 13c87c5fbaSopenharmony_cicoap_observe, 14c87c5fbaSopenharmony_cicoap_resource_set_get_observable, 15c87c5fbaSopenharmony_cicoap_resource_notify_observers, 16c87c5fbaSopenharmony_cicoap_cancel_observe, 17c87c5fbaSopenharmony_cicoap_session_set_no_observe_cancel 18c87c5fbaSopenharmony_ci- Work with CoAP observe 19c87c5fbaSopenharmony_ci 20c87c5fbaSopenharmony_ciSYNOPSIS 21c87c5fbaSopenharmony_ci-------- 22c87c5fbaSopenharmony_ci*#include <coap@LIBCOAP_API_VERSION@/coap.h>* 23c87c5fbaSopenharmony_ci 24c87c5fbaSopenharmony_ci*void coap_resource_set_get_observable(coap_resource_t *_resource_, 25c87c5fbaSopenharmony_ciint _mode_);* 26c87c5fbaSopenharmony_ci 27c87c5fbaSopenharmony_ci*int coap_resource_notify_observers(coap_resource_t *_resource_, 28c87c5fbaSopenharmony_ciconst coap_string_t *_query_);* 29c87c5fbaSopenharmony_ci 30c87c5fbaSopenharmony_ci*int coap_cancel_observe(coap_session_t *_session_, coap_binary_t *_token_, 31c87c5fbaSopenharmony_cicoap_pdu_type_t _message_type_);* 32c87c5fbaSopenharmony_ci 33c87c5fbaSopenharmony_ci*void coap_session_set_no_observe_cancel(coap_session_t *_session_);* 34c87c5fbaSopenharmony_ci 35c87c5fbaSopenharmony_ciFor specific (D)TLS library support, link with 36c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, 37c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* 38c87c5fbaSopenharmony_cior *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with 39c87c5fbaSopenharmony_ci*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. 40c87c5fbaSopenharmony_ci 41c87c5fbaSopenharmony_ciDESCRIPTION 42c87c5fbaSopenharmony_ci----------- 43c87c5fbaSopenharmony_cihttps://rfc-editor.org/rfc/rfc7641[RFC7641] extends the CoAP protocol to be 44c87c5fbaSopenharmony_ciable to monitor the state of a resource over time. 45c87c5fbaSopenharmony_ci 46c87c5fbaSopenharmony_ciThis enables clients to "observe" resources with a defined query, i.e., to 47c87c5fbaSopenharmony_ciretrieve a representation of a resource and keep this representation updated 48c87c5fbaSopenharmony_ciby the server over a period of time. 49c87c5fbaSopenharmony_ci 50c87c5fbaSopenharmony_ciThe server has to flag a resource as "observable", and then the client has 51c87c5fbaSopenharmony_cito request in a GET request that it wants to observe this resource by the use 52c87c5fbaSopenharmony_ciof the COAP_OPTION_OBSERVE Option with a value of COAP_OBSERVE_ESTABLISH. 53c87c5fbaSopenharmony_ciOptionally, the client can specify query options for the resource, or by using 54c87c5fbaSopenharmony_cia FETCH request instead of a GET to define a query 55c87c5fbaSopenharmony_ci(https://rfc-editor.org/rfc/rfc8132[RFC8132]). 56c87c5fbaSopenharmony_ci 57c87c5fbaSopenharmony_ciTo remove the "observe" subscription, the client has to issue a GET (or FETCH) 58c87c5fbaSopenharmony_cirequest with the COAP_OPTION_OBSERVE Option with a value of 59c87c5fbaSopenharmony_ciCOAP_OBSERVE_CANCEL using the same token and other options used for making the 60c87c5fbaSopenharmony_ciinitial "observe" request. Alternatively, "observe" can be cancelled using 61c87c5fbaSopenharmony_ci*coap_cancel_observe*() instead. 62c87c5fbaSopenharmony_ci 63c87c5fbaSopenharmony_ciThe underlying library adds in and removes "subscribers" to "observe" the 64c87c5fbaSopenharmony_ciresource as appropriate in the server side logic. 65c87c5fbaSopenharmony_ci 66c87c5fbaSopenharmony_ci*NOTE:* COAP_RESOURCE_MAX_SUBSCRIBER may have been defined to limit the number 67c87c5fbaSopenharmony_ciof subscribers to a resource when libcoap was built. 68c87c5fbaSopenharmony_ci 69c87c5fbaSopenharmony_ciWithin the server application, it needs to determine that there is a change of 70c87c5fbaSopenharmony_cistate of the resource under observation, and then cause the CoAP library 71c87c5fbaSopenharmony_cilayer to initiate a "fake GET/FETCH request" so that an observe GET/FETCH 72c87c5fbaSopenharmony_ciresponse gets sent back to all the clients that are observing the resource. The 73c87c5fbaSopenharmony_ciappropriate GET/FETCH handler within the server application is called to fill 74c87c5fbaSopenharmony_ciin the response packet with the appropriate information. This "fake GET/FETCH 75c87c5fbaSopenharmony_cirequest" is triggered by a call to *coap_resource_notify_observers*(). 76c87c5fbaSopenharmony_ci 77c87c5fbaSopenharmony_ciThe call to *coap_io_process*() in the main server application i/o loop will do 78c87c5fbaSopenharmony_ciall the necessary processing of sending any outstanding "fake GET/FETCH 79c87c5fbaSopenharmony_cirequests". 80c87c5fbaSopenharmony_ci 81c87c5fbaSopenharmony_ciWhenever the server sends a copy of the state of the "observed" resource to 82c87c5fbaSopenharmony_cithe client, it will use the same token used by the client when the client 83c87c5fbaSopenharmony_cirequested the "observe" (or the last token used for a FETCH that spans 84c87c5fbaSopenharmony_cimultiple blocks). The client will receive this observe response 85c87c5fbaSopenharmony_ciin the handler defined by *coap_register_response_handler*(3) (with the token 86c87c5fbaSopenharmony_ciupdated to the initial token used by the client application for a large FETCH). 87c87c5fbaSopenharmony_ciIt is the responsibility of the client application to match the supplied token 88c87c5fbaSopenharmony_ciand update the appropriate internal information. 89c87c5fbaSopenharmony_ci 90c87c5fbaSopenharmony_ciFUNCTIONS 91c87c5fbaSopenharmony_ci--------- 92c87c5fbaSopenharmony_ci 93c87c5fbaSopenharmony_ci*Function: coap_resource_set_get_observable()* 94c87c5fbaSopenharmony_ci 95c87c5fbaSopenharmony_ciThe *coap_resource_set_get_observable*() function enables or disables the 96c87c5fbaSopenharmony_ciobservable status of the _resource_ by the setting of _mode_. If _mode_ is 97c87c5fbaSopenharmony_ci1, then the _resource_ is observable. If _mode_ is 0, then the 98c87c5fbaSopenharmony_ci_resource_ is no longer observable. 99c87c5fbaSopenharmony_ci 100c87c5fbaSopenharmony_ci*NOTE:* It is not possible for the Unknown Resource, created by 101c87c5fbaSopenharmony_ci*coap_resource_unknown_init*(3), to be observable as the Uri-Path is not known 102c87c5fbaSopenharmony_ciwhen libcoap creates a "fake GET/FETCH request". The Unknown Resource PUT 103c87c5fbaSopenharmony_cihandler must create a new resource and mark the resource as "observable" if 104c87c5fbaSopenharmony_cia specific resource needs to be observable. The application must then 105c87c5fbaSopenharmony_cimanage the deletion of the resource at the appropriate time. 106c87c5fbaSopenharmony_ci 107c87c5fbaSopenharmony_ci*NOTE:* The type (confirmable or non-confirmable) of the triggered observe 108c87c5fbaSopenharmony_ciGET response is determined not by the initial GET/FETCH request, but 109c87c5fbaSopenharmony_ciindependently by the server as per 110c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7641#section-3.5[RFC7641 3.5. Transmission]". 111c87c5fbaSopenharmony_ciThis is controlled by the flags (one of COAP_RESOURCE_FLAGS_NOTIFY_NON, 112c87c5fbaSopenharmony_ciCOAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS or COAP_RESOURCE_FLAGS_NOTIFY_CON) 113c87c5fbaSopenharmony_ciused when creating the resource using *coap_resource_init*(3). 114c87c5fbaSopenharmony_ci 115c87c5fbaSopenharmony_ci*NOTE:* Furthermore, the server must send at least one "observe" response as 116c87c5fbaSopenharmony_ciconfirmable, when generally sending non-confirmable, at least every 24 hours 117c87c5fbaSopenharmony_cias per "https://rfc-editor.org/rfc/rfc7641#section-4.5[RFC7641 118c87c5fbaSopenharmony_ci4.5. Transmission]". 119c87c5fbaSopenharmony_ciLibcoap automatically handles this by sending every fifth (COAP_OBS_MAX_NON) 120c87c5fbaSopenharmony_ciresponse as a confirmable response for detection that the client is still 121c87c5fbaSopenharmony_ciresponding unless if COAP_RESOURCE_FLAGS_NOTIFY_NON_ALWAYS is set, which is a 122c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7641#section-4.5[RFC7641 4.5. Transmission]" 123c87c5fbaSopenharmony_civiolation, where non-confirmable "observe" responses are always sent 124c87c5fbaSopenharmony_cias required by some higher layer protocols. 125c87c5fbaSopenharmony_ci 126c87c5fbaSopenharmony_ci*Function: coap_resource_notify_observers()* 127c87c5fbaSopenharmony_ci 128c87c5fbaSopenharmony_ciThe *coap_resource_notify_observers*() function needs to be called whenever the 129c87c5fbaSopenharmony_ciserver application determines that there has been a change to the state of 130c87c5fbaSopenharmony_ci_resource_. The _query_ parameter is obsolete and ignored. 131c87c5fbaSopenharmony_ci 132c87c5fbaSopenharmony_ci*Function: coap_cancel_observe()* 133c87c5fbaSopenharmony_ci 134c87c5fbaSopenharmony_ciThe *coap_cancel_observe*() function can be used by the client to cancel an 135c87c5fbaSopenharmony_ciobserve request that is being tracked. This will cause the 136c87c5fbaSopenharmony_ciappropriate PDU to be sent to the server to cancel the observation, based on 137c87c5fbaSopenharmony_cithe _session_ and _token_ used to set up the observe and the PDU is of type 138c87c5fbaSopenharmony_ci_message_type_ (use COAP_MESSAGE_NON or COAP_MESSAGE_CON). 139c87c5fbaSopenharmony_ci 140c87c5fbaSopenharmony_ci*Function: coap_session_set_no_observe_cancel()* 141c87c5fbaSopenharmony_ci 142c87c5fbaSopenharmony_ciThe *coap_session_set_no_observe_cancel*() function can be called by the 143c87c5fbaSopenharmony_ciclient to disable calling *coap_cancel_observe*() when the _session_ is being 144c87c5fbaSopenharmony_ciclosed down / freed off. *coap_cancel_observe*() can still be called directly 145c87c5fbaSopenharmony_ciby the client application. 146c87c5fbaSopenharmony_ci 147c87c5fbaSopenharmony_ciRETURN VALUES 148c87c5fbaSopenharmony_ci------------- 149c87c5fbaSopenharmony_ci*coap_resource_notify_observers*() returns 0 if not observable or 150c87c5fbaSopenharmony_cino observers, 1 on success. 151c87c5fbaSopenharmony_ci 152c87c5fbaSopenharmony_ci*coap_cancel_observe*() returns 0 on failure, 1 on success. 153c87c5fbaSopenharmony_ci 154c87c5fbaSopenharmony_ciEXAMPLES 155c87c5fbaSopenharmony_ci-------- 156c87c5fbaSopenharmony_ci*Simple Time Server* 157c87c5fbaSopenharmony_ci 158c87c5fbaSopenharmony_ci[source, c] 159c87c5fbaSopenharmony_ci---- 160c87c5fbaSopenharmony_ci#include <coap@LIBCOAP_API_VERSION@/coap.h> 161c87c5fbaSopenharmony_ci 162c87c5fbaSopenharmony_ci#include <stdio.h> 163c87c5fbaSopenharmony_ci 164c87c5fbaSopenharmony_cicoap_resource_t *time_resource = NULL; 165c87c5fbaSopenharmony_ci 166c87c5fbaSopenharmony_ci/* specific GET "time" handler, called from hnd_get_generic() */ 167c87c5fbaSopenharmony_ci 168c87c5fbaSopenharmony_cistatic void 169c87c5fbaSopenharmony_cihnd_get_time(coap_resource_t *resource, coap_session_t *session, 170c87c5fbaSopenharmony_ciconst coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { 171c87c5fbaSopenharmony_ci 172c87c5fbaSopenharmony_ci unsigned char buf[40]; 173c87c5fbaSopenharmony_ci size_t len; 174c87c5fbaSopenharmony_ci time_t now; 175c87c5fbaSopenharmony_ci (void)resource; 176c87c5fbaSopenharmony_ci (void)session; 177c87c5fbaSopenharmony_ci 178c87c5fbaSopenharmony_ci /* ... Additional analysis code for resource, request pdu etc. ... */ 179c87c5fbaSopenharmony_ci 180c87c5fbaSopenharmony_ci /* After analysis, generate a suitable response */ 181c87c5fbaSopenharmony_ci 182c87c5fbaSopenharmony_ci /* Note that token, if set, is already in the response pdu */ 183c87c5fbaSopenharmony_ci 184c87c5fbaSopenharmony_ci now = time(NULL); 185c87c5fbaSopenharmony_ci 186c87c5fbaSopenharmony_ci if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) { 187c87c5fbaSopenharmony_ci /* Output secs since Jan 1 1970 */ 188c87c5fbaSopenharmony_ci len = snprintf((char *)buf, sizeof(buf), "%lu", now); 189c87c5fbaSopenharmony_ci } 190c87c5fbaSopenharmony_ci else { 191c87c5fbaSopenharmony_ci /* Output human-readable time */ 192c87c5fbaSopenharmony_ci struct tm *tmp; 193c87c5fbaSopenharmony_ci tmp = gmtime(&now); 194c87c5fbaSopenharmony_ci if (!tmp) { 195c87c5fbaSopenharmony_ci /* If 'now' is not valid */ 196c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); 197c87c5fbaSopenharmony_ci return; 198c87c5fbaSopenharmony_ci } 199c87c5fbaSopenharmony_ci len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp); 200c87c5fbaSopenharmony_ci } 201c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 202c87c5fbaSopenharmony_ci /* 203c87c5fbaSopenharmony_ci * Invoke coap_add_data_large_response() to do all the hard work. 204c87c5fbaSopenharmony_ci * 205c87c5fbaSopenharmony_ci * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in 206c87c5fbaSopenharmony_ci * Define how long this response is valid for (secs) - 1 - to add in. 207c87c5fbaSopenharmony_ci * ETAG Option added internally with unique value as param set to 0 208c87c5fbaSopenharmony_ci * 209c87c5fbaSopenharmony_ci * OBSERVE Option added internally if needed within the function 210c87c5fbaSopenharmony_ci * BLOCK2 Option added internally if output too large 211c87c5fbaSopenharmony_ci * SIZE2 Option added internally 212c87c5fbaSopenharmony_ci */ 213c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 214c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0, 215c87c5fbaSopenharmony_ci len, 216c87c5fbaSopenharmony_ci buf, NULL, NULL); 217c87c5fbaSopenharmony_ci} 218c87c5fbaSopenharmony_ci 219c87c5fbaSopenharmony_ci/* Generic GET handler */ 220c87c5fbaSopenharmony_ci 221c87c5fbaSopenharmony_cistatic void 222c87c5fbaSopenharmony_cihnd_get_generic(coap_resource_t *resource, coap_session_t *session, 223c87c5fbaSopenharmony_ciconst coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { 224c87c5fbaSopenharmony_ci 225c87c5fbaSopenharmony_ci coap_str_const_t *uri_path = coap_resource_get_uri_path(resource); 226c87c5fbaSopenharmony_ci 227c87c5fbaSopenharmony_ci if (!uri_path) { 228c87c5fbaSopenharmony_ci /* Unexpected Failure */ 229c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); 230c87c5fbaSopenharmony_ci return; 231c87c5fbaSopenharmony_ci } 232c87c5fbaSopenharmony_ci 233c87c5fbaSopenharmony_ci /* Is this the "time" resource" ? */ 234c87c5fbaSopenharmony_ci if (coap_string_equal(uri_path, coap_make_str_const("time"))) { 235c87c5fbaSopenharmony_ci hnd_get_time(resource, session, request, query, response); 236c87c5fbaSopenharmony_ci return; 237c87c5fbaSopenharmony_ci } 238c87c5fbaSopenharmony_ci 239c87c5fbaSopenharmony_ci /* Other resources code */ 240c87c5fbaSopenharmony_ci 241c87c5fbaSopenharmony_ci /* Failure response */ 242c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); 243c87c5fbaSopenharmony_ci} 244c87c5fbaSopenharmony_ci 245c87c5fbaSopenharmony_ci/* Initialize generic GET handler */ 246c87c5fbaSopenharmony_ci 247c87c5fbaSopenharmony_cistatic void 248c87c5fbaSopenharmony_ciinit_resources(coap_context_t *ctx) 249c87c5fbaSopenharmony_ci{ 250c87c5fbaSopenharmony_ci 251c87c5fbaSopenharmony_ci coap_resource_t *r; 252c87c5fbaSopenharmony_ci 253c87c5fbaSopenharmony_ci /* Create a resource to return return or update time */ 254c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("time"), 255c87c5fbaSopenharmony_ci COAP_RESOURCE_FLAGS_NOTIFY_CON); 256c87c5fbaSopenharmony_ci 257c87c5fbaSopenharmony_ci /* We are using a generic GET handler here */ 258c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_generic); 259c87c5fbaSopenharmony_ci 260c87c5fbaSopenharmony_ci coap_resource_set_get_observable(r, 1); 261c87c5fbaSopenharmony_ci 262c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 263c87c5fbaSopenharmony_ci time_resource = r; 264c87c5fbaSopenharmony_ci 265c87c5fbaSopenharmony_ci} 266c87c5fbaSopenharmony_ci 267c87c5fbaSopenharmony_ciint 268c87c5fbaSopenharmony_cimain(int argc, char *argv[]) { 269c87c5fbaSopenharmony_ci 270c87c5fbaSopenharmony_ci coap_context_t *ctx = NULL; 271c87c5fbaSopenharmony_ci coap_endpoint_t *ep = NULL; 272c87c5fbaSopenharmony_ci coap_address_t addr; 273c87c5fbaSopenharmony_ci unsigned wait_ms; 274c87c5fbaSopenharmony_ci struct timeval tv_last = {0, 0}; 275c87c5fbaSopenharmony_ci 276c87c5fbaSopenharmony_ci /* Initialize libcoap library */ 277c87c5fbaSopenharmony_ci coap_startup(); 278c87c5fbaSopenharmony_ci 279c87c5fbaSopenharmony_ci /* Remove (void) definition if variable is used */ 280c87c5fbaSopenharmony_ci (void)argc; 281c87c5fbaSopenharmony_ci (void)argv; 282c87c5fbaSopenharmony_ci 283c87c5fbaSopenharmony_ci memset (&tv_last, 0, sizeof(tv_last)); 284c87c5fbaSopenharmony_ci 285c87c5fbaSopenharmony_ci /* Create the libcoap context */ 286c87c5fbaSopenharmony_ci ctx = coap_new_context(NULL); 287c87c5fbaSopenharmony_ci if (!ctx) { 288c87c5fbaSopenharmony_ci exit(1); 289c87c5fbaSopenharmony_ci } 290c87c5fbaSopenharmony_ci /* See coap_block(3) */ 291c87c5fbaSopenharmony_ci coap_context_set_block_mode(ctx, 292c87c5fbaSopenharmony_ci COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 293c87c5fbaSopenharmony_ci 294c87c5fbaSopenharmony_ci coap_address_init(&addr); 295c87c5fbaSopenharmony_ci addr.addr.sa.sa_family = AF_INET; 296c87c5fbaSopenharmony_ci addr.addr.sin.sin_port = ntohs(COAP_DEFAULT_PORT); 297c87c5fbaSopenharmony_ci ep = coap_new_endpoint(ctx, &addr, COAP_PROTO_UDP); 298c87c5fbaSopenharmony_ci 299c87c5fbaSopenharmony_ci /* Other Set up Code */ 300c87c5fbaSopenharmony_ci 301c87c5fbaSopenharmony_ci init_resources(ctx); 302c87c5fbaSopenharmony_ci 303c87c5fbaSopenharmony_ci wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; 304c87c5fbaSopenharmony_ci 305c87c5fbaSopenharmony_ci while (1) { 306c87c5fbaSopenharmony_ci int result = coap_io_process( ctx, wait_ms ); 307c87c5fbaSopenharmony_ci if ( result < 0 ) { 308c87c5fbaSopenharmony_ci break; 309c87c5fbaSopenharmony_ci } else if ( result && (unsigned)result < wait_ms ) { 310c87c5fbaSopenharmony_ci /* decrement if there is a result wait time returned */ 311c87c5fbaSopenharmony_ci wait_ms -= result; 312c87c5fbaSopenharmony_ci } else { 313c87c5fbaSopenharmony_ci /* 314c87c5fbaSopenharmony_ci * result == 0, or result >= wait_ms 315c87c5fbaSopenharmony_ci * (wait_ms could have decremented to a small value, below 316c87c5fbaSopenharmony_ci * the granularity of the timer in coap_io_process() and hence 317c87c5fbaSopenharmony_ci * result == 0) 318c87c5fbaSopenharmony_ci */ 319c87c5fbaSopenharmony_ci wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; 320c87c5fbaSopenharmony_ci } 321c87c5fbaSopenharmony_ci if (time_resource) { 322c87c5fbaSopenharmony_ci struct timeval tv_now; 323c87c5fbaSopenharmony_ci if (gettimeofday (&tv_now, NULL) == 0) { 324c87c5fbaSopenharmony_ci if (tv_last.tv_sec != tv_now.tv_sec) { 325c87c5fbaSopenharmony_ci /* Happens once per second */ 326c87c5fbaSopenharmony_ci tv_last = tv_now; 327c87c5fbaSopenharmony_ci coap_resource_notify_observers(time_resource, NULL); 328c87c5fbaSopenharmony_ci } 329c87c5fbaSopenharmony_ci /* need to wait until next second starts if wait_ms is too large */ 330c87c5fbaSopenharmony_ci unsigned next_sec_ms = 1000 - (tv_now.tv_usec / 1000); 331c87c5fbaSopenharmony_ci 332c87c5fbaSopenharmony_ci if (next_sec_ms && next_sec_ms < wait_ms) 333c87c5fbaSopenharmony_ci wait_ms = next_sec_ms; 334c87c5fbaSopenharmony_ci } 335c87c5fbaSopenharmony_ci } 336c87c5fbaSopenharmony_ci } 337c87c5fbaSopenharmony_ci coap_free_context(ctx); 338c87c5fbaSopenharmony_ci coap_cleanup(); 339c87c5fbaSopenharmony_ci exit(0); 340c87c5fbaSopenharmony_ci 341c87c5fbaSopenharmony_ci} 342c87c5fbaSopenharmony_ci---- 343c87c5fbaSopenharmony_ci 344c87c5fbaSopenharmony_ci*Client Observe Request Setup* 345c87c5fbaSopenharmony_ci 346c87c5fbaSopenharmony_ci[source, c] 347c87c5fbaSopenharmony_ci---- 348c87c5fbaSopenharmony_ci#include <coap@LIBCOAP_API_VERSION@/coap.h> 349c87c5fbaSopenharmony_ci 350c87c5fbaSopenharmony_ci/* Usually, requests are sent confirmable */ 351c87c5fbaSopenharmony_ci 352c87c5fbaSopenharmony_cistatic unsigned char msgtype = COAP_MESSAGE_CON; 353c87c5fbaSopenharmony_ci 354c87c5fbaSopenharmony_cistatic unsigned int token = 0; 355c87c5fbaSopenharmony_ci 356c87c5fbaSopenharmony_cistatic coap_pdu_t * 357c87c5fbaSopenharmony_cicoap_new_request(coap_context_t *context, coap_session_t *session, char request_code, 358c87c5fbaSopenharmony_cicoap_optlist_t **options, unsigned char *data, size_t length, int observe) { 359c87c5fbaSopenharmony_ci 360c87c5fbaSopenharmony_ci coap_pdu_t *pdu; 361c87c5fbaSopenharmony_ci /* Remove (void) definition if variable is used */ 362c87c5fbaSopenharmony_ci (void)context; 363c87c5fbaSopenharmony_ci 364c87c5fbaSopenharmony_ci /* Create the pdu with the appropriate options */ 365c87c5fbaSopenharmony_ci pdu = coap_pdu_init(msgtype, request_code, coap_new_message_id(session), 366c87c5fbaSopenharmony_ci coap_session_max_pdu_size(session)); 367c87c5fbaSopenharmony_ci if (!pdu) 368c87c5fbaSopenharmony_ci return NULL; 369c87c5fbaSopenharmony_ci 370c87c5fbaSopenharmony_ci /* 371c87c5fbaSopenharmony_ci * Create uniqueness token for this request for handling unsolicited / 372c87c5fbaSopenharmony_ci * delayed responses 373c87c5fbaSopenharmony_ci */ 374c87c5fbaSopenharmony_ci token++; 375c87c5fbaSopenharmony_ci if (!coap_add_token(pdu, sizeof(token), (unsigned char*)&token)) { 376c87c5fbaSopenharmony_ci coap_log_debug("cannot add token to request\n"); 377c87c5fbaSopenharmony_ci goto error; 378c87c5fbaSopenharmony_ci } 379c87c5fbaSopenharmony_ci 380c87c5fbaSopenharmony_ci if (request_code == COAP_REQUEST_GET && observe) { 381c87c5fbaSopenharmony_ci /* Indicate that we want to observe this resource */ 382c87c5fbaSopenharmony_ci if (!coap_insert_optlist(options, 383c87c5fbaSopenharmony_ci coap_new_optlist(COAP_OPTION_OBSERVE, 384c87c5fbaSopenharmony_ci COAP_OBSERVE_ESTABLISH, NULL))) 385c87c5fbaSopenharmony_ci goto error; 386c87c5fbaSopenharmony_ci } 387c87c5fbaSopenharmony_ci 388c87c5fbaSopenharmony_ci /* ... Other code / options etc. ... */ 389c87c5fbaSopenharmony_ci 390c87c5fbaSopenharmony_ci /* Add in all the options (after internal sorting) to the pdu */ 391c87c5fbaSopenharmony_ci if (!coap_add_optlist_pdu(pdu, options)) 392c87c5fbaSopenharmony_ci goto error; 393c87c5fbaSopenharmony_ci 394c87c5fbaSopenharmony_ci if (data && length) { 395c87c5fbaSopenharmony_ci /* Add in the specified data */ 396c87c5fbaSopenharmony_ci if (!coap_add_data(pdu, length, data)) 397c87c5fbaSopenharmony_ci goto error; 398c87c5fbaSopenharmony_ci } 399c87c5fbaSopenharmony_ci 400c87c5fbaSopenharmony_ci return pdu; 401c87c5fbaSopenharmony_ci 402c87c5fbaSopenharmony_cierror: 403c87c5fbaSopenharmony_ci 404c87c5fbaSopenharmony_ci coap_delete_pdu(pdu); 405c87c5fbaSopenharmony_ci return NULL; 406c87c5fbaSopenharmony_ci 407c87c5fbaSopenharmony_ci} 408c87c5fbaSopenharmony_ci---- 409c87c5fbaSopenharmony_ci 410c87c5fbaSopenharmony_ciSEE ALSO 411c87c5fbaSopenharmony_ci-------- 412c87c5fbaSopenharmony_ci*coap_block*(3), *coap_context*(3), *coap_handler*(3), *coap_init*(3), 413c87c5fbaSopenharmony_ci*coap_pdu_setup*(3), *coap_resource*(3) and *coap_session*(3) 414c87c5fbaSopenharmony_ci 415c87c5fbaSopenharmony_ciFURTHER INFORMATION 416c87c5fbaSopenharmony_ci------------------- 417c87c5fbaSopenharmony_ciSee 418c87c5fbaSopenharmony_ci 419c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7252[RFC7252: The Constrained Application Protocol (CoAP)]" 420c87c5fbaSopenharmony_ci 421c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc7641[RFC7641: Observing Resources in the Constrained Application Protocol (CoAP)]" 422c87c5fbaSopenharmony_ci 423c87c5fbaSopenharmony_ci"https://rfc-editor.org/rfc/rfc8132[RFC8132: PATCH and FETCH Methods for the Constrained Application Protocol (CoAP)]" 424c87c5fbaSopenharmony_ci 425c87c5fbaSopenharmony_cifor further information. 426c87c5fbaSopenharmony_ci 427c87c5fbaSopenharmony_ci 428c87c5fbaSopenharmony_ciBUGS 429c87c5fbaSopenharmony_ci---- 430c87c5fbaSopenharmony_ciPlease report bugs on the mailing list for libcoap: 431c87c5fbaSopenharmony_cilibcoap-developers@lists.sourceforge.net or raise an issue on GitHub at 432c87c5fbaSopenharmony_cihttps://github.com/obgm/libcoap/issues 433c87c5fbaSopenharmony_ci 434c87c5fbaSopenharmony_ciAUTHORS 435c87c5fbaSopenharmony_ci------- 436c87c5fbaSopenharmony_ciThe libcoap project <libcoap-developers@lists.sourceforge.net> 437