Revised Erbium observing.
This commit is contained in:
parent
4a02790c76
commit
dc6142fa0b
|
@ -58,7 +58,7 @@ LIST(observers_list);
|
|||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
coap_observer_t *
|
||||
coap_add_observer(const char *url, uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len)
|
||||
coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len, const char *url)
|
||||
{
|
||||
coap_observer_t *o = memb_alloc(&observers_memb);
|
||||
|
||||
|
@ -173,7 +173,7 @@ coap_observe_handler(resource_t *resource, void *request, void *response)
|
|||
{
|
||||
if (IS_OPTION((coap_packet_t *)request, COAP_OPTION_TOKEN))
|
||||
{
|
||||
if (coap_add_observer(resource->url, &UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, ((coap_packet_t *)request)->token, ((coap_packet_t *)request)->token_len))
|
||||
if (coap_add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, ((coap_packet_t *)request)->token, ((coap_packet_t *)request)->token_len, resource->url))
|
||||
{
|
||||
coap_set_header_observe(response, 0);
|
||||
coap_set_payload(response, (uint8_t *)content, snprintf(content, sizeof(content), "Added as observer %u/%u", list_length(observers_list), COAP_MAX_OBSERVERS));
|
||||
|
|
|
@ -65,7 +65,7 @@ typedef struct coap_observer {
|
|||
} coap_observer_t;
|
||||
|
||||
list_t coap_get_observers(void);
|
||||
coap_observer_t *coap_add_observer(const char *url, uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len);
|
||||
coap_observer_t *coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len, const char *url);
|
||||
void coap_remove_observer(coap_observer_t *o);
|
||||
int coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port);
|
||||
int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, uint8_t *token, size_t token_len);
|
||||
|
|
|
@ -745,7 +745,7 @@ coap_set_header_uri_query(void *packet, const char *query)
|
|||
/*- PAYLOAD -------------------------------------------------------------------------*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
int
|
||||
coap_get_payload(void *packet, const uint8_t **payload)
|
||||
coap_get_payload(void *packet, uint8_t **payload)
|
||||
{
|
||||
if (((coap_packet_t *)packet)->payload) {
|
||||
*payload = ((coap_packet_t *)packet)->payload;
|
||||
|
@ -757,11 +757,11 @@ coap_get_payload(void *packet, const uint8_t **payload)
|
|||
}
|
||||
|
||||
int
|
||||
coap_set_payload(void *packet, uint8_t *payload, size_t length)
|
||||
coap_set_payload(void *packet, const void *payload, size_t length)
|
||||
{
|
||||
PRINTF("setting payload (%u/%u)\n", length, REST_MAX_CHUNK_SIZE);
|
||||
|
||||
((coap_packet_t *)packet)->payload = payload;
|
||||
((coap_packet_t *)packet)->payload = (uint8_t *) payload;
|
||||
((coap_packet_t *)packet)->payload_len = MIN(REST_MAX_CHUNK_SIZE, length);
|
||||
|
||||
return ((coap_packet_t *)packet)->payload_len;
|
||||
|
|
|
@ -278,7 +278,7 @@ int coap_set_header_block(void *packet, uint32_t num, uint8_t more, uint16_t siz
|
|||
int coap_get_header_uri_query(void *packet, const char **query); /*CAUTION in-place string might not be 0-terminated */
|
||||
int coap_set_header_uri_query(void *packet, const char *query);
|
||||
|
||||
int coap_get_payload(void *packet, const uint8_t **payload);
|
||||
int coap_set_payload(void *packet, uint8_t *payload, size_t length);
|
||||
int coap_get_payload(void *packet, uint8_t **payload);
|
||||
int coap_set_payload(void *packet, const void *payload, size_t length);
|
||||
|
||||
#endif /* COAP_03_H_ */
|
||||
|
|
|
@ -225,8 +225,8 @@ handle_incoming_data(void)
|
|||
/* Cancel possible subscriptions. */
|
||||
if (IS_OPTION(message, COAP_OPTION_TOKEN))
|
||||
{
|
||||
PRINTF(" Token 0x%02X%02X\n", message->token[0], message->token[1]);
|
||||
coap_remove_observer_by_token(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, message->token, message->token_len);
|
||||
/* RST must be empty, so it is a full client reset. */
|
||||
coap_remove_observer_by_client(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ LIST(observers_list);
|
|||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
coap_observer_t *
|
||||
coap_add_observer(const char *url, uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len)
|
||||
coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len, const char *url)
|
||||
{
|
||||
coap_observer_t *o = memb_alloc(&observers_memb);
|
||||
|
||||
|
@ -125,7 +125,7 @@ coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, uint8_t *token,
|
|||
return removed;
|
||||
}
|
||||
int
|
||||
coap_remove_observer_by_url(const char *url)
|
||||
coap_remove_observer_by_url(uip_ipaddr_t *addr, uint16_t port, const char *url)
|
||||
{
|
||||
int removed = 0;
|
||||
coap_observer_t* obs = NULL;
|
||||
|
@ -133,7 +133,7 @@ coap_remove_observer_by_url(const char *url)
|
|||
for (obs = (coap_observer_t*)list_head(observers_list); obs; obs = obs->next)
|
||||
{
|
||||
PRINTF("Remove check URL %p\n", url);
|
||||
if (obs->url==url || memcmp(obs->url, url, strlen(obs->url))==0)
|
||||
if (uip_ipaddr_cmp(&obs->addr, addr) && obs->port==port && (obs->url==url || memcmp(obs->url, url, strlen(obs->url))==0))
|
||||
{
|
||||
coap_remove_observer(obs);
|
||||
removed++;
|
||||
|
@ -189,17 +189,21 @@ coap_observe_handler(resource_t *resource, void *request, void *response)
|
|||
coap_packet_t *const coap_req = (coap_packet_t *) request;
|
||||
coap_packet_t *const coap_res = (coap_packet_t *) response;
|
||||
|
||||
static char content[26];
|
||||
static char content[16];
|
||||
|
||||
if (coap_req->code==COAP_GET && coap_res && coap_res->code<128) /* GET request and response without error code */
|
||||
if (coap_req->code==COAP_GET && coap_res->code<128) /* GET request and response without error code */
|
||||
{
|
||||
if (IS_OPTION(coap_req, COAP_OPTION_OBSERVE))
|
||||
{
|
||||
|
||||
if (coap_add_observer(resource->url, &UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, coap_req->token, coap_req->token_len))
|
||||
if (coap_add_observer(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, coap_req->token, coap_req->token_len, resource->url))
|
||||
{
|
||||
coap_set_header_observe(coap_res, 0);
|
||||
coap_set_payload(coap_res, content, snprintf(content, sizeof(content), "Added as observer %u/%u", list_length(observers_list), COAP_MAX_OBSERVERS));
|
||||
/*
|
||||
* For demonstration purposes only. A subscription should return the same representation as a normal GET.
|
||||
* TODO: Comment the following line for any real application.
|
||||
*/
|
||||
coap_set_payload(coap_res, content, snprintf(content, sizeof(content), "Added %u/%u", list_length(observers_list), COAP_MAX_OBSERVERS));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -210,7 +214,7 @@ coap_observe_handler(resource_t *resource, void *request, void *response)
|
|||
else /* if (observe) */
|
||||
{
|
||||
/* Remove client if it is currently observing. */
|
||||
coap_remove_observer_by_client(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport);
|
||||
coap_remove_observer_by_url(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, resource->url);
|
||||
} /* if (observe) */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,12 +66,12 @@ typedef struct coap_observer {
|
|||
|
||||
list_t coap_get_observers(void);
|
||||
|
||||
coap_observer_t *coap_add_observer(const char *url, uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len);
|
||||
void coap_remove_observer(coap_observer_t *o);
|
||||
coap_observer_t *coap_add_observer(uip_ipaddr_t *addr, uint16_t port, const uint8_t *token, size_t token_len, const char *url);
|
||||
|
||||
void coap_remove_observer(coap_observer_t *o);
|
||||
int coap_remove_observer_by_client(uip_ipaddr_t *addr, uint16_t port);
|
||||
int coap_remove_observer_by_token(uip_ipaddr_t *addr, uint16_t port, uint8_t *token, size_t token_len);
|
||||
int coap_remove_observer_by_url(const char *url);
|
||||
int coap_remove_observer_by_url(uip_ipaddr_t *addr, uint16_t port, const char *url);
|
||||
|
||||
void coap_notify_observers(const char *url, int type, uint32_t observe, uint8_t *payload, size_t payload_len);
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
#define REST_RES_HELLO 1
|
||||
#define REST_RES_MIRROR 0 /* causes largest code size */
|
||||
#define REST_RES_CHUNKS 1
|
||||
#define REST_RES_POLLING 0
|
||||
#define REST_RES_SEPARATE 1
|
||||
#define REST_RES_PUSHING 1
|
||||
#define REST_RES_EVENT 1
|
||||
#define REST_RES_LEDS 1
|
||||
#define REST_RES_TOGGLE 1
|
||||
|
@ -313,8 +313,8 @@ chunks_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre
|
|||
REST.set_response_status(response, REST.status.BAD_OPTION);
|
||||
/* A block error message should not exceed the minimum block size (16). */
|
||||
|
||||
const char error_msg[] = "BlockOutOfScope";
|
||||
REST.set_response_payload(response, (uint8_t *)error_msg, sizeof(error_msg)-1);
|
||||
const char *error_msg = "BlockOutOfScope";
|
||||
REST.set_response_payload(response, error_msg, strlen(error_msg));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -349,47 +349,6 @@ chunks_handler(void* request, void* response, uint8_t *buffer, uint16_t preferre
|
|||
}
|
||||
#endif
|
||||
|
||||
#if REST_RES_POLLING
|
||||
/*
|
||||
* Example for a periodic resource.
|
||||
* It takes an additional period parameter, which defines the interval to call [name]_periodic_handler().
|
||||
* A default post_handler takes care of subscriptions by managing a list of subscribers to notify.
|
||||
*/
|
||||
PERIODIC_RESOURCE(polling, METHOD_GET, "debug/poll", "title=\"Periodic demo\";rt=\"Observable\"", 5*CLOCK_SECOND);
|
||||
|
||||
void
|
||||
polling_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
|
||||
|
||||
/* Usually, a CoAP server would response with the current resource representation. */
|
||||
const char msg[] = "It's periodic!";
|
||||
REST.set_response_payload(response, (uint8_t *)msg, sizeof(msg)-1);
|
||||
|
||||
/* A post_handler that handles subscriptions will be called for periodic resources by the REST framework. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE.
|
||||
* It will be called by the REST manager process with the defined period.
|
||||
*/
|
||||
int
|
||||
polling_periodic_handler(resource_t *r)
|
||||
{
|
||||
static uint32_t periodic_i = 0;
|
||||
static char content[16];
|
||||
|
||||
PRINTF("TICK /%s\n", r->url);
|
||||
periodic_i = periodic_i + 1;
|
||||
|
||||
/* Notify the registered observers with the given message type, observe option, and payload. */
|
||||
REST.notify_subscribers(r->url, 1, periodic_i, (uint8_t *)content, snprintf(content, sizeof(content), "TICK %lu", periodic_i));
|
||||
/* |-> implementation-specific, e.g. CoAP: 1=CON and 0=NON notification */
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if REST_RES_SEPARATE && WITH_COAP > 3
|
||||
/* Required to manually (=not by the engine) handle the response transaction. */
|
||||
#include "er-coap-07-separate.h"
|
||||
|
@ -413,8 +372,8 @@ separate_handler(void* request, void* response, uint8_t *buffer, uint16_t prefer
|
|||
if (separate_active)
|
||||
{
|
||||
REST.set_response_status(response, REST.status.SERVICE_UNAVAILABLE);
|
||||
const char msg[] = "AlreadyInUse";
|
||||
REST.set_response_payload(response, (uint8_t *)msg, sizeof(msg)-1);
|
||||
const char *msg = "AlreadyInUse";
|
||||
REST.set_response_payload(response, msg, strlen(msg));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -463,6 +422,47 @@ separate_finalize_handler()
|
|||
}
|
||||
#endif
|
||||
|
||||
#if REST_RES_PUSHING
|
||||
/*
|
||||
* Example for a periodic resource.
|
||||
* It takes an additional period parameter, which defines the interval to call [name]_periodic_handler().
|
||||
* A default post_handler takes care of subscriptions by managing a list of subscribers to notify.
|
||||
*/
|
||||
PERIODIC_RESOURCE(pushing, METHOD_GET, "debug/push", "title=\"Periodic demo\";rt=\"Observable\"", 5*CLOCK_SECOND);
|
||||
|
||||
void
|
||||
pushing_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
|
||||
|
||||
/* Usually, a CoAP server would response with the resource representation matching the periodic_handler. */
|
||||
const char *msg = "It's periodic!";
|
||||
REST.set_response_payload(response, msg, strlen(msg));
|
||||
|
||||
/* A post_handler that handles subscriptions will be called for periodic resources by the REST framework. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Additionally, a handler function named [resource name]_handler must be implemented for each PERIODIC_RESOURCE.
|
||||
* It will be called by the REST manager process with the defined period.
|
||||
*/
|
||||
int
|
||||
pushing_periodic_handler(resource_t *r)
|
||||
{
|
||||
static uint32_t periodic_i = 0;
|
||||
static char content[16];
|
||||
|
||||
PRINTF("TICK /%s\n", r->url);
|
||||
periodic_i = periodic_i + 1;
|
||||
|
||||
/* Notify the registered observers with the given message type, observe option, and payload. */
|
||||
REST.notify_subscribers(r->url, 1, periodic_i, (uint8_t *)content, snprintf(content, sizeof(content), "TICK %lu", periodic_i));
|
||||
/* |-> implementation-specific, e.g. CoAP: 1=CON and 0=NON notification */
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (PLATFORM_HAS_BUTTON) && REST_RES_EVENT
|
||||
/*
|
||||
* Example for an event resource.
|
||||
|
@ -475,10 +475,9 @@ void
|
|||
event_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
|
||||
{
|
||||
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
|
||||
|
||||
/* Usually, a CoAP server would response with the current resource representation. */
|
||||
const char msg[] = "It's eventful!";
|
||||
REST.set_response_payload(response, (uint8_t *)msg, sizeof(msg)-1);
|
||||
const char *msg = "It's eventful!";
|
||||
REST.set_response_payload(response, (uint8_t *)msg, strlen(msg));
|
||||
|
||||
/* A post_handler that handles subscriptions/observing will be called for periodic resources by the framework. */
|
||||
}
|
||||
|
@ -600,8 +599,8 @@ light_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred
|
|||
else
|
||||
{
|
||||
REST.set_response_status(response, REST.status.UNSUPPORTED_MADIA_TYPE);
|
||||
const char msg[] = "Supporting content-types text/plain, application/xml, and application/json";
|
||||
REST.set_response_payload(response, (uint8_t *)msg, sizeof(msg)-1);
|
||||
const char *msg = "Supporting content-types text/plain, application/xml, and application/json";
|
||||
REST.set_response_payload(response, msg, strlen(msg));
|
||||
}
|
||||
}
|
||||
#endif /* PLATFORM_HAS_LIGHT */
|
||||
|
@ -634,8 +633,8 @@ battery_handler(void* request, void* response, uint8_t *buffer, uint16_t preferr
|
|||
else
|
||||
{
|
||||
REST.set_response_status(response, REST.status.UNSUPPORTED_MADIA_TYPE);
|
||||
const char msg[] = "Supporting content-types text/plain and application/json";
|
||||
REST.set_response_payload(response, (uint8_t *)msg, sizeof(msg)-1);
|
||||
const char *msg = "Supporting content-types text/plain and application/json";
|
||||
REST.set_response_payload(response, msg, strlen(msg));
|
||||
}
|
||||
}
|
||||
#endif /* PLATFORM_HAS_BATTERY */
|
||||
|
@ -680,8 +679,8 @@ PROCESS_THREAD(rest_server_example, ev, data)
|
|||
#if REST_RES_CHUNKS
|
||||
rest_activate_resource(&resource_chunks);
|
||||
#endif
|
||||
#if REST_RES_POLLING
|
||||
rest_activate_periodic_resource(&periodic_resource_polling);
|
||||
#if REST_RES_PUSHING
|
||||
rest_activate_periodic_resource(&periodic_resource_pushing);
|
||||
#endif
|
||||
#if REST_RES_SEPARATE && WITH_COAP > 3
|
||||
rest_set_pre_handler(&resource_separate, coap_separate_handler);
|
||||
|
|
Loading…
Reference in a new issue