1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #4287 from kaspar030/add_conn_coap_example

examples: add microcoap, gnrc, conn example
This commit is contained in:
Oleg Hahm 2015-12-04 12:49:12 +01:00
commit 548a63db0d
6 changed files with 360 additions and 0 deletions

View File

@ -0,0 +1,58 @@
# 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)/../..
BOARD_INSUFFICIENT_MEMORY := airfy-beacon chronos msb-430 msb-430h nrf51dongle \
nrf6310 pca10000 pca10005 spark-core \
stm32f0discovery telosb weio wsn430-v1_3b wsn430-v1_4 \
yunjia-nrf51822 z1
# Include packages that pull up and auto-init the link layer.
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
USEMODULE += gnrc_netif_default
USEMODULE += auto_init_gnrc_netif
# Specify the mandatory networking modules for IPv6 and UDP
USEMODULE += gnrc_ipv6_router_default
USEMODULE += gnrc_udp
# Add a routing protocol
USEMODULE += gnrc_rpl
# Additional networking modules that can be dropped if not needed
USEMODULE += gnrc_icmpv6_echo
#
USEMODULE += gnrc_conn_udp
USEPKG += microcoap
CFLAGS += -DMICROCOAP_DEBUG
# include this for printing IP addresses
USEMODULE += shell_commands
# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
#CFLAGS += -DDEVELHELP
# Use different settings when compiling for one of the following (low-memory)
# boards
LOW_MEMORY_BOARDS := nucleo-f334
ifneq (,$(filter $(BOARD),$(LOW_MEMORY_BOARDS)))
$(info Using low-memory configuration for microcoap_server.)
## low-memory tuning values
# lower pktbuf buffer size
CFLAGS += -DGNRC_PKTBUF_SIZE=1000
# disable fib, rpl
DISABLE_MODULE += fib gnrc_rpl
USEMODULE += prng_minstd
endif
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,62 @@
microcoap server example
========================
This application is meant to get you started with impementing a CoAP server on RIOT.
It uses the gnrc network stack through RIOT's conn socket API.
Usage
=====
To try on native, compile with
```
# make all
```
Then run the resulting binary, e.g.,
```
# make term
```
The application is now listening on all it's configured IP addresses.
Now find out it's link\_layer address:
```
$ make term
/home/kaspar/src/riot/examples/microcoap_server/bin/native/microcoap_server.elf tap0
RIOT native interrupts/signals initialized.
LED_GREEN_OFF
LED_RED_ON
RIOT native board initialized.
RIOT native hardware initialization complete.
main(): This is RIOT! (Version: 2015.12-devel-632-g8f451-booze-add_conn_coap_example)
RIOT microcoap example application
Configured network interfaces:
Iface 5 HWaddr: fa:bf:2b:01:9e:a3
MTU:1280 HL:64
Source address length: 6
Link type: wired
inet6 addr: ff02::1/128 scope: local [multicast]
inet6 addr: fe80::f8bf:2bff:fe01:9ea3/64 scope: local
inet6 addr: ff02::1:ff01:9ea3/128 scope: local [multicast]
inet6 addr: ff02::2/128 scope: local [multicast]
Waiting for incoming UDP packet...
```
The link-layer address in this case is "fe80::f8bf:2bff:fe01:9ea3", the only
"scope: local" address set.
Connect using libcoap CLI
=========================
(replace "fe80::f8bf:2bff:fe01:9ea3" with your link-layer address)
```
# coap-client coap://[fe80::f8bf:2bff:fe01:9ea3%tap0]/riot/board
```

View File

