diff --git a/08-coap-basic/server.c b/08-coap-basic/server.c index 6a9e01c..84d3ce4 100644 --- a/08-coap-basic/server.c +++ b/08-coap-basic/server.c @@ -22,15 +22,22 @@ #include "board.h" static ssize_t _riot_board_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx); +static ssize_t _led_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx); /* [TASK 2: add the prototype of your resource handler here] */ /* [TASK 2: declare the array of LEDs here] */ +static const gpio_t leds[] = { + LED0_PIN, + LED1_PIN, + LED2_PIN, +}; /* CoAP resources. Must be sorted by path (ASCII order). */ static const coap_resource_t _resources[] = { /* [TASK 2: register your CoAP resource here] */ - { "/riot/board", COAP_GET, _riot_board_handler, NULL }, + { "/led/", COAP_GET | COAP_PUT | COAP_MATCH_SUBTREE, _led_handler, NULL }, + { "/riot/board", COAP_GET, _riot_board_handler, NULL } }; /* a gcoap listener is a collection of resources. Additionally we can specify @@ -53,9 +60,82 @@ void server_init(void) gcoap_register_listener(&_listener); /* [TASK 2: initialize the GPIOs here] */ + /* initialize LEDs and turn them off */ + for (unsigned i = 0; i < ARRAY_SIZE(leds); i++) { + gpio_init(leds[i], GPIO_OUT); + gpio_set(leds[i]); +} } /* [TASK 2: implement the LED handler here] */ +static ssize_t _led_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx) +{ + (void) ctx; /* argument not used */ + + /* implement your handler here */ + char uri[CONFIG_NANOCOAP_URI_MAX] = { 0 }; + /* get the request path, to know which LED is being requested */ + if (coap_get_uri_path(pdu, (uint8_t *)uri) <= 0) { + /* reply with an error if we could not parse the URI */ + return gcoap_response(pdu, buf, len, COAP_CODE_BAD_REQUEST); + } + + /* find the LED number, the URI should be /led/ */ + char *led_str = uri + strlen("/led/"); + unsigned led_number = atoi(led_str); + + /* verify that the number is valid, respond with an error otherwise */ + if (led_number >= ARRAY_SIZE(leds)) { + return gcoap_response(pdu, buf, len, COAP_CODE_BAD_REQUEST); + } + + ssize_t resp_len = 0; + int led_status = 0; + unsigned method = coap_method2flag(coap_get_code_detail(pdu)); + + switch (method) { + case COAP_PUT: /* on PUT, we set the status of the LED based on the payload */ + if (pdu->payload_len) { + led_status = atoi((char *)pdu->payload); + } else { + return gcoap_response(pdu, buf, len, COAP_CODE_BAD_REQUEST); + } + + if (led_status) { + gpio_clear(leds[led_number]); + puts("LED off"); + } else { + gpio_set(leds[led_number]); + puts("LED on"); + } + return gcoap_response(pdu, buf, len, COAP_CODE_CHANGED); + + case COAP_GET: /* on GET, we return the status of the LED in plain text */ + /* initialize the CoAP response */ + gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT); + + /* set the content format to plain text */ + coap_opt_add_format(pdu, COAP_FORMAT_TEXT); + + /* finish the options indicating that we will include a payload */ + resp_len = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD); + + /* get the current status of the LED, which is the inverted value of the GPIO */ + led_status = !gpio_read(leds[led_number]); + + /* based on the status, write the value of the payload to send */ + if (led_status) { + pdu->payload[0] = '1'; + } else { + pdu->payload[0] = '0'; + } + resp_len++; + return resp_len; + + } + + return 0; +} /* * Server callback for /riot/board. Accepts only GET.