diff --git a/examples/gcoap/README.md b/examples/gcoap/README.md index 47209f5f86..9cd7d3b8b2 100644 --- a/examples/gcoap/README.md +++ b/examples/gcoap/README.md @@ -1,19 +1,29 @@ -# gcoap Example +## About -This application provides command line access to gcoap, a high-level API for CoAP messaging. See the [CoAP spec][1] for background, and the Modules>Networking>CoAP topic in the source documentation for detailed usage instructions and implementation notes. +This application provides command line access to gcoap, a high-level API for +CoAP messaging. See the [CoAP spec][1] for background, and the +Modules>Networking>CoAP topic in the source documentation for detailed usage +instructions and implementation notes. We support two setup options for this example: ### Native networking -Build with the standard `Makefile`. Follow the setup [instructions][2] for the gnrc_networking example. + +Build with the standard `Makefile`. Follow the setup [instructions][2] for +the gnrc_networking example. ### SLIP-based border router -Build with `Makefile.slip`. Follow the setup instructions in README-slip.md, which are based on the [SLIP instructions][3] for the gnrc_border_router example. We also plan to provide or reference the ethos/UHCP instructions, but we don't have it working yet. +Build with `Makefile.slip`. Follow the setup instructions in README-slip.md, +which are based on the [SLIP instructions][3] for the gnrc_border_router +example. We also plan to provide or reference the ethos/UHCP instructions, +but we don't have it working yet. ## Example Use -This example uses gcoap as a server on RIOT native. Then we send a request from a libcoap example client on the Linux host. + +This example uses gcoap as a server on RIOT native. Then we send a request +from a libcoap example client on the Linux host. ### Verify setup from RIOT terminal @@ -26,7 +36,10 @@ Expected response: CoAP open requests: 0 ### Query from libcoap example client -gcoap does not provide any output to the CoAP terminal when it handles a request. We recommend use of Wireshark to see the request and response. You also can add some debug output in the endpoint function callback. + +gcoap does not provide any output to the CoAP terminal when it handles a +request. We recommend use of Wireshark to see the request and response. You +also can add some debug output in the endpoint function callback. ./coap-client -N -m get -p 5683 coap://[fe80::1843:8eff:fe40:4eaa%tap0]/.well-known/core @@ -38,6 +51,7 @@ Example response: The response shows the endpoint registered by the gcoap CLI example. ### Send query to libcoap example server + Start the libcoap example server with the command below. ./coap-server @@ -53,6 +67,19 @@ CLI output: ;title="General Info";ct=0,;if="clock";rt="Ticks";title="Internal Clock";ct=0;obs,;ct=0 +## Other available CoAP implementations and applications + +RIOT also provides package imports and test applications for other CoAP +implementations: + +* [Nanocoap](../nanocoap_server): a very lightweight CoAP server based on the + [nanocoap library](https://github.com/kaspar030/sock/tree/master/nanocoap) + implementation + +* [Microcoap](../../tests/pkg_microcoap): another lightweight CoAP server based + on the [microcoap library](https://github.com/1248/microcoap) implementation + + [1]: https://tools.ietf.org/html/rfc7252 "CoAP spec" [2]: https://github.com/RIOT-OS/RIOT/tree/master/examples/gnrc_networking "instructions" [3]: https://github.com/RIOT-OS/RIOT/tree/master/examples/gnrc_border_router "SLIP instructions" diff --git a/examples/gcoap/gcoap_cli.c b/examples/gcoap/gcoap_cli.c index d8dc5d0845..9a3706851c 100644 --- a/examples/gcoap/gcoap_cli.c +++ b/examples/gcoap/gcoap_cli.c @@ -32,11 +32,14 @@ static void _resp_handler(unsigned req_state, coap_pkt_t* pdu, sock_udp_ep_t *remote); static ssize_t _stats_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len); +static ssize_t _riot_board_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len); /* CoAP resources */ static const coap_resource_t _resources[] = { - { "/cli/stats", COAP_GET, _stats_handler }, + { "/cli/stats", COAP_GET | COAP_PUT, _stats_handler }, + { "/riot/board", COAP_GET, _riot_board_handler }, }; + static gcoap_listener_t _listener = { (coap_resource_t *)&_resources[0], sizeof(_resources) / sizeof(_resources[0]), @@ -88,16 +91,50 @@ static void _resp_handler(unsigned req_state, coap_pkt_t* pdu, } /* - * Server callback for /cli/stats. Returns the count of packets sent by the - * CLI. + * Server callback for /cli/stats. Accepts either a GET or a PUT. + * + * GET: Returns the count of packets sent by the CLI. + * PUT: Updates the count of packets. Rejects an obviously bad request, but + * allows any two byte value for example purposes. Semantically, the only + * valid action is to set the value to 0. */ static ssize_t _stats_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len) +{ + /* read coap method type in packet */ + unsigned method_flag = coap_method2flag(coap_get_code_detail(pdu)); + + switch(method_flag) { + case COAP_GET: + gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT); + + /* write the response buffer with the request count value */ + size_t payload_len = fmt_u16_dec((char *)pdu->payload, req_count); + + return gcoap_finish(pdu, payload_len, COAP_FORMAT_TEXT); + + case COAP_PUT: + /* convert the payload to an integer and update the internal + value */ + if (pdu->payload_len <= 5) { + char payload[6] = { 0 }; + memcpy(payload, (char *)pdu->payload, pdu->payload_len); + req_count = (uint16_t)strtoul(payload, NULL, 10); + return gcoap_response(pdu, buf, len, COAP_CODE_CHANGED); + } + else { + return gcoap_response(pdu, buf, len, COAP_CODE_BAD_REQUEST); + } + } + + return 0; +} + +static ssize_t _riot_board_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len) { gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT); - - size_t payload_len = fmt_u16_dec((char *)pdu->payload, req_count); - - return gcoap_finish(pdu, payload_len, COAP_FORMAT_TEXT); + /* write the RIOT board name in the response buffer */ + memcpy(pdu->payload, RIOT_BOARD, strlen(RIOT_BOARD)); + return gcoap_finish(pdu, strlen(RIOT_BOARD), COAP_FORMAT_TEXT); } static size_t _send(uint8_t *buf, size_t len, char *addr_str, char *port_str) diff --git a/examples/nanocoap_server/README.md b/examples/nanocoap_server/README.md index 103ae98491..d2b373d25d 100644 --- a/examples/nanocoap_server/README.md +++ b/examples/nanocoap_server/README.md @@ -1,5 +1,5 @@ nanocoap server example -======================== +======================= This application is meant to get you started with implementing a CoAP server on RIOT. It uses the GNRC network stack through RIOT's @@ -62,15 +62,34 @@ The link-layer address in this case is "fe80::e42a:1aff:feca:10ec", the only Testing ======= -There are multiple external CoAP clients you can use to test the server on native. + +The CoAP server exposes 3 different resources: + +* `/.well-known/core`: returns the list of available resources on the server. +This is part of the CoAP specifications. It works only with GET requests. +* `/riot/board`: returns the name of the board running the server. It works +only with GET requests. +* `/riot/value`: returns the value of an internal variable of the server. It +works with GET requests and also with PUT and POST requests, which means that +this value can be updated from a client. + +There are multiple external CoAP clients you can use to easily test the server +running on native. libcoap CLI ----------- (replace "fe80::e42a:1aff:feca:10ec" with your link-layer address) +* Get the name of the board: ``` -# coap-client "coap://[fe80::e42a:1aff:feca:10ec%tap0]/riot/board" + # coap-client -m get coap://[fe80::e42a:1aff:feca:10ec%tap0]/riot/board +``` + +* Update and get the internal value: +``` + # coap-client -m put coap://[fe80::e42a:1aff:feca:10ec%tap0]/riot/value -e 42 + # coap-client -m get coap://[fe80::e42a:1aff:feca:10ec%tap0]/riot/value ``` Copper (Firefox Plugin) diff --git a/examples/microcoap_server/Makefile b/tests/pkg_microcoap/Makefile similarity index 60% rename from examples/microcoap_server/Makefile rename to tests/pkg_microcoap/Makefile index f34d00ba64..fce28cfba2 100644 --- a/examples/microcoap_server/Makefile +++ b/tests/pkg_microcoap/Makefile @@ -1,11 +1,5 @@ -# name of your application -APPLICATION = microcoap_server - -# If no BOARD is found in the environment, use this default: -BOARD ?= native - -# This has to be the absolute path to the RIOT base directory: -RIOTBASE ?= $(CURDIR)/../.. +APPLICATION = pkg_microcoap +include ../Makefile.tests_common BOARD_INSUFFICIENT_MEMORY := chronos msb-430 msb-430h nucleo32-f031 nucleo32-f042 \ nucleo32-l031 nucleo-f030 nucleo-l053 pca10000 pca10005 \ @@ -25,7 +19,6 @@ USEMODULE += gnrc_icmpv6_echo USEMODULE += gnrc_sock_udp USEPKG += microcoap -CFLAGS += -DMICROCOAP_DEBUG # include this for printing IP addresses USEMODULE += shell_commands @@ -47,21 +40,4 @@ ifneq (,$(filter $(BOARD),$(LOW_MEMORY_BOARDS))) USEMODULE += prng_minstd endif -# Change this to 0 show compiler invocation lines by default: -QUIET ?= 1 - include $(RIOTBASE)/Makefile.include - -# Set a custom channel if needed -ifneq (,$(filter cc110x,$(USEMODULE))) # radio is cc110x sub-GHz - DEFAULT_CHANNEL ?= 0 - CFLAGS += -DCC110X_DEFAULT_CHANNEL=$(DEFAULT_CHANNEL) -else - ifneq (,$(filter at86rf212b,$(USEMODULE))) # radio is IEEE 802.15.4 sub-GHz - DEFAULT_CHANNEL ?= 5 - CFLAGS += -DIEEE802154_DEFAULT_SUBGHZ_CHANNEL=$(DEFAULT_CHANNEL) - else # radio is IEEE 802.15.4 2.4 GHz - DEFAULT_CHANNEL ?= 26 - CFLAGS += -DIEEE802154_DEFAULT_CHANNEL=$(DEFAULT_CHANNEL) - endif -endif diff --git a/examples/microcoap_server/README.md b/tests/pkg_microcoap/README.md similarity index 96% rename from examples/microcoap_server/README.md rename to tests/pkg_microcoap/README.md index aa5304132a..89be63dc2e 100644 --- a/examples/microcoap_server/README.md +++ b/tests/pkg_microcoap/README.md @@ -1,8 +1,8 @@ -microcoap server example -======================== +microcoap server test +===================== -This application is meant to get you started with implementing a CoAP server on RIOT. -It uses the GNRC network stack through RIOT's conn socket API. +This application is meant to get you started with implementing a CoAP server +on RIOT. It uses the GNRC network stack through RIOT's conn socket API. Usage ===== diff --git a/examples/microcoap_server/coap.c b/tests/pkg_microcoap/coap.c similarity index 100% rename from examples/microcoap_server/coap.c rename to tests/pkg_microcoap/coap.c diff --git a/examples/microcoap_server/main.c b/tests/pkg_microcoap/main.c similarity index 86% rename from examples/microcoap_server/main.c rename to tests/pkg_microcoap/main.c index 38e0d3b9c1..73c58d8763 100644 --- a/examples/microcoap_server/main.c +++ b/tests/pkg_microcoap/main.c @@ -7,11 +7,11 @@ */ /** - * @ingroup examples + * @ingroup tests * @{ * * @file - * @brief CoAP example server application (using microcoap) + * @brief CoAP test server application (using microcoap) * * @author Kaspar Schleiser * @} @@ -28,7 +28,7 @@ extern int _netif_config(int argc, char **argv); int main(void) { - puts("RIOT microcoap example application"); + puts("RIOT microcoap test application"); puts("Waiting for address autoconfiguration..."); xtimer_sleep(3); diff --git a/examples/microcoap_server/microcoap_sock.c b/tests/pkg_microcoap/microcoap_sock.c similarity index 97% rename from examples/microcoap_server/microcoap_sock.c rename to tests/pkg_microcoap/microcoap_sock.c index 3c989de732..d3abdb61e1 100644 --- a/examples/microcoap_server/microcoap_sock.c +++ b/tests/pkg_microcoap/microcoap_sock.c @@ -9,11 +9,7 @@ #include "net/af.h" #include "net/sock/udp.h" -#ifdef MICROCOAP_DEBUG -#define ENABLE_DEBUG (1) -#else #define ENABLE_DEBUG (0) -#endif #include "debug.h" #include "coap.h"