From f8e6ad15ca28380212148c3dcc1f60e4e2d78d44 Mon Sep 17 00:00:00 2001 From: Maik Lorenz Date: Thu, 23 Mar 2023 18:17:25 +0000 Subject: [PATCH] Add sensor CoAP resources --- 08-coap-basic/server.c | 77 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/08-coap-basic/server.c b/08-coap-basic/server.c index 3c7e404..1ca4e75 100644 --- a/08-coap-basic/server.c +++ b/08-coap-basic/server.c @@ -24,13 +24,20 @@ static ssize_t _riot_board_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, coap_request_ctx_t *ctx); /* [TASK 2: add the prototype of your resource handler here] */ +static ssize_t _led_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, coap_request_ctx_t *ctx); /* [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 }, }; /* a gcoap listener is a collection of resources. Additionally we can specify @@ -53,9 +60,79 @@ 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, coap_request_ctx_t *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 */ + /* check if there is a payload with a LED status */ + 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]); + } else { + gpio_set(leds[led_number]); + } + 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.