@ -0,0 +1,101 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include <coap.h>
#include <string.h>
#define MAX_RESPONSE_LEN 500
static uint8_t response[MAX_RESPONSE_LEN] = { 0 };
static int handle_get_well_known_core(coap_rw_buffer_t *scratch,
const coap_packet_t *inpkt,
coap_packet_t *outpkt,
uint8_t id_hi, uint8_t id_lo);
static int handle_get_riot_board(coap_rw_buffer_t *scratch,
const coap_packet_t *inpkt,
coap_packet_t *outpkt,
uint8_t id_hi, uint8_t id_lo);
static const coap_endpoint_path_t path_well_known_core =
{ 2, { ".well-known", "core" } };
static const coap_endpoint_path_t path_riot_board =
{ 2, { "riot", "board" } };
const coap_endpoint_t endpoints[] =
{
{ COAP_METHOD_GET, handle_get_well_known_core,
&path_well_known_core, "ct=40" },
{ COAP_METHOD_GET, handle_get_riot_board,
&path_riot_board, "ct=0" },
/* marks the end of the endpoints array: */
{ (coap_method_t)0, NULL, NULL, NULL }
};
static int handle_get_well_known_core(coap_rw_buffer_t *scratch,
const coap_packet_t *inpkt, coap_packet_t *outpkt,
uint8_t id_hi, uint8_t id_lo)
{
char *rsp = (char *)response;
int len = sizeof(response);
const coap_endpoint_t *ep = endpoints;
int i;
len--; // Null-terminated string
while (NULL != ep->handler) {
if (NULL == ep->core_attr) {
ep++;
continue;
}
if (0 < strlen(rsp)) {
strncat(rsp, ",", len);
len--;
}
strncat(rsp, "<", len);
len--;
for (i = 0; i < ep->path->count; i++) {
strncat(rsp, "/", len);
len--;
strncat(rsp, ep->path->elems[i], len);
len -= strlen(ep->path->elems[i]);
}
strncat(rsp, ">;", len);
len -= 2;
strncat(rsp, ep->core_attr, len);
len -= strlen(ep->core_attr);
ep++;
}
return coap_make_response(scratch, outpkt, (const uint8_t *)rsp,
strlen(rsp), id_hi, id_lo, &inpkt->tok,
COAP_RSPCODE_CONTENT,
COAP_CONTENTTYPE_APPLICATION_LINKFORMAT);
}
static int handle_get_riot_board(coap_rw_buffer_t *scratch,
const coap_packet_t *inpkt, coap_packet_t *outpkt,
uint8_t id_hi, uint8_t id_lo)
{
const char *riot_name = RIOT_BOARD;
int len = strlen(RIOT_BOARD);
memcpy(response, riot_name, len);
return coap_make_response(scratch, outpkt, (const uint8_t *)response, len,
id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT,
COAP_CONTENTTYPE_TEXT_PLAIN);
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup examples
* @{
*
* @file
* @brief CoAP example server application (using microcoap)
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @}
*/
#include <stdio.h>
#include "msg.h"
#define MAIN_QUEUE_SIZE (8)
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
void microcoap_server_loop(void);
/* import "ifconfig" shell command, used for printing addresses */
extern int _netif_config(int argc, char **argv);
int main(void)
{
puts("RIOT microcoap example application");
/* microcoap_server uses conn which uses gnrc which needs a msg queue */
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
/* print network addresses */
puts("Configured network interfaces:");
_netif_config(0, NULL);
/* start coap server loop */
microcoap_server_loop();
/* should be never reached */
return 0;
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include "net/af.h"
#include "net/conn/udp.h"
#ifdef MICROCOAP_DEBUG
#define ENABLE_DEBUG (1)
#else
#define ENABLE_DEBUG (0)
#endif
#include "debug.h"
#include "coap.h"
static uint8_t _udp_buf[512]; /* udp read buffer (max udp payload size) */
uint8_t scratch_raw[1024]; /* microcoap scratch buffer */
coap_rw_buffer_t scratch_buf = { scratch_raw, sizeof(scratch_raw) };
#define COAP_SERVER_PORT (5683)
/*
* Starts a blocking and never-returning loop dispatching CoAP requests.
*
* When using gnrc, make sure the calling thread has an initialized msg queue.
*/
void microcoap_server_loop(void)
{
uint8_t laddr[16] = { 0 };
uint8_t raddr[16] = { 0 };
size_t raddr_len;
uint16_t rport;
conn_udp_t conn;
int rc = conn_udp_create(&conn, laddr, sizeof(laddr), AF_INET6, COAP_SERVER_PORT);
while (1) {
DEBUG("Waiting for incoming UDP packet...\n");
rc = conn_udp_recvfrom(&conn, (char *)_udp_buf, sizeof(_udp_buf), raddr, &raddr_len, &rport);
if (rc < 0) {
DEBUG("Error in conn_udp_recvfrom(). rc=%u\n", rc);
continue;
}
size_t n = rc;
coap_packet_t pkt;
DEBUG("Received packet: ");
coap_dump(_udp_buf, n, true);
DEBUG("\n");
/* parse UDP packet to CoAP */
if (0 != (rc = coap_parse(&pkt, _udp_buf, n))) {
DEBUG("Bad packet rc=%d\n", rc);
}
else {
coap_packet_t rsppkt;
DEBUG("content:\n");
coap_dumpPacket(&pkt);
/* handle CoAP request */
coap_handle_req(&scratch_buf, &pkt, &rsppkt);
/* build reply */
size_t rsplen = sizeof(_udp_buf);
if ((rc = coap_build(_udp_buf, &rsplen, &rsppkt)) != 0) {
DEBUG("coap_build failed rc=%d\n", rc);
}
else {
DEBUG("Sending packet: ");
coap_dump(_udp_buf, rsplen, true);
DEBUG("\n");
DEBUG("content:\n");
coap_dumpPacket(&rsppkt);
/* send reply via UDP */
rc = conn_udp_sendto(_udp_buf, rsplen, NULL, 0, raddr, raddr_len, AF_INET6, COAP_SERVER_PORT, rport);
if (rc < 0) {
DEBUG("Error sending CoAP reply via udp; %u\n", rc);
}
}
}
}
}

Binary file not shown.