mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
add microcoap example application
This commit is contained in:
parent
7bc5111e87
commit
7daa0c00f9
32
microcoap/Makefile
Normal file
32
microcoap/Makefile
Normal file
@ -0,0 +1,32 @@
|
||||
# name of your application
|
||||
APPLICATION = microcoap-example
|
||||
|
||||
# If no BOARD is found in the environment, use this default:
|
||||
BOARD ?= native
|
||||
|
||||
# if you try to compile this for anything but the boards specified, it will break.
|
||||
# This application has not been verified to work with any other boards-- proceed with caution.
|
||||
BOARD_WHITELIST := native
|
||||
|
||||
# This has to be the absolute path to the RIOT base directory:
|
||||
RIOTBASE ?= $(CURDIR)/../../RIOT
|
||||
|
||||
# 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 += -DRIOT -DMICROCOAP_DEBUG
|
||||
|
||||
# Change this to 0 show compiler invocation lines by default:
|
||||
QUIET ?= 1
|
||||
|
||||
USEPKG=microcoap
|
||||
|
||||
USEMODULE += config
|
||||
USEMODULE += uart0
|
||||
|
||||
USEMODULE += nativenet
|
||||
|
||||
USEMODULE += sixlowpan
|
||||
USEMODULE += udp
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
146
microcoap/README.md
Normal file
146
microcoap/README.md
Normal file
@ -0,0 +1,146 @@
|
||||
Microcoap example
|
||||
============
|
||||
|
||||
This is a small microcoap example application. It provides a server which only
|
||||
answers GET requests to the resource /foo/bar.
|
||||
|
||||
## Setup
|
||||
|
||||
You can use [marz](https://github.com/sgso/marz) to tunnel CoAP messages into the RIOT native thread. This is a bit tricky, so maybe this walkthrough will help:
|
||||
|
||||
0. Build this application.
|
||||
1. Install the copper plugin in your Firefox browser.
|
||||
2. Run `sudo apt-get install bridge-utils`
|
||||
3. In your RIOT directury, run
|
||||
|
||||
./cpu/native/tapsetup.sh create 2
|
||||
|
||||
This will set up two tap devices connected by a bridge. our RIOT application and
|
||||
marz will each listen at one of these devices, and communicate over the bridge.
|
||||
|
||||
3. Open two terminal windows.
|
||||
|
||||
**In window #1**, start the microcoap-example application:
|
||||
|
||||
cd applications/microcoap
|
||||
sudo ./bin/native/microcoap-example.elf tap1 -i 1
|
||||
|
||||
*Make sure to bind it to ``tap1``, since marz will be bound to ``tap0`!*
|
||||
``-i 1`` forces your RIOT instance to match its id to the one specified in marz.config. You should **only** specify this for the **one** RIOT that marz tunnels to. This is sufficient for this example; if you need help running more than one RIOT with marz, please contact the author of this example.
|
||||
|
||||
You should see output similar to this.
|
||||
|
||||
RIOT native uart0 initialized.
|
||||
RIOT native interrupts/signals initialized.
|
||||
LED_GREEN_OFF
|
||||
LED_RED_ON
|
||||
RIOT native board initialized.
|
||||
RIOT native hardware initialization complete.
|
||||
|
||||
kernel_init(): This is RIOT! (Version: 400e-microcoap)
|
||||
kernel_init(): jumping into first task...
|
||||
UART0 thread started.
|
||||
uart0_init() [OK]
|
||||
Initializing transport layer protocol: udp
|
||||
Starting example microcoap server...
|
||||
initializing 6LoWPAN...
|
||||
initializing receive socket...
|
||||
Ready to receive requests.
|
||||
|
||||
Welcome to RIOT
|
||||
|
||||
>
|
||||
|
||||
**In window #2**, first install Python development headers by running
|
||||
|
||||
sudo apt-get install python-dev
|
||||
|
||||
Afterwards you can install and run marz:
|
||||
|
||||
pip install --user Twisted &&
|
||||
pip install --user bidict &&
|
||||
git clone https://github.com/sgso/marz &&
|
||||
cd marz &&
|
||||
./setup.sh
|
||||
|
||||
./marz.py
|
||||
|
||||
You should see output similar to this.
|
||||
|
||||
WARNING: No route found for IPv6 destination :: (no default route?)
|
||||
Listening on UDP ports: [5683, 2222]
|
||||
Listening on tap interface tap0 with MAC address 9a:80:a3:fc:93:18
|
||||
|
||||
## Testing
|
||||
|
||||
The "Copper" firefox plugin is a convenient way to test CoAP endpoints. In the absence of a GUI you can also use Python to send test requests.
|
||||
|
||||
### Using python(3)
|
||||
|
||||
First, make sure Python 3 is installed, clone `aiocoap` into a directory of your choice and then change into it:
|
||||
|
||||
git clone git@github.com:chrysn/aiocoap.git &&
|
||||
cd aiocoap
|
||||
|
||||
Open the `clientGET.py` file and change the line that reads
|
||||
|
||||
request.set_request_uri(<some url>)
|
||||
|
||||
to
|
||||
|
||||
request.set_request_uri('coap://[::1]/foo/bar')
|
||||
|
||||
Then run `clientGET.py`, which should print the following:
|
||||
|
||||
$ ./clientGET.py
|
||||
Result: 2.05 Content
|
||||
b'1337'
|
||||
|
||||
|
||||
### Using the Firefox Copper plugin
|
||||
|
||||
Open Firefox and enter
|
||||
|
||||
coap://[::1]:5683/foo/bar
|
||||
|
||||
Into the browser window. Then, click the big gren ``GET`` button. This should
|
||||
trigger a GET request to our microcoap-example application. Shortly after you've
|
||||
clicked GET, **window #2** should read
|
||||
|
||||
make new connection
|
||||
[UDP6 5683] Received 14 data bytes from ('::1', 54685): Relaying through 54685 to RiotEndpoint(hwaddr=1, ipv6='fe80::ff:fe00:1', port=5683)
|
||||
[TAP] Received 12 data bytes on port 54685: Relaying through 5683 to IP6Endpoint(ipv6='::1', port=54685)
|
||||
|
||||
**window #1** should supply you with detailed information about the received
|
||||
request and the reply our microcoap-example is sending:
|
||||
|
||||
> Received packet: 40 01 0B EC B3 66 6F 6F 03 62 61 72 C1 02
|
||||
content:
|
||||
Header:
|
||||
ver 0x01
|
||||
t 0x01
|
||||
tkl 0x00
|
||||
code 0x01
|
||||
id 0x0BEC
|
||||
Options:
|
||||
0x0B [ 66 6F 6F ]
|
||||
0x0B [ 62 61 72 ]
|
||||
0x17 [ 02 ]
|
||||
Payload:
|
||||
Sending packet: 60 45 0B EC C2 00 00 FF 31 33 33 37
|
||||
content:
|
||||
Header:
|
||||
ver 0x01
|
||||
t 0x01
|
||||
tkl 0x00
|
||||
code 0x45
|
||||
id 0x0BEC
|
||||
Options:
|
||||
0x0C [ 00 00 ]
|
||||
Payload: 31 33 33 37
|
||||
|
||||
And finally, the big grey ``Payload`` box in your Firefox window should read:
|
||||
|
||||
1337
|
||||
|
||||
If this all works, you're good to go! :)
|
53
microcoap/endpoints.c
Normal file
53
microcoap/endpoints.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2015 HAW Hamburg
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief microcoap example server endpoints
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "coap.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#define MAX_RESPONSE_LEN 1500
|
||||
static uint8_t response[MAX_RESPONSE_LEN] = "";
|
||||
|
||||
static const coap_endpoint_path_t path = {2, {"foo", "bar"}};
|
||||
|
||||
void create_response_payload(const uint8_t *buffer)
|
||||
{
|
||||
char *response = "1337";
|
||||
memcpy((void*)buffer, response, strlen(response));
|
||||
}
|
||||
|
||||
/* The handler which handles the path /foo/bar */
|
||||
static int handle_get_response(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo)
|
||||
{
|
||||
DEBUG("[endpoints] %s()\n", __func__);
|
||||
create_response_payload(response);
|
||||
/* NOTE: COAP_RSPCODE_CONTENT only works in a packet answering a GET. */
|
||||
return coap_make_response(scratch, outpkt, response, strlen((char*)response),
|
||||
id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
|
||||
}
|
||||
|
||||
const coap_endpoint_t endpoints[] =
|
||||
{
|
||||
{COAP_METHOD_GET, handle_get_response, &path, "ct=0"},
|
||||
{(coap_method_t)0, NULL, NULL, NULL} /* marks the end of the endpoints array */
|
||||
};
|
143
microcoap/main.c
Normal file
143
microcoap/main.c
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (C) 2015 HAW Hamburg
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief microcoap example server
|
||||
*
|
||||
* @author Lotte Steenbrink <lotte.steenbrink@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "udp.h"
|
||||
#include "net_help.h"
|
||||
#include "net_if.h"
|
||||
#include "periph/cpuid.h"
|
||||
#include "board_uart0.h"
|
||||
#include "thread.h"
|
||||
#include "posix_io.h"
|
||||
#include <coap.h>
|
||||
#include "hashes.h"
|
||||
|
||||
#define ENABLE_DEBUG (1)
|
||||
#include "debug.h"
|
||||
|
||||
#define PORT 5683
|
||||
#define BUFSZ 128
|
||||
|
||||
#define RCV_MSG_Q_SIZE (64)
|
||||
|
||||
static void *_microcoap_server_thread(void *arg);
|
||||
|
||||
msg_t msg_q[RCV_MSG_Q_SIZE];
|
||||
char _rcv_stack_buf[KERNEL_CONF_STACKSIZE_MAIN];
|
||||
|
||||
static ipv6_addr_t prefix;
|
||||
int sock_rcv, if_id;
|
||||
sockaddr6_t sa_rcv;
|
||||
uint8_t buf[BUFSZ];
|
||||
uint8_t scratch_raw[BUFSZ];
|
||||
coap_rw_buffer_t scratch_buf = {scratch_raw, sizeof(scratch_raw)};
|
||||
|
||||
static void _init_tlayer(void);
|
||||
static uint16_t get_hw_addr(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
DEBUG("Starting example microcoap server...\n");
|
||||
|
||||
_init_tlayer();
|
||||
thread_create(_rcv_stack_buf, KERNEL_CONF_STACKSIZE_MAIN, PRIORITY_MAIN, CREATE_STACKTEST, _microcoap_server_thread, NULL ,"_microcoap_server_thread");
|
||||
|
||||
DEBUG("Ready to receive requests.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t get_hw_addr(void)
|
||||
{
|
||||
return sysconfig.id;
|
||||
}
|
||||
|
||||
/* init transport layer & routing stuff*/
|
||||
static void _init_tlayer(void)
|
||||
{
|
||||
msg_init_queue(msg_q, RCV_MSG_Q_SIZE);
|
||||
|
||||
net_if_set_hardware_address(0, get_hw_addr());
|
||||
DEBUG("set hawddr to: %d\n", get_hw_addr());
|
||||
|
||||
printf("initializing 6LoWPAN...\n");
|
||||
|
||||
ipv6_addr_init(&prefix, 0xABCD, 0xEF12, 0, 0, 0, 0, 0, 0);
|
||||
if_id = 0; /* having more than one interface isn't supported anyway */
|
||||
|
||||
sixlowpan_lowpan_init_interface(if_id);
|
||||
}
|
||||
|
||||
static void *_microcoap_server_thread(void *arg)
|
||||
{
|
||||
(void)arg; /* make the compiler shut up about unused variables */
|
||||
|
||||
printf("initializing receive socket...\n");
|
||||
|
||||
sa_rcv = (sockaddr6_t) { .sin6_family = AF_INET6,
|
||||
.sin6_port = HTONS(PORT) };
|
||||
|
||||
sock_rcv = socket_base_socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (-1 == socket_base_bind(sock_rcv, &sa_rcv, sizeof(sa_rcv))) {
|
||||
printf("Error: bind to receive socket failed!\n");
|
||||
socket_base_close(sock_rcv);
|
||||
}
|
||||
|
||||
printf("Ready to receive requests.\n");
|
||||
|
||||
while(1)
|
||||
{
|
||||
int n, rc;
|
||||
socklen_t len = sizeof(sa_rcv);
|
||||
coap_packet_t pkt;
|
||||
|
||||
n = socket_base_recvfrom(sock_rcv, buf, sizeof(buf), 0, &sa_rcv, &len);
|
||||
printf("Received packet: ");
|
||||
coap_dump(buf, n, true);
|
||||
printf("\n");
|
||||
|
||||
if (0 != (rc = coap_parse(&pkt, buf, n)))
|
||||
printf("Bad packet rc=%d\n", rc);
|
||||
else
|
||||
{
|
||||
size_t rsplen = sizeof(buf);
|
||||
coap_packet_t rsppkt;
|
||||
printf("content:\n");
|
||||
coap_dumpPacket(&pkt);
|
||||
coap_handle_req(&scratch_buf, &pkt, &rsppkt);
|
||||
|
||||
if (0 != (rc = coap_build(buf, &rsplen, &rsppkt)))
|
||||
printf("coap_build failed rc=%d\n", rc);
|
||||
else
|
||||
{
|
||||
printf("Sending packet: ");
|
||||
coap_dump(buf, rsplen, true);
|
||||
printf("\n");
|
||||
printf("content:\n");
|
||||
coap_dumpPacket(&rsppkt);
|
||||
socket_base_sendto(sock_rcv, buf, rsplen, 0, &sa_rcv, sizeof(sa_rcv));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
Loading…
Reference in New Issue
Block a